mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
Merge branch 'feature'
This commit is contained in:
commit
1c1a67fe1d
@ -244,6 +244,272 @@ exports[`renders ./components/alert/demo/close-text.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/custom-icon.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-alert ant-alert-success ant-alert-no-icon"
|
||||
data-show="true"
|
||||
>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
showIcon = false
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-alert ant-alert-success"
|
||||
data-show="true"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-smile ant-alert-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
Success Tips
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-alert ant-alert-info"
|
||||
data-show="true"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-smile ant-alert-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
Informational Notes
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-alert ant-alert-warning"
|
||||
data-show="true"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-smile ant-alert-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
Warning
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-alert ant-alert-error"
|
||||
data-show="true"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-smile ant-alert-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
Error
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-alert ant-alert-success ant-alert-with-description"
|
||||
data-show="true"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-smile ant-alert-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
Success Tips
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
>
|
||||
Detailed description and advices about successful copywriting.
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-alert ant-alert-info ant-alert-with-description"
|
||||
data-show="true"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-smile ant-alert-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
Informational Notes
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
>
|
||||
Additional description and informations about copywriting.
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-alert ant-alert-warning ant-alert-with-description"
|
||||
data-show="true"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-smile ant-alert-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
Warning
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
>
|
||||
This is a warning notice about copywriting.
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-alert ant-alert-error ant-alert-with-description"
|
||||
data-show="true"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-smile ant-alert-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
Error
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
>
|
||||
This is an error message about copywriting.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/description.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
|
59
components/alert/demo/custom-icon.md
Normal file
59
components/alert/demo/custom-icon.md
Normal file
@ -0,0 +1,59 @@
|
||||
---
|
||||
order: 12
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 自定义图标
|
||||
en-US: Custom Icon
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可口的图标让信息类型更加醒目。
|
||||
|
||||
## en-US
|
||||
|
||||
Decent icon make information more clear and more friendly.
|
||||
|
||||
````jsx
|
||||
import { Alert, Icon } from 'antd';
|
||||
|
||||
const icon = <Icon type="smile" />;
|
||||
|
||||
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 />
|
||||
<Alert icon={icon} message="Warning" type="warning" showIcon />
|
||||
<Alert icon={icon} message="Error" type="error" showIcon />
|
||||
<Alert
|
||||
icon={icon}
|
||||
message="Success Tips"
|
||||
description="Detailed description and advices about successful copywriting."
|
||||
type="success"
|
||||
showIcon
|
||||
/>
|
||||
<Alert
|
||||
icon={icon}
|
||||
message="Informational Notes"
|
||||
description="Additional description and informations about copywriting."
|
||||
type="info"
|
||||
showIcon
|
||||
/>
|
||||
<Alert
|
||||
icon={icon}
|
||||
message="Warning"
|
||||
description="This is a warning notice about copywriting."
|
||||
type="warning"
|
||||
showIcon
|
||||
/>
|
||||
<Alert
|
||||
icon={icon}
|
||||
message="Error"
|
||||
description="This is an error message about copywriting."
|
||||
type="error"
|
||||
showIcon
|
||||
/>
|
||||
</div>,
|
||||
mountNode);
|
||||
````
|
@ -20,7 +20,7 @@ Alert component for feedback.
|
||||
| closable | Whether Alert can be closed | boolean | - |
|
||||
| closeText | Close text to show | string\|ReactNode | - |
|
||||
| description | Additional content of Alert | string\|ReactNode | - |
|
||||
| iconType | Icon type, effective when `showIcon` is `true` | string | - |
|
||||
| icon | Custom icon, effective when `showIcon` is `true` | ReactNode | - |
|
||||
| message | Content of Alert | string\|ReactNode | - |
|
||||
| showIcon | Whether to show icon | boolean | false, in `banner` mode default is true |
|
||||
| type | Type of Alert styles, options: `success`, `info`, `warning`, `error` | string | `info`, in `banner` mode default is `warning` |
|
||||
|
@ -31,6 +31,7 @@ export interface AlertProps {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
banner?: boolean;
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
|
||||
export default class Alert extends React.Component<AlertProps, any> {
|
||||
@ -64,7 +65,7 @@ export default class Alert extends React.Component<AlertProps, any> {
|
||||
render() {
|
||||
let {
|
||||
closable, description, type, prefixCls = 'ant-alert', message, closeText, showIcon, banner,
|
||||
className = '', style, iconType,
|
||||
className = '', style, iconType, icon,
|
||||
} = this.props;
|
||||
|
||||
// banner模式默认有 Icon
|
||||
@ -73,6 +74,8 @@ export default class Alert extends React.Component<AlertProps, any> {
|
||||
type = banner && type === undefined ? 'warning' : type || 'info';
|
||||
|
||||
let iconTheme: ThemeType = 'filled';
|
||||
// should we give a warning?
|
||||
// warning(!iconType, `The property 'iconType' is deprecated. Use the property 'icon' instead.`);
|
||||
if (!iconType) {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
@ -117,7 +120,19 @@ export default class Alert extends React.Component<AlertProps, any> {
|
||||
|
||||
const dataOrAriaProps = getDataOrAriaProps(this.props);
|
||||
|
||||
const iconNode = <Icon className={`${prefixCls}-icon`} type={iconType} theme={iconTheme} />;
|
||||
const iconNode = icon && (
|
||||
React.isValidElement<{ className?: string }>(icon)
|
||||
? React.cloneElement(
|
||||
icon,
|
||||
{
|
||||
className: classNames({
|
||||
[icon.props.className!]: icon.props.className,
|
||||
[`${prefixCls}-icon`]: true,
|
||||
}),
|
||||
},
|
||||
) : <span className={`${prefixCls}-icon`}>{icon}</span>) || (
|
||||
<Icon className={`${prefixCls}-icon`} type={iconType} theme={iconTheme} />
|
||||
);
|
||||
|
||||
return this.state.closed ? null : (
|
||||
<Animate
|
||||
|
@ -21,7 +21,7 @@ title: Alert
|
||||
| closable | 默认不显示关闭按钮 | boolean | 无 |
|
||||
| closeText | 自定义关闭按钮 | string\|ReactNode | 无 |
|
||||
| description | 警告提示的辅助性文字介绍 | string\|ReactNode | 无 |
|
||||
| iconType | 自定义图标类型,`showIcon` 为 `true` 时有效 | string | - |
|
||||
| icon | 自定义图标,`showIcon` 为 `true` 时有效 | ReactNode | - |
|
||||
| message | 警告提示内容 | string\|ReactNode | 无 |
|
||||
| showIcon | 是否显示辅助图标 | boolean | false,`banner` 模式下默认值为 true |
|
||||
| type | 指定警告提示的样式,有四种选择 `success`、`info`、`warning`、`error` | string | `info`,`banner` 模式下默认值为 `warning` |
|
||||
|
@ -425,15 +425,17 @@ exports[`renders ./components/badge/demo/change.md correctly 1`] = `
|
||||
data-show="true"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
<button
|
||||
aria-checked="true"
|
||||
checked=""
|
||||
class="ant-switch ant-switch-checked"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -372,14 +372,16 @@ exports[`renders ./components/card/demo/inner.md correctly 1`] = `
|
||||
|
||||
exports[`renders ./components/card/demo/loading.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
class="ant-card ant-card-loading ant-card-bordered"
|
||||
style="width:300px;margin-top:16px"
|
||||
|
@ -493,3 +493,63 @@ exports[`renders ./components/cascader/demo/size.md correctly 1`] = `
|
||||
<br />
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/cascader/demo/suffix.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="ant-cascader-picker"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="ant-cascader-picker-label"
|
||||
/>
|
||||
<input
|
||||
autocomplete="off"
|
||||
class="ant-input ant-cascader-input "
|
||||
placeholder="Please select"
|
||||
readonly=""
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<i
|
||||
class="anticon anticon-smile ant-cascader-picker-arrow"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
<span
|
||||
class="ant-cascader-picker"
|
||||
style="margin-top:1rem"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="ant-cascader-picker-label"
|
||||
/>
|
||||
<input
|
||||
autocomplete="off"
|
||||
class="ant-input ant-cascader-input "
|
||||
placeholder="Please select"
|
||||
readonly=""
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-cascader-picker-arrow"
|
||||
>
|
||||
ab
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
65
components/cascader/demo/suffix.md
Normal file
65
components/cascader/demo/suffix.md
Normal file
@ -0,0 +1,65 @@
|
||||
---
|
||||
order: 11
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 后缀图标
|
||||
en-US: Suffix
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
省市区级联。
|
||||
|
||||
## en-US
|
||||
|
||||
Cascade selection box for selecting province/city/district.
|
||||
|
||||
````jsx
|
||||
import { Cascader, Icon } from 'antd';
|
||||
|
||||
const options = [{
|
||||
value: 'zhejiang',
|
||||
label: 'Zhejiang',
|
||||
children: [{
|
||||
value: 'hangzhou',
|
||||
label: 'Hangzhou',
|
||||
children: [{
|
||||
value: 'xihu',
|
||||
label: 'West Lake',
|
||||
}],
|
||||
}],
|
||||
}, {
|
||||
value: 'jiangsu',
|
||||
label: 'Jiangsu',
|
||||
children: [{
|
||||
value: 'nanjing',
|
||||
label: 'Nanjing',
|
||||
children: [{
|
||||
value: 'zhonghuamen',
|
||||
label: 'Zhong Hua Men',
|
||||
}],
|
||||
}],
|
||||
}];
|
||||
|
||||
function onChange(value) {
|
||||
console.log(value);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Cascader
|
||||
suffixIcon={<Icon type="smile" />}
|
||||
options={options}
|
||||
onChange={onChange}
|
||||
placeholder="Please select"
|
||||
/>
|
||||
<Cascader
|
||||
suffixIcon="ab"
|
||||
style={{ marginTop: '1rem' }}
|
||||
options={options}
|
||||
onChange={onChange}
|
||||
placeholder="Please select"
|
||||
/>
|
||||
</div>,
|
||||
mountNode);
|
||||
````
|
@ -40,6 +40,7 @@ Cascade selection box.
|
||||
| showSearch | Whether show search input in single mode. | boolean\|object | false |
|
||||
| size | input size, one of `large` `default` `small` | string | `default` |
|
||||
| style | additional style | string | - |
|
||||
| suffixIcon | The custom suffix icon | ReactNode | - |
|
||||
| value | selected value | string\[] | - |
|
||||
| onChange | callback when finishing cascader select | `(value, selectedOptions) => void` | - |
|
||||
| onPopupVisibleChange | callback when popup shown or hidden | `(value) => void` | - |
|
||||
|
@ -83,6 +83,7 @@ export interface CascaderProps {
|
||||
getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement;
|
||||
popupVisible?: boolean;
|
||||
fieldNames?: FieldNamesType;
|
||||
suffixIcon?: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface CascaderState {
|
||||
@ -341,7 +342,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
const { props, state } = this;
|
||||
const {
|
||||
prefixCls, inputPrefixCls, children, placeholder, size, disabled,
|
||||
className, style, allowClear, showSearch = false, ...otherProps
|
||||
className, style, allowClear, showSearch = false, suffixIcon, ...otherProps
|
||||
} = props;
|
||||
const { value, inputFocused } = state;
|
||||
|
||||
@ -414,6 +415,20 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
dropdownMenuColumnStyle.width = this.input.input.offsetWidth;
|
||||
}
|
||||
|
||||
const inputIcon = suffixIcon && (
|
||||
React.isValidElement<{ className?: string }>(suffixIcon)
|
||||
? React.cloneElement(
|
||||
suffixIcon,
|
||||
{
|
||||
className: classNames({
|
||||
[suffixIcon.props.className!]: suffixIcon.props.className,
|
||||
[`${prefixCls}-picker-arrow`]: true,
|
||||
}),
|
||||
},
|
||||
) : <span className={`${prefixCls}-picker-arrow`}>{suffixIcon}</span>) || (
|
||||
<Icon type="down" className={arrowCls} />
|
||||
);
|
||||
|
||||
const input = children || (
|
||||
<span
|
||||
style={style}
|
||||
@ -438,7 +453,7 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
onChange={showSearch ? this.handleInputChange : undefined}
|
||||
/>
|
||||
{clearIcon}
|
||||
<Icon type="down" className={arrowCls} />
|
||||
{inputIcon}
|
||||
</span>
|
||||
);
|
||||
|
||||
@ -452,9 +467,11 @@ export default class Cascader extends React.Component<CascaderProps, CascaderSta
|
||||
</span>
|
||||
);
|
||||
|
||||
const rest = omit(props, ['inputIcon', 'expandIcon', 'loadingIcon']);
|
||||
|
||||
return (
|
||||
<RcCascader
|
||||
{...props}
|
||||
{...rest}
|
||||
options={options}
|
||||
value={value}
|
||||
popupVisible={state.popupVisible}
|
||||
|
@ -41,6 +41,7 @@ subtitle: 级联选择
|
||||
| showSearch | 在选择框中显示搜索框 | boolean | false |
|
||||
| size | 输入框大小,可选 `large` `default` `small` | string | `default` |
|
||||
| style | 自定义样式 | string | - |
|
||||
| suffixIcon | 自定义的选择框后缀图标 | ReactNode | - |
|
||||
| value | 指定选中项 | string\[] | - |
|
||||
| onChange | 选择完成后的回调 | `(value, selectedOptions) => void` | - |
|
||||
| onPopupVisibleChange | 显示/隐藏浮层的回调 | `(value) => void` | - |
|
||||
|
@ -254,7 +254,7 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
||||
disabledDate, disabledTime,
|
||||
showTime, showToday,
|
||||
ranges, onOk, locale, localeCode, format,
|
||||
dateRender, onCalendarChange,
|
||||
dateRender, onCalendarChange, suffixIcon,
|
||||
} = props;
|
||||
|
||||
fixLocale(value, localeCode);
|
||||
@ -328,6 +328,20 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
||||
/>
|
||||
) : null;
|
||||
|
||||
const inputIcon = suffixIcon && (
|
||||
React.isValidElement<{ className?: string }>(suffixIcon)
|
||||
? React.cloneElement(
|
||||
suffixIcon,
|
||||
{
|
||||
className: classNames({
|
||||
[suffixIcon.props.className!]: suffixIcon.props.className,
|
||||
[`${prefixCls}-picker-icon`]: true,
|
||||
}),
|
||||
},
|
||||
) : <span className={`${prefixCls}-picker-icon`}>{suffixIcon}</span>) || (
|
||||
<Icon type="calendar" className={`${prefixCls}-picker-icon`} />
|
||||
);
|
||||
|
||||
const input = ({ value: inputValue }: { value: any }) => {
|
||||
const start = inputValue[0];
|
||||
const end = inputValue[1];
|
||||
@ -351,7 +365,7 @@ class RangePicker extends React.Component<any, RangePickerState> {
|
||||
tabIndex={-1}
|
||||
/>
|
||||
{clearIcon}
|
||||
<Icon type="calendar" className={`${prefixCls}-picker-icon`}/>
|
||||
{inputIcon}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
@ -87,7 +87,7 @@ class WeekPicker extends React.Component<any, any> {
|
||||
const {
|
||||
prefixCls, className, disabled, pickerClass, popupStyle,
|
||||
pickerInputClass, format, allowClear, locale, localeCode, disabledDate,
|
||||
style, onFocus, onBlur, id,
|
||||
style, onFocus, onBlur, id, suffixIcon,
|
||||
} = this.props;
|
||||
|
||||
const pickerValue = this.state.value;
|
||||
@ -118,7 +118,22 @@ class WeekPicker extends React.Component<any, any> {
|
||||
theme="filled"
|
||||
/>
|
||||
) : null;
|
||||
const input = ({ value }: { value: moment.Moment | undefined }) => {
|
||||
|
||||
const inputIcon = suffixIcon && (
|
||||
React.isValidElement<{ className?: string }>(suffixIcon)
|
||||
? React.cloneElement(
|
||||
suffixIcon,
|
||||
{
|
||||
className: classNames({
|
||||
[suffixIcon.props.className!]: suffixIcon.props.className,
|
||||
[`${prefixCls}-picker-icon`]: true,
|
||||
}),
|
||||
},
|
||||
) : <span className={`${prefixCls}-picker-icon`}>{suffixIcon}</span>) || (
|
||||
<Icon type="calendar" className={`${prefixCls}-picker-icon`} />
|
||||
);
|
||||
|
||||
const input = ({ value }: { value: moment.Moment | undefined }) => {
|
||||
return (
|
||||
<span>
|
||||
<input
|
||||
@ -132,7 +147,7 @@ class WeekPicker extends React.Component<any, any> {
|
||||
onBlur={onBlur}
|
||||
/>
|
||||
{clearIcon}
|
||||
<Icon type="calendar" className={`${prefixCls}-picker-icon`}/>
|
||||
{inputIcon}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
@ -1237,6 +1237,234 @@ exports[`renders ./components/date-picker/demo/start-end.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/date-picker/demo/suffix.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="ant-calendar-picker"
|
||||
>
|
||||
<div>
|
||||
<input
|
||||
class="ant-calendar-picker-input ant-input"
|
||||
placeholder="Select date"
|
||||
readonly=""
|
||||
value=""
|
||||
/>
|
||||
<i
|
||||
class="anticon anticon-smile ant-calendar-picker-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
</span>
|
||||
<br />
|
||||
<span
|
||||
class="ant-calendar-picker"
|
||||
>
|
||||
<div>
|
||||
<input
|
||||
class="ant-calendar-picker-input ant-input"
|
||||
placeholder="Select month"
|
||||
readonly=""
|
||||
value=""
|
||||
/>
|
||||
<i
|
||||
class="anticon anticon-smile ant-calendar-picker-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
</span>
|
||||
<br />
|
||||
<span
|
||||
class="ant-calendar-picker"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="ant-calendar-picker-input ant-input"
|
||||
>
|
||||
<input
|
||||
class="ant-calendar-range-picker-input"
|
||||
placeholder="Start date"
|
||||
readonly=""
|
||||
tabindex="-1"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-calendar-range-picker-separator"
|
||||
>
|
||||
~
|
||||
</span>
|
||||
<input
|
||||
class="ant-calendar-range-picker-input"
|
||||
placeholder="End date"
|
||||
readonly=""
|
||||
tabindex="-1"
|
||||
value=""
|
||||
/>
|
||||
<i
|
||||
class="anticon anticon-smile ant-calendar-picker-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
<span
|
||||
class="ant-calendar-picker"
|
||||
>
|
||||
<span>
|
||||
<input
|
||||
class="ant-calendar-picker-input ant-input"
|
||||
placeholder="Select week"
|
||||
readonly=""
|
||||
value=""
|
||||
/>
|
||||
<i
|
||||
class="anticon anticon-smile ant-calendar-picker-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
<span
|
||||
class="ant-calendar-picker"
|
||||
>
|
||||
<div>
|
||||
<input
|
||||
class="ant-calendar-picker-input ant-input"
|
||||
placeholder="Select date"
|
||||
readonly=""
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-calendar-picker-icon"
|
||||
>
|
||||
ab
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
<br />
|
||||
<span
|
||||
class="ant-calendar-picker"
|
||||
>
|
||||
<div>
|
||||
<input
|
||||
class="ant-calendar-picker-input ant-input"
|
||||
placeholder="Select month"
|
||||
readonly=""
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-calendar-picker-icon"
|
||||
>
|
||||
ab
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
<br />
|
||||
<span
|
||||
class="ant-calendar-picker"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="ant-calendar-picker-input ant-input"
|
||||
>
|
||||
<input
|
||||
class="ant-calendar-range-picker-input"
|
||||
placeholder="Start date"
|
||||
readonly=""
|
||||
tabindex="-1"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-calendar-range-picker-separator"
|
||||
>
|
||||
~
|
||||
</span>
|
||||
<input
|
||||
class="ant-calendar-range-picker-input"
|
||||
placeholder="End date"
|
||||
readonly=""
|
||||
tabindex="-1"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-calendar-picker-icon"
|
||||
>
|
||||
ab
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
<span
|
||||
class="ant-calendar-picker"
|
||||
>
|
||||
<span>
|
||||
<input
|
||||
class="ant-calendar-picker-input ant-input"
|
||||
placeholder="Select week"
|
||||
readonly=""
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-calendar-picker-icon"
|
||||
>
|
||||
ab
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/date-picker/demo/time.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
|
@ -101,7 +101,7 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
||||
render() {
|
||||
const { value, showDate } = this.state;
|
||||
const props = omit(this.props, ['onChange']);
|
||||
const { prefixCls, locale, localeCode } = props;
|
||||
const { prefixCls, locale, localeCode, suffixIcon } = props;
|
||||
|
||||
const placeholder = ('placeholder' in props)
|
||||
? props.placeholder : locale.lang.placeholder;
|
||||
@ -168,6 +168,20 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
||||
/>
|
||||
) : null;
|
||||
|
||||
const inputIcon = suffixIcon && (
|
||||
React.isValidElement<{ className?: string }>(suffixIcon)
|
||||
? React.cloneElement(
|
||||
suffixIcon,
|
||||
{
|
||||
className: classNames({
|
||||
[suffixIcon.props.className!]: suffixIcon.props.className,
|
||||
[`${prefixCls}-picker-icon`]: true,
|
||||
}),
|
||||
},
|
||||
) : <span className={`${prefixCls}-picker-icon`}>{suffixIcon}</span>) || (
|
||||
<Icon type="calendar" className={`${prefixCls}-picker-icon`} />
|
||||
);
|
||||
|
||||
const dataOrAriaProps = getDataOrAriaProps(props);
|
||||
const input = ({ value: inputValue }: { value: moment.Moment | null }) => (
|
||||
<div>
|
||||
@ -181,7 +195,7 @@ export default function createPicker(TheCalendar: React.ComponentClass): any {
|
||||
{...dataOrAriaProps}
|
||||
/>
|
||||
{clearIcon}
|
||||
<Icon type="calendar" className={`${prefixCls}-picker-icon`}/>
|
||||
{inputIcon}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
46
components/date-picker/demo/suffix.md
Normal file
46
components/date-picker/demo/suffix.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
order: 13
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 后缀图标
|
||||
en-US: Suffix
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
最简单的用法,在浮层中可以选择或者输入日期。
|
||||
|
||||
## en-US
|
||||
|
||||
Basic use case. Users can select or input a date in panel.
|
||||
|
||||
````jsx
|
||||
import { DatePicker, Icon } from 'antd';
|
||||
|
||||
const smileIcon = <Icon type="smile" />;
|
||||
const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
|
||||
|
||||
function onChange(date, dateString) {
|
||||
console.log(date, dateString);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker suffixIcon={smileIcon} onChange={onChange} />
|
||||
<br />
|
||||
<MonthPicker suffixIcon={smileIcon} onChange={onChange} placeholder="Select month" />
|
||||
<br />
|
||||
<RangePicker suffixIcon={smileIcon} onChange={onChange} />
|
||||
<br />
|
||||
<WeekPicker suffixIcon={smileIcon} onChange={onChange} placeholder="Select week" />
|
||||
<br />
|
||||
<DatePicker suffixIcon="ab" onChange={onChange} />
|
||||
<br />
|
||||
<MonthPicker suffixIcon="ab" onChange={onChange} placeholder="Select month" />
|
||||
<br />
|
||||
<RangePicker suffixIcon="ab" onChange={onChange} />
|
||||
<br />
|
||||
<WeekPicker suffixIcon="ab" onChange={onChange} placeholder="Select week" />
|
||||
</div>,
|
||||
mountNode);
|
||||
````
|
@ -61,6 +61,7 @@ The following APIs are shared by DatePicker, MonthPicker, RangePicker, WeekPicke
|
||||
| placeholder | placeholder of date input | string\|RangePicker\[] | - |
|
||||
| popupStyle | to customize the style of the popup calendar | object | {} |
|
||||
| size | determine the size of the input box, the height of `large` and `small`, are 40px and 24px respectively, while default size is 32px | string | - |
|
||||
| suffixIcon | The custom suffix icon | ReactNode | - |
|
||||
| style | to customize the style of the input box | object | {} |
|
||||
| onOpenChange | a callback function, can be executed whether the popup calendar is popped up or closed | function(status) | - |
|
||||
| onPanelChange | callback when picker panel mode is changed | function(value, mode) | - |
|
||||
|
@ -62,6 +62,7 @@ moment.locale('zh-cn');
|
||||
| placeholder | 输入框提示文字 | string\|RangePicker\[] | - |
|
||||
| popupStyle | 额外的弹出日历样式 | object | {} |
|
||||
| size | 输入框大小,`large` 高度为 40px,`small` 为 24px,默认是 32px | string | 无 |
|
||||
| suffixIcon | 自定义的选择框后缀图标 | ReactNode | - |
|
||||
| style | 自定义输入框样式 | object | {} |
|
||||
| onOpenChange | 弹出日历和关闭日历的回调 | function(status) | 无 |
|
||||
|
||||
|
@ -10,6 +10,7 @@ export interface PickerProps {
|
||||
disabled?: boolean;
|
||||
allowClear?: boolean;
|
||||
className?: string;
|
||||
suffixIcon?: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
popupStyle?: React.CSSProperties;
|
||||
dropdownClassName?: string;
|
||||
|
@ -2801,17 +2801,19 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-form-item-children"
|
||||
>
|
||||
<span
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
data-__field="[object Object]"
|
||||
data-__meta="[object Object]"
|
||||
id="switch"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
9
components/grid/RowContext.tsx
Normal file
9
components/grid/RowContext.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import createContext, { Context } from 'create-react-context';
|
||||
|
||||
export interface RowContextState {
|
||||
gutter?: number;
|
||||
}
|
||||
|
||||
const RowContext: Context<RowContextState> = createContext({});
|
||||
|
||||
export default RowContext;
|
@ -1,5 +1,23 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Grid renders wrapped Col correctly 1`] = `
|
||||
<div
|
||||
class="ant-row"
|
||||
style="margin-left:-10px;margin-right:-10px"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-col-12"
|
||||
style="padding-left:10px;padding-right:10px"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-12"
|
||||
style="padding-left:10px;padding-right:10px"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Grid should render Col 1`] = `
|
||||
<div
|
||||
class="ant-col-2"
|
||||
|
@ -9,10 +9,24 @@ describe('Grid', () => {
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render Row', () => {
|
||||
const wrapper = render(
|
||||
<Row />
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders wrapped Col correctly', () => {
|
||||
const MyCol = () => <Col span="12" />;
|
||||
const wrapper = render(
|
||||
<Row gutter={20}>
|
||||
<div>
|
||||
<Col span="12" />
|
||||
</div>
|
||||
<MyCol />
|
||||
</Row>
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import RowContext from './RowContext';
|
||||
|
||||
const stringOrNumber = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
|
||||
const objectOrNumber = PropTypes.oneOfType([PropTypes.object, PropTypes.number]);
|
||||
@ -76,6 +77,20 @@ export default class Col extends React.Component<ColProps, {}> {
|
||||
[`${prefixCls}-pull-${pull}`]: pull,
|
||||
}, className, sizeClassObj);
|
||||
|
||||
return <div {...others} className={classes}>{children}</div>;
|
||||
return (
|
||||
<RowContext.Consumer>
|
||||
{({ gutter }) => {
|
||||
let style = others.style;
|
||||
if (gutter as number > 0) {
|
||||
style = {
|
||||
paddingLeft: (gutter as number) / 2,
|
||||
paddingRight: (gutter as number) / 2,
|
||||
...style,
|
||||
};
|
||||
}
|
||||
return <div {...others} style={style} className={classes}>{children}</div>;
|
||||
}}
|
||||
</RowContext.Consumer>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,9 @@ if (typeof window !== 'undefined') {
|
||||
}
|
||||
|
||||
import * as React from 'react';
|
||||
import { Children, cloneElement } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import RowContext from './RowContext';
|
||||
|
||||
export type Breakpoint = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
|
||||
export type BreakpointMap = Partial<Record<Breakpoint, string>>;
|
||||
@ -100,7 +100,7 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
Object.keys(responsiveMap)
|
||||
.map((screen: Breakpoint) => enquire.unregister(responsiveMap[screen]));
|
||||
}
|
||||
getGutter() {
|
||||
getGutter(): number | undefined {
|
||||
const { gutter } = this.props;
|
||||
if (typeof gutter === 'object') {
|
||||
for (let i = 0; i <= responsiveArray.length; i++) {
|
||||
@ -110,7 +110,7 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
}
|
||||
}
|
||||
}
|
||||
return gutter;
|
||||
return gutter as number;
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
@ -129,23 +129,14 @@ export default class Row extends React.Component<RowProps, RowState> {
|
||||
marginRight: (gutter as number) / -2,
|
||||
...style,
|
||||
} : style;
|
||||
const cols = Children.map(children, (col: React.ReactElement<HTMLDivElement>) => {
|
||||
if (!col) {
|
||||
return null;
|
||||
}
|
||||
if (col.props && (gutter as number) > 0) {
|
||||
return cloneElement(col, {
|
||||
style: {
|
||||
paddingLeft: (gutter as number) / 2,
|
||||
paddingRight: (gutter as number) / 2,
|
||||
...col.props.style,
|
||||
},
|
||||
});
|
||||
}
|
||||
return col;
|
||||
});
|
||||
const otherProps = { ...others };
|
||||
delete otherProps.gutter;
|
||||
return <div {...otherProps} className={classes} style={rowStyle}>{cols}</div>;
|
||||
return (
|
||||
<RowContext.Provider value={{ gutter }}>
|
||||
<div {...otherProps} className={classes} style={rowStyle}>
|
||||
{children}
|
||||
</div>
|
||||
</RowContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ export default function create(options: CustomIconOptions = {}): React.SFC<IconP
|
||||
&& !customCache.has(scriptUrl)
|
||||
) {
|
||||
const script = document.createElement('script');
|
||||
script.setAttribute('src', `https:${scriptUrl}`);
|
||||
script.setAttribute('src', scriptUrl);
|
||||
script.setAttribute('data-namespace', scriptUrl);
|
||||
customCache.add(scriptUrl);
|
||||
document.body.appendChild(script);
|
||||
|
@ -22,6 +22,7 @@ When a numeric value needs to be provided.
|
||||
| min | min value | number | -Infinity |
|
||||
| parser | Specifies the value extracted from formatter | function( string): number | - |
|
||||
| precision | precision of input value | number | - |
|
||||
| decilamSeparator | decimal separator | string | - |
|
||||
| size | width of input box | string | - |
|
||||
| step | The number to which the current value is increased or decreased. It can be an integer or decimal. | number\|string | 1 |
|
||||
| value | current value | number | |
|
||||
|
@ -20,6 +20,7 @@ export interface InputNumberProps extends Omit<React.InputHTMLAttributes<HTMLInp
|
||||
size?: 'large' | 'small' | 'default';
|
||||
formatter?: (value: number | string | undefined) => string;
|
||||
parser?: (displayValue: string | undefined) => number;
|
||||
decimalSeparator?: string;
|
||||
placeholder?: string;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
|
@ -25,6 +25,7 @@ title: InputNumber
|
||||
| min | 最小值 | number | -Infinity |
|
||||
| parser | 指定从 formatter 里转换回数字的方式,和 formatter 搭配使用 | function( string): number | - |
|
||||
| precision | 数值精度 | number | - |
|
||||
| decimalSeparator | 小数点 | string | - |
|
||||
| size | 输入框大小 | string | 无 |
|
||||
| step | 每次改变步数,可以为小数 | number\|string | 1 |
|
||||
| value | 当前值 | number | |
|
||||
|
@ -179,10 +179,10 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
@ -214,10 +214,10 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
@ -249,10 +249,10 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
@ -284,10 +284,10 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
@ -411,10 +411,10 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
>
|
||||
<div
|
||||
class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
@ -446,10 +446,10 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
@ -481,10 +481,10 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
@ -516,10 +516,10 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
@ -551,10 +551,10 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
@ -586,10 +586,10 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
|
@ -1711,36 +1711,40 @@ exports[`renders ./components/locale-provider/demo/all.md correctly 1`] = `
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-column-has-filters"
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters"
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Name
|
||||
<i
|
||||
class="anticon anticon-filter ant-dropdown-trigger"
|
||||
title="Filter menu"
|
||||
</div>
|
||||
<i
|
||||
class="anticon anticon-filter ant-dropdown-trigger"
|
||||
title="Filter menu"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="filter"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="filter"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M880.1 154H143.9c-24.5 0-39.8 26.7-27.5 48L349 597.4V838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V597.4L907.7 202c12.2-21.3-3.1-48-27.6-48zM603.4 798H420.6V642h182.9v156zm9.6-236.6l-9.5 16.6h-183l-9.5-16.6L212.7 226h598.6L613 561.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
<path
|
||||
d="M349 838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V642H349v196zm531.1-684H143.9c-24.5 0-39.8 26.7-27.5 48l221.3 376h348.8l221.3-376c12.1-21.3-3.2-48-27.7-48z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Age
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,7 @@ export default {
|
||||
emptyText: 'No data',
|
||||
selectAll: 'Select current page',
|
||||
selectInvert: 'Invert current page',
|
||||
sortTitle: 'Sort',
|
||||
},
|
||||
Modal: {
|
||||
okText: 'OK',
|
||||
|
@ -16,6 +16,7 @@ export default {
|
||||
emptyText: '暂无数据',
|
||||
selectAll: '全选当页',
|
||||
selectInvert: '反选当页',
|
||||
sortTitle: '排序',
|
||||
},
|
||||
Modal: {
|
||||
okText: '确定',
|
||||
|
@ -762,27 +762,31 @@ exports[`renders ./components/menu/demo/sider-current.md correctly 1`] = `
|
||||
|
||||
exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
Change Mode
|
||||
<span
|
||||
class="ant-divider"
|
||||
style="margin:0 1em"
|
||||
/>
|
||||
<span
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
Change Theme
|
||||
<br />
|
||||
<br />
|
||||
@ -959,17 +963,19 @@ exports[`renders ./components/menu/demo/switch-mode.md correctly 1`] = `
|
||||
|
||||
exports[`renders ./components/menu/demo/theme.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
<button
|
||||
aria-checked="true"
|
||||
checked=""
|
||||
class="ant-switch ant-switch-checked"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
>
|
||||
Dark
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<br />
|
||||
<ul
|
||||
|
@ -1,13 +1,14 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import Button from '../button';
|
||||
import { ButtonType } from '../button/button';
|
||||
import { ButtonType, NativeButtonProps } from '../button/button';
|
||||
|
||||
export interface ActionButtonProps {
|
||||
type?: ButtonType;
|
||||
actionFn?: (...args: any[]) => any | PromiseLike<any>;
|
||||
closeModal: Function;
|
||||
autoFocus?: boolean;
|
||||
buttonProps?: NativeButtonProps;
|
||||
}
|
||||
|
||||
export interface ActionButtonState {
|
||||
@ -61,10 +62,10 @@ export default class ActionButton extends React.Component<ActionButtonProps, Act
|
||||
}
|
||||
|
||||
render() {
|
||||
const { type, children } = this.props;
|
||||
const { type, children, buttonProps } = this.props;
|
||||
const loading = this.state.loading;
|
||||
return (
|
||||
<Button type={type} onClick={this.onClick} loading={loading}>
|
||||
<Button type={type} onClick={this.onClick} loading={loading} {...buttonProps}>
|
||||
{children}
|
||||
</Button>
|
||||
);
|
||||
|
@ -66,6 +66,8 @@ export interface ModalFuncProps {
|
||||
content?: React.ReactNode;
|
||||
onOk?: (...args: any[]) => any | PromiseLike<any>;
|
||||
onCancel?: (...args: any[]) => any | PromiseLike<any>;
|
||||
okButtonProps?: NativeButtonProps;
|
||||
cancelButtonProps?: NativeButtonProps;
|
||||
centered?: boolean;
|
||||
width?: string | number;
|
||||
iconClassName?: string;
|
||||
@ -80,6 +82,7 @@ export interface ModalFuncProps {
|
||||
type?: string;
|
||||
keyboard?: boolean;
|
||||
getContainer?: (instance: React.ReactInstance) => HTMLElement;
|
||||
autoFocusButton?: null | 'ok' | 'cancel';
|
||||
}
|
||||
|
||||
export type ModalFunc = (props: ModalFuncProps) => {
|
||||
|
@ -84,6 +84,13 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
expect($$('.ant-btn')[0].innerHTML).toContain('OK');
|
||||
});
|
||||
|
||||
it('allows extra props on buttons', () => {
|
||||
open({ okButtonProps: { disabled: true }, cancelButtonProps: { 'data-test': 'baz' } });
|
||||
expect($$('.ant-btn')).toHaveLength(2);
|
||||
expect($$('.ant-btn')[0].attributes['data-test'].value).toBe('baz');
|
||||
expect($$('.ant-btn')[1].disabled).toBe(true);
|
||||
});
|
||||
|
||||
it('trigger onCancel once when click on cancel button', () => {
|
||||
jest.useFakeTimers();
|
||||
['info', 'success', 'warning', 'error'].forEach((type) => {
|
||||
|
@ -9,12 +9,13 @@ import { getConfirmLocale } from './locale';
|
||||
interface ConfirmDialogProps extends ModalFuncProps {
|
||||
afterClose?: () => void;
|
||||
close: (...args: any[]) => void;
|
||||
autoFocusButton?: null | 'ok' | 'cancel';
|
||||
}
|
||||
|
||||
const IS_REACT_16 = !!ReactDOM.createPortal;
|
||||
|
||||
const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
const { onCancel, onOk, close, zIndex, afterClose, visible, keyboard, centered, getContainer } = props;
|
||||
const { onCancel, onOk, close, zIndex, afterClose, visible, keyboard, centered, getContainer, okButtonProps, cancelButtonProps } = props;
|
||||
const iconType = props.iconType || 'question-circle';
|
||||
const okType = props.okType || 'primary';
|
||||
const prefixCls = props.prefixCls || 'ant-confirm';
|
||||
@ -28,6 +29,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
const okText = props.okText ||
|
||||
(okCancel ? runtimeLocale.okText : runtimeLocale.justOkText);
|
||||
const cancelText = props.cancelText || runtimeLocale.cancelText;
|
||||
const autoFocusButton = props.autoFocusButton === null ? false : props.autoFocusButton || 'ok';
|
||||
|
||||
const classString = classNames(
|
||||
prefixCls,
|
||||
@ -36,7 +38,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
);
|
||||
|
||||
const cancelButton = okCancel && (
|
||||
<ActionButton actionFn={onCancel} closeModal={close}>
|
||||
<ActionButton actionFn={onCancel} closeModal={close} autoFocus={autoFocusButton === 'cancel'} buttonProps={cancelButtonProps}>
|
||||
{cancelText}
|
||||
</ActionButton>
|
||||
);
|
||||
@ -68,7 +70,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
</div>
|
||||
<div className={`${prefixCls}-btns`}>
|
||||
{cancelButton}
|
||||
<ActionButton type={okType} actionFn={onOk} closeModal={close} autoFocus>
|
||||
<ActionButton type={okType} actionFn={onOk} closeModal={close} autoFocus={autoFocusButton === 'ok'} buttonProps={okButtonProps}>
|
||||
{okText}
|
||||
</ActionButton>
|
||||
</div>
|
||||
|
@ -47,6 +47,28 @@ function showDeleteConfirm() {
|
||||
});
|
||||
}
|
||||
|
||||
function showPropsConfirm() {
|
||||
confirm({
|
||||
title: 'Are you sure delete this task?',
|
||||
content: 'Some descriptions',
|
||||
okText: 'Yes',
|
||||
okType: 'danger',
|
||||
okButtonProps: {
|
||||
disabled: true,
|
||||
},
|
||||
cancelButtonProps: {
|
||||
loading: true,
|
||||
},
|
||||
cancelText: 'No',
|
||||
onOk() {
|
||||
console.log('OK');
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Button onClick={showConfirm}>
|
||||
@ -55,6 +77,9 @@ ReactDOM.render(
|
||||
<Button onClick={showDeleteConfirm} type="dashed">
|
||||
Delete
|
||||
</Button>
|
||||
<Button onClick={showPropsConfirm} type="dashed">
|
||||
With extra props
|
||||
</Button>
|
||||
</div>,
|
||||
mountNode);
|
||||
````
|
||||
|
@ -62,6 +62,7 @@ The properties of the object are follows:
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| autoFocusButton | Specify which button to autofocus | null\|string: `ok` `cancel` | `ok` |
|
||||
| cancelText | Text of the Cancel button | string | `Cancel` |
|
||||
| centered | Centered Modal | Boolean | `false` |
|
||||
| className | className of container | string | - |
|
||||
@ -71,6 +72,8 @@ The properties of the object are follows:
|
||||
| maskClosable | Whether to close the modal dialog when the mask (area outside the modal) is clicked | Boolean | `false` |
|
||||
| okText | Text of the OK button | string | `OK` |
|
||||
| okType | Button `type` of the OK button | string | `primary` |
|
||||
| okButtonProps | The ok button props | [ButtonProps](/components/button) | - |
|
||||
| cancelButtonProps | The cancel button props | [ButtonProps](/components/button) | - |
|
||||
| title | Title | string\|ReactNode | - |
|
||||
| width | Width of the modal dialog | string\|number | 416 |
|
||||
| zIndex | The `z-index` of the Modal | Number | 1000 |
|
||||
|
@ -61,6 +61,7 @@ title: Modal
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| autoFocusButton | 指定自动获得焦点的按钮 | null\|string: `ok` `cancel` | `ok` |
|
||||
| cancelText | 取消按钮文字 | string | 取消 |
|
||||
| centered | 垂直居中展示 Modal | Boolean | `false` |
|
||||
| className | 容器类名 | string | - |
|
||||
@ -69,6 +70,8 @@ title: Modal
|
||||
| maskClosable | 点击蒙层是否允许关闭 | Boolean | `false` |
|
||||
| okText | 确认按钮文字 | string | 确定 |
|
||||
| okType | 确认按钮类型 | string | primary |
|
||||
| okButtonProps | ok 按钮 props | [ButtonProps](/components/button) | - |
|
||||
| cancelButtonProps | cancel 按钮 props | [ButtonProps](/components/button) | - |
|
||||
| title | 标题 | string\|ReactNode | 无 |
|
||||
| width | 宽度 | string\|number | 416 |
|
||||
| zIndex | 设置 Modal 的 `z-index` | Number | 1000 |
|
||||
|
@ -18,14 +18,16 @@ exports[`renders ./components/popconfirm/demo/dynamic-trigger.md correctly 1`] =
|
||||
<br />
|
||||
<br />
|
||||
Whether directly execute:
|
||||
<span
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch ant-switch-checked"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
@ -974,6 +974,109 @@ exports[`renders ./components/select/demo/size.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/select/demo/suffix.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-select ant-select-enabled"
|
||||
style="width:120px"
|
||||
>
|
||||
<div
|
||||
aria-autocomplete="list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-select-selection
|
||||
ant-select-selection--single"
|
||||
role="combobox"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selection__rendered"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selection-selected-value"
|
||||
style="display:block;opacity:1"
|
||||
title="Lucy"
|
||||
>
|
||||
Lucy
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="on"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-smile"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-select ant-select-disabled"
|
||||
style="width:120px"
|
||||
>
|
||||
<div
|
||||
aria-autocomplete="list"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
class="ant-select-selection
|
||||
ant-select-selection--single"
|
||||
role="combobox"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selection__rendered"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selection-selected-value"
|
||||
style="display:block;opacity:1"
|
||||
title="Lucy"
|
||||
>
|
||||
Lucy
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="on"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-meh"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="meh"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 565H360c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h304c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/select/demo/tags.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-select ant-select-enabled"
|
||||
|
41
components/select/demo/suffix.md
Normal file
41
components/select/demo/suffix.md
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
order: 20
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 后缀图标
|
||||
en-US: Suffix
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
基本使用。
|
||||
|
||||
## en-US
|
||||
|
||||
Basic Usage.
|
||||
|
||||
````jsx
|
||||
import { Select, Icon } from 'antd';
|
||||
|
||||
const smileIcon = <Icon type="smile" />;
|
||||
const mehIcon = <Icon type="meh" />;
|
||||
const Option = Select.Option;
|
||||
|
||||
function handleChange(value) {
|
||||
console.log(`selected ${value}`);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Select suffixIcon={smileIcon} defaultValue="lucy" style={{ width: 120 }} onChange={handleChange}>
|
||||
<Option value="jack">Jack</Option>
|
||||
<Option value="lucy">Lucy</Option>
|
||||
<Option value="disabled" disabled>Disabled</Option>
|
||||
<Option value="Yiminghe">yiminghe</Option>
|
||||
</Select>
|
||||
<Select suffixIcon={mehIcon} defaultValue="lucy" style={{ width: 120 }} disabled>
|
||||
<Option value="lucy">Lucy</Option>
|
||||
</Select>
|
||||
</div>,
|
||||
mountNode);
|
||||
````
|
@ -46,6 +46,7 @@ Select component to select value from options.
|
||||
| showArrow | Whether to show the drop-down arrow | boolean | true |
|
||||
| showSearch | Whether show search input in single mode. | boolean | false |
|
||||
| size | Size of Select input. `default` `large` `small` | string | default |
|
||||
| suffixIcon | The custom suffix icon | ReactNode | - |
|
||||
| tokenSeparators | Separator used to tokenize on tag/multiple mode | string\[] | |
|
||||
| value | Current selected option. | string\|number\|string\[]\|number\[] | - |
|
||||
| onBlur | Called when blur | function | - |
|
||||
|
@ -4,6 +4,7 @@ import RcSelect, { Option, OptGroup } from 'rc-select';
|
||||
import classNames from 'classnames';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import defaultLocale from '../locale-provider/default';
|
||||
import omit from 'omit.js';
|
||||
import warning from 'warning';
|
||||
import Icon from '../icon';
|
||||
|
||||
@ -65,6 +66,7 @@ export interface SelectProps extends AbstractSelectProps {
|
||||
tokenSeparators?: string[];
|
||||
getInputElement?: () => React.ReactElement<any>;
|
||||
autoFocus?: boolean;
|
||||
suffixIcon?: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface OptionProps {
|
||||
@ -157,8 +159,11 @@ export default class Select extends React.Component<SelectProps, {}> {
|
||||
className = '',
|
||||
size,
|
||||
mode,
|
||||
suffixIcon,
|
||||
...restProps
|
||||
} = this.props;
|
||||
const rest = omit(restProps, ['inputIcon', 'removeIcon', 'clearIcon']);
|
||||
|
||||
const cls = classNames({
|
||||
[`${prefixCls}-lg`]: size === 'large',
|
||||
[`${prefixCls}-sm`]: size === 'small',
|
||||
@ -176,9 +181,11 @@ export default class Select extends React.Component<SelectProps, {}> {
|
||||
combobox: this.isCombobox(),
|
||||
};
|
||||
|
||||
const inputIcon = (
|
||||
<Icon type="down" className={`${prefixCls}-arrow-icon`} />
|
||||
);
|
||||
const inputIcon = suffixIcon && (
|
||||
React.isValidElement<{ className?: string }>(suffixIcon)
|
||||
? React.cloneElement(suffixIcon) : suffixIcon) || (
|
||||
<Icon type="down" className={`${prefixCls}-arrow-icon`} />
|
||||
);
|
||||
|
||||
const removeIcon = (
|
||||
<Icon type="close" className={`${prefixCls}-remove-icon`} />
|
||||
@ -198,7 +205,7 @@ export default class Select extends React.Component<SelectProps, {}> {
|
||||
removeIcon={removeIcon}
|
||||
clearIcon={clearIcon}
|
||||
menuItemSelectedIcon={menuItemSelectedIcon}
|
||||
{...restProps}
|
||||
{...rest}
|
||||
{...modeConfig}
|
||||
prefixCls={prefixCls}
|
||||
className={cls}
|
||||
|
@ -47,6 +47,7 @@ title: Select
|
||||
| showArrow | 是否显示下拉小箭头 | boolean | true |
|
||||
| showSearch | 使单选模式可搜索 | boolean | false |
|
||||
| size | 选择框大小,可选 `large` `small` | string | default |
|
||||
| suffixIcon | 自定义的选择框后缀图标 | ReactNode | - |
|
||||
| tokenSeparators | 在 tags 和 multiple 模式下自动分词的分隔符 | string\[] | |
|
||||
| value | 指定当前选中的条目 | string\|string\[]\|number\|number\[] | - |
|
||||
| onBlur | 失去焦点的时回调 | function | - |
|
||||
|
@ -103,14 +103,16 @@ exports[`renders ./components/skeleton/demo/complex.md correctly 1`] = `
|
||||
|
||||
exports[`renders ./components/skeleton/demo/list.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
class="ant-list ant-list-vertical ant-list-lg ant-list-split"
|
||||
>
|
||||
|
@ -67,14 +67,16 @@ exports[`renders ./components/slider/demo/basic.md correctly 1`] = `
|
||||
/>
|
||||
</div>
|
||||
Disabled:
|
||||
<span
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch-small ant-switch"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
@ -69,14 +69,16 @@ exports[`renders ./components/spin/demo/delayAndDebounce.md correctly 1`] = `
|
||||
style="margin-top:16px"
|
||||
>
|
||||
Loading state:
|
||||
<span
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@ -129,14 +131,16 @@ exports[`renders ./components/spin/demo/nested.md correctly 1`] = `
|
||||
style="margin-top:16px"
|
||||
>
|
||||
Loading state:
|
||||
<span
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -344,6 +344,7 @@
|
||||
@table-header-bg: @background-color-light;
|
||||
@table-header-color: @heading-color;
|
||||
@table-header-sort-bg: @background-color-base;
|
||||
@table-body-sort-bg: rgba(0, 0, 0, .01);
|
||||
@table-row-hover-bg: @primary-1;
|
||||
@table-selected-row-bg: #fafafa;
|
||||
@table-expanded-row-bg: #fbfbfb;
|
||||
@ -490,6 +491,10 @@
|
||||
// ---
|
||||
@skeleton-color: #f2f2f2;
|
||||
|
||||
// Transfer
|
||||
// ---
|
||||
@transfer-disabled-bg: @disabled-bg;
|
||||
|
||||
// Message
|
||||
// ---
|
||||
@message-notice-content-padding: 10px 16px;
|
||||
|
@ -1,26 +1,31 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/switch/demo/basic.md correctly 1`] = `
|
||||
<span
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch ant-switch-checked"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/switch/demo/disabled.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch ant-switch-checked ant-switch-disabled"
|
||||
tabindex="-1"
|
||||
disabled=""
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
@ -35,9 +40,11 @@ exports[`renders ./components/switch/demo/disabled.md correctly 1`] = `
|
||||
|
||||
exports[`renders ./components/switch/demo/loading.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch-loading ant-switch ant-switch-checked"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-loading ant-switch-loading-icon"
|
||||
@ -59,11 +66,13 @@ exports[`renders ./components/switch/demo/loading.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<span
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch-small ant-switch-loading ant-switch"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-loading ant-switch-loading-icon"
|
||||
@ -85,59 +94,69 @@ exports[`renders ./components/switch/demo/loading.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/switch/demo/size.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch ant-switch-checked"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<span
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch-small ant-switch ant-switch-checked"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/switch/demo/text.md correctly 1`] = `
|
||||
<div>
|
||||
<span
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch ant-switch-checked"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
>
|
||||
开
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<span
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
>
|
||||
0
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
<br />
|
||||
<span
|
||||
<button
|
||||
aria-checked="true"
|
||||
class="ant-switch ant-switch-checked"
|
||||
tabindex="0"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
@ -160,6 +179,6 @@ exports[`renders ./components/switch/demo/text.md correctly 1`] = `
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
@ -33,6 +33,7 @@ import {
|
||||
TableSelectWay,
|
||||
TableRowSelection,
|
||||
PaginationConfig,
|
||||
PrepareParamsArgumentsReturn,
|
||||
} from './interface';
|
||||
import { RadioChangeEvent } from '../radio';
|
||||
import { CheckboxChangeEvent } from '../checkbox';
|
||||
@ -340,8 +341,8 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
};
|
||||
}
|
||||
|
||||
getSorterFn() {
|
||||
const { sortOrder, sortColumn } = this.state;
|
||||
getSorterFn(state: TableState<T>) {
|
||||
const { sortOrder, sortColumn } = state || this.state;
|
||||
if (!sortOrder || !sortColumn ||
|
||||
typeof sortColumn.sorter !== 'function') {
|
||||
return;
|
||||
@ -356,24 +357,24 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
};
|
||||
}
|
||||
|
||||
toggleSortOrder(order: 'ascend'|'descend', column: ColumnProps<T>) {
|
||||
let { sortColumn, sortOrder } = this.state;
|
||||
toggleSortOrder(column: ColumnProps<T>) {
|
||||
const { sortOrder, sortColumn } = this.state;
|
||||
// 只同时允许一列进行排序,否则会导致排序顺序的逻辑问题
|
||||
let isSortColumn = this.isSortColumn(column);
|
||||
if (!isSortColumn) { // 当前列未排序
|
||||
sortOrder = order;
|
||||
sortColumn = column;
|
||||
} else { // 当前列已排序
|
||||
if (sortOrder === order) { // 切换为未排序状态
|
||||
sortOrder = undefined;
|
||||
sortColumn = null;
|
||||
} else { // 切换为排序状态
|
||||
sortOrder = order;
|
||||
}
|
||||
let newSortOrder: 'descend' | 'ascend' | undefined;
|
||||
// 切换另一列时,丢弃 sortOrder 的状态
|
||||
const oldSortOrder = sortColumn === column ? sortOrder : undefined;
|
||||
// 切换排序状态,按照降序/升序/不排序的顺序
|
||||
if (!oldSortOrder) {
|
||||
newSortOrder = 'descend';
|
||||
} else if (oldSortOrder === 'descend') {
|
||||
newSortOrder = 'ascend';
|
||||
} else {
|
||||
newSortOrder = undefined;
|
||||
}
|
||||
|
||||
const newState = {
|
||||
sortOrder,
|
||||
sortColumn,
|
||||
sortOrder: newSortOrder,
|
||||
sortColumn: newSortOrder ? column : null,
|
||||
};
|
||||
|
||||
// Controlled
|
||||
@ -381,7 +382,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
this.setState(newState);
|
||||
}
|
||||
|
||||
const onChange = this.props.onChange;
|
||||
const { onChange } = this.props;
|
||||
if (onChange) {
|
||||
onChange.apply(null, this.prepareParamsArguments({
|
||||
...this.state,
|
||||
@ -444,7 +445,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
this.store.setState({
|
||||
selectionDirty: false,
|
||||
});
|
||||
const onChange = this.props.onChange;
|
||||
const { onChange } = this.props;
|
||||
if (onChange) {
|
||||
onChange.apply(null, this.prepareParamsArguments({
|
||||
...this.state,
|
||||
@ -462,7 +463,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
const defaultSelection = this.store.getState().selectionDirty ? [] : this.getDefaultSelection();
|
||||
let selectedRowKeys = this.store.getState().selectedRowKeys.concat(defaultSelection);
|
||||
let key = this.getRecordKey(record, rowIndex);
|
||||
const pivot = this.state.pivot;
|
||||
const { pivot } = this.state;
|
||||
const rows = this.getFlatCurrentPageData();
|
||||
let realIndex = rowIndex;
|
||||
if (this.props.expandedRowRender) {
|
||||
@ -639,7 +640,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
selectionDirty: false,
|
||||
});
|
||||
|
||||
const onChange = this.props.onChange;
|
||||
const { onChange } = this.props;
|
||||
if (onChange) {
|
||||
onChange.apply(null, this.prepareParamsArguments({
|
||||
...this.state,
|
||||
@ -674,7 +675,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
}
|
||||
|
||||
getRecordKey = (record: T, index: number) => {
|
||||
const rowKey = this.props.rowKey;
|
||||
const { rowKey } = this.props;
|
||||
const recordKey = (typeof rowKey === 'function') ?
|
||||
rowKey(record, index) : (record as any)[rowKey as string];
|
||||
warning(recordKey !== undefined,
|
||||
@ -747,7 +748,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
}
|
||||
|
||||
getMaxCurrent(total: number) {
|
||||
const { current, pageSize } = this.state.pagination;
|
||||
const { pagination: { current, pageSize } } = this.state;
|
||||
if ((current! - 1) * pageSize! >= total) {
|
||||
return Math.floor((total - 1) / pageSize!) + 1;
|
||||
}
|
||||
@ -765,11 +766,11 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
renderColumnsDropdown(columns: ColumnProps<T>[], locale: TableLocale) {
|
||||
const { prefixCls, dropdownPrefixCls } = this.props;
|
||||
const { sortOrder } = this.state;
|
||||
return treeMap(columns, (originColumn, i) => {
|
||||
let column = { ...originColumn };
|
||||
let key = this.getColumnKey(column, i) as string;
|
||||
return treeMap(columns, (column, i) => {
|
||||
const key = this.getColumnKey(column, i) as string;
|
||||
let filterDropdown;
|
||||
let sortButton;
|
||||
const isSortColumn = this.isSortColumn(column);
|
||||
if ((column.filters && column.filters.length > 0) || column.filterDropdown) {
|
||||
let colFilters = this.state.filters[key] || [];
|
||||
filterDropdown = (
|
||||
@ -781,55 +782,66 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
prefixCls={`${prefixCls}-filter`}
|
||||
dropdownPrefixCls={dropdownPrefixCls || 'ant-dropdown'}
|
||||
getPopupContainer={this.getPopupContainer}
|
||||
key="filter-dropdown"
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (column.sorter) {
|
||||
let isSortColumn = this.isSortColumn(column);
|
||||
if (isSortColumn) {
|
||||
column.className = classNames(column.className, {
|
||||
[`${prefixCls}-column-sort`]: sortOrder,
|
||||
});
|
||||
}
|
||||
const isAscend = isSortColumn && sortOrder === 'ascend';
|
||||
const isDescend = isSortColumn && sortOrder === 'descend';
|
||||
sortButton = (
|
||||
<div className={`${prefixCls}-column-sorter`}>
|
||||
<span
|
||||
<div className={`${prefixCls}-column-sorter`} key="sorter">
|
||||
<Icon
|
||||
className={`${prefixCls}-column-sorter-up ${isAscend ? 'on' : 'off'}`}
|
||||
title="↑"
|
||||
onClick={() => this.toggleSortOrder('ascend', column)}
|
||||
>
|
||||
<Icon type="caret-up" />
|
||||
</span>
|
||||
<span
|
||||
type="caret-up"
|
||||
theme="filled"
|
||||
/>
|
||||
<Icon
|
||||
className={`${prefixCls}-column-sorter-down ${isDescend ? 'on' : 'off'}`}
|
||||
title="↓"
|
||||
onClick={() => this.toggleSortOrder('descend', column)}
|
||||
>
|
||||
<Icon type="caret-down" />
|
||||
</span>
|
||||
type="caret-down"
|
||||
theme="filled"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
column.title = (
|
||||
<span key={key}>
|
||||
{column.title}
|
||||
{sortButton}
|
||||
{filterDropdown}
|
||||
</span>
|
||||
);
|
||||
|
||||
if (sortButton || filterDropdown) {
|
||||
column.className = classNames(`${prefixCls}-column-has-filters`, column.className);
|
||||
}
|
||||
|
||||
return column;
|
||||
return {
|
||||
...column,
|
||||
className: classNames(column.className, {
|
||||
[`${prefixCls}-column-has-actions`]: sortButton || filterDropdown,
|
||||
[`${prefixCls}-column-has-filters`]: filterDropdown,
|
||||
[`${prefixCls}-column-has-sorters`]: sortButton,
|
||||
[`${prefixCls}-column-sort`]: isSortColumn && sortOrder,
|
||||
}),
|
||||
title: [
|
||||
<div
|
||||
key="title"
|
||||
title={locale.sortTitle}
|
||||
className={sortButton ? `${prefixCls}-column-sorters` : undefined}
|
||||
onClick={() => this.toggleSortOrder(column)}
|
||||
>
|
||||
{this.renderColumnTitle(column.title)}
|
||||
{sortButton}
|
||||
</div>,
|
||||
filterDropdown,
|
||||
],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
renderColumnTitle(title: ColumnProps<T>['title']) {
|
||||
const { filters, sortOrder } = this.state;
|
||||
// https://github.com/ant-design/ant-design/issues/11246#issuecomment-405009167
|
||||
if (typeof title === 'function') {
|
||||
return title({
|
||||
filters,
|
||||
sortOrder,
|
||||
});
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
handleShowSizeChange = (current: number, pageSize: number) => {
|
||||
const pagination = this.state.pagination;
|
||||
const { pagination } = this.state;
|
||||
pagination.onShowSizeChange!(current, pageSize);
|
||||
const nextPagination = {
|
||||
...pagination,
|
||||
@ -838,7 +850,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
};
|
||||
this.setState({ pagination: nextPagination });
|
||||
|
||||
const onChange = this.props.onChange;
|
||||
const { onChange } = this.props;
|
||||
if (onChange) {
|
||||
onChange.apply(null, this.prepareParamsArguments({
|
||||
...this.state,
|
||||
@ -876,7 +888,7 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
}
|
||||
|
||||
// Get pagination, filters, sorter
|
||||
prepareParamsArguments(state: any): [any, string[], Object] {
|
||||
prepareParamsArguments(state: any): PrepareParamsArgumentsReturn<T> {
|
||||
const pagination = { ...state.pagination };
|
||||
// remove useless handle function in Table.onChange
|
||||
delete pagination.onChange;
|
||||
@ -889,7 +901,12 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
sorter.field = state.sortColumn.dataIndex;
|
||||
sorter.columnKey = this.getColumnKey(state.sortColumn);
|
||||
}
|
||||
return [pagination, filters, sorter];
|
||||
|
||||
const extra = {
|
||||
currentDataSource: this.getLocalData(state),
|
||||
};
|
||||
|
||||
return [pagination, filters, sorter, extra];
|
||||
}
|
||||
|
||||
findColumn(myKey: string | number) {
|
||||
@ -944,24 +961,24 @@ export default class Table<T> extends React.Component<TableProps<T>, TableState<
|
||||
} : item));
|
||||
}
|
||||
|
||||
getLocalData() {
|
||||
const state = this.state;
|
||||
getLocalData(state?: TableState<T>) {
|
||||
const currentState: TableState<T> = state || this.state;
|
||||
const { dataSource } = this.props;
|
||||
let data = dataSource || [];
|
||||
// 优化本地排序
|
||||
data = data.slice(0);
|
||||
const sorterFn = this.getSorterFn();
|
||||
const sorterFn = this.getSorterFn(currentState);
|
||||
if (sorterFn) {
|
||||
data = this.recursiveSort(data, sorterFn);
|
||||
}
|
||||
// 筛选
|
||||
if (state.filters) {
|
||||
Object.keys(state.filters).forEach((columnKey) => {
|
||||
if (currentState.filters) {
|
||||
Object.keys(currentState.filters).forEach((columnKey) => {
|
||||
let col = this.findColumn(columnKey) as any;
|
||||
if (!col) {
|
||||
return;
|
||||
}
|
||||
let values = state.filters[columnKey] || [];
|
||||
let values = currentState.filters[columnKey] || [];
|
||||
if (values.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -220,7 +220,14 @@ describe('Table.filter', () => {
|
||||
dropdownWrapper.find('MenuItem').first().simulate('click');
|
||||
dropdownWrapper.find('.confirm').simulate('click');
|
||||
|
||||
expect(handleChange).toBeCalledWith({}, { name: ['boy'] }, {});
|
||||
expect(handleChange).toBeCalledWith(
|
||||
{},
|
||||
{ name: ['boy'] },
|
||||
{},
|
||||
{
|
||||
currentDataSource: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should not fire change event on close filterDropdown without changing anything', () => {
|
||||
@ -377,6 +384,7 @@ describe('Table.filter', () => {
|
||||
wrapper.find('.ant-dropdown-trigger').first().simulate('click');
|
||||
|
||||
expect(handleChange).toBeCalled();
|
||||
expect(handleChange.mock.calls[0][3].currentDataSource.length).toBe(1);
|
||||
});
|
||||
|
||||
it('renders custom filter icon correctly', () => {
|
||||
|
@ -86,7 +86,15 @@ describe('Table.pagination', () => {
|
||||
pageSize: 2,
|
||||
},
|
||||
{},
|
||||
{}
|
||||
{},
|
||||
{
|
||||
currentDataSource: [
|
||||
{ key: 0, name: 'Jack' },
|
||||
{ key: 1, name: 'Lucy' },
|
||||
{ key: 2, name: 'Tom' },
|
||||
{ key: 3, name: 'Jerry' },
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
expect(handlePaginationChange).toBeCalledWith(2, 2);
|
||||
|
@ -433,13 +433,13 @@ describe('Table.rowSelection', () => {
|
||||
}}
|
||||
/>
|
||||
);
|
||||
expect(wrapper.find('thead tr span').at(0).text()).toBe('多选');
|
||||
expect(wrapper.find('thead tr div').at(0).text()).toBe('多选');
|
||||
wrapper.setProps({
|
||||
rowSelection: {
|
||||
type: 'radio',
|
||||
columnTitle: '单选',
|
||||
},
|
||||
});
|
||||
expect(wrapper.find('thead tr span').at(0).text()).toBe('单选');
|
||||
expect(wrapper.find('thead tr div').at(0).text()).toBe('单选');
|
||||
});
|
||||
});
|
||||
|
@ -60,11 +60,13 @@ describe('Table.sorter', () => {
|
||||
it('sort records', () => {
|
||||
const wrapper = mount(createTable());
|
||||
|
||||
wrapper.find('.ant-table-column-sorter-up').simulate('click');
|
||||
expect(renderedNames(wrapper)).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom']);
|
||||
|
||||
wrapper.find('.ant-table-column-sorter-down').simulate('click');
|
||||
// descent
|
||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
||||
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
||||
|
||||
// ascent
|
||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
||||
expect(renderedNames(wrapper)).toEqual(['Jack', 'Jerry', 'Lucy', 'Tom']);
|
||||
});
|
||||
|
||||
it('can be controlled by sortOrder', () => {
|
||||
@ -92,13 +94,27 @@ describe('Table.sorter', () => {
|
||||
const handleChange = jest.fn();
|
||||
const wrapper = mount(createTable({ onChange: handleChange }));
|
||||
|
||||
wrapper.find('.ant-table-column-sorter-up').simulate('click');
|
||||
// ascent
|
||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
||||
const sorter1 = handleChange.mock.calls[0][2];
|
||||
expect(sorter1.column.dataIndex).toBe('name');
|
||||
expect(sorter1.order).toBe('descend');
|
||||
expect(sorter1.field).toBe('name');
|
||||
expect(sorter1.columnKey).toBe('name');
|
||||
|
||||
const sorter = handleChange.mock.calls[0][2];
|
||||
expect(sorter.column.dataIndex).toBe('name');
|
||||
expect(sorter.order).toBe('ascend');
|
||||
expect(sorter.field).toBe('name');
|
||||
expect(sorter.columnKey).toBe('name');
|
||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
||||
const sorter2 = handleChange.mock.calls[1][2];
|
||||
expect(sorter2.column.dataIndex).toBe('name');
|
||||
expect(sorter2.order).toBe('ascend');
|
||||
expect(sorter2.field).toBe('name');
|
||||
expect(sorter2.columnKey).toBe('name');
|
||||
|
||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
||||
const sorter3 = handleChange.mock.calls[2][2];
|
||||
expect(sorter3.column).toBe(undefined);
|
||||
expect(sorter3.order).toBe(undefined);
|
||||
expect(sorter3.field).toBe(undefined);
|
||||
expect(sorter3.columnKey).toBe(undefined);
|
||||
});
|
||||
|
||||
it('works with grouping columns in controlled mode', () => {
|
||||
@ -134,4 +150,64 @@ describe('Table.sorter', () => {
|
||||
|
||||
expect(renderedNames(wrapper)).toEqual(['Tom', 'Lucy', 'Jack', 'Jerry']);
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/11246#issuecomment-405009167
|
||||
it('Allow column title as render props with sortOrder argument', () => {
|
||||
const columns = [
|
||||
{
|
||||
title: ({ sortOrder }) => <div className="custom-title">{sortOrder}</div>,
|
||||
key: 'group',
|
||||
sorter: true,
|
||||
},
|
||||
];
|
||||
const testData = [
|
||||
{ key: 0, name: 'Jack', age: 11 },
|
||||
{ key: 1, name: 'Lucy', age: 20 },
|
||||
{ key: 2, name: 'Tom', age: 21 },
|
||||
{ key: 3, name: 'Jerry', age: 22 },
|
||||
];
|
||||
const wrapper = mount(
|
||||
<Table columns={columns} dataSource={testData} />
|
||||
);
|
||||
expect(wrapper.find('.custom-title').text()).toEqual('');
|
||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
||||
expect(wrapper.find('.custom-title').text()).toEqual('descend');
|
||||
wrapper.find('.ant-table-column-sorters').simulate('click');
|
||||
expect(wrapper.find('.custom-title').text()).toEqual('ascend');
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/pull/12264#discussion_r218053034
|
||||
it('should sort from begining state when toggle from different columns', () => {
|
||||
const columns = [
|
||||
{
|
||||
title: 'name',
|
||||
dataIndex: 'name',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: 'age',
|
||||
dataIndex: 'age',
|
||||
sorter: true,
|
||||
},
|
||||
];
|
||||
const testData = [
|
||||
{ key: 0, name: 'Jack', age: 11 },
|
||||
{ key: 1, name: 'Lucy', age: 20 },
|
||||
{ key: 2, name: 'Tom', age: 21 },
|
||||
{ key: 3, name: 'Jerry', age: 22 },
|
||||
];
|
||||
const wrapper = mount(
|
||||
<Table columns={columns} dataSource={testData} />
|
||||
);
|
||||
const nameColumn = wrapper.find('.ant-table-column-sorters').at(0);
|
||||
const ageColumn = wrapper.find('.ant-table-column-sorters').at(1);
|
||||
// sort name
|
||||
nameColumn.simulate('click');
|
||||
expect(nameColumn.find('.ant-table-column-sorter-down').at(0).getDOMNode().className).toContain(' on');
|
||||
expect(ageColumn.find('.ant-table-column-sorter-down').at(0).getDOMNode().className).toContain(' off');
|
||||
// sort age
|
||||
ageColumn.simulate('click');
|
||||
expect(nameColumn.find('.ant-table-column-sorter-down').at(0).getDOMNode().className).toContain(' off');
|
||||
expect(ageColumn.find('.ant-table-column-sorter-down').at(0).getDOMNode().className).toContain(' on');
|
||||
});
|
||||
});
|
||||
|
@ -29,7 +29,7 @@ exports[`Table.filter override custom filter correctly 1`] = `
|
||||
exports[`Table.filter renders custom content correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-dropdown ant-dropdown-placement-bottomLeft ant-dropdown-hidden"
|
||||
class="ant-dropdown ant-dropdown-placement-bottomRight ant-dropdown-hidden"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
@ -44,7 +44,7 @@ exports[`Table.filter renders custom content correctly 1`] = `
|
||||
|
||||
exports[`Table.filter renders custom filter icon correctly 1`] = `
|
||||
<span
|
||||
class="ant-table-filter-icon ant-dropdown-trigger"
|
||||
class="ant-table-filter-icon ant-table-filter-selected ant-dropdown-trigger"
|
||||
style=""
|
||||
title="Filter menu"
|
||||
>
|
||||
@ -92,29 +92,31 @@ exports[`Table.filter renders filter correctly 1`] = `
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-column-has-filters"
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters"
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Name
|
||||
<i
|
||||
class="anticon anticon-filter ant-dropdown-trigger"
|
||||
title="Filter menu"
|
||||
</div>
|
||||
<i
|
||||
class="anticon anticon-filter ant-dropdown-trigger"
|
||||
title="Filter menu"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="filter"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="filter"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M880.1 154H143.9c-24.5 0-39.8 26.7-27.5 48L349 597.4V838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V597.4L907.7 202c12.2-21.3-3.1-48-27.6-48zM603.4 798H420.6V642h182.9v156zm9.6-236.6l-9.5 16.6h-183l-9.5-16.6L212.7 226h598.6L613 561.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
<path
|
||||
d="M349 838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3 31.8-32V642H349v196zm531.1-684H143.9c-24.5 0-39.8 26.7-27.5 48l221.3 376h348.8l221.3-376c12.1-21.3-3.2-48-27.7-48z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -126,7 +128,7 @@ exports[`Table.filter renders filter correctly 1`] = `
|
||||
data-row-key="0"
|
||||
>
|
||||
<td
|
||||
class="ant-table-column-has-filters"
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
@ -140,7 +142,7 @@ exports[`Table.filter renders filter correctly 1`] = `
|
||||
data-row-key="1"
|
||||
>
|
||||
<td
|
||||
class="ant-table-column-has-filters"
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
@ -154,7 +156,7 @@ exports[`Table.filter renders filter correctly 1`] = `
|
||||
data-row-key="2"
|
||||
>
|
||||
<td
|
||||
class="ant-table-column-has-filters"
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
@ -168,7 +170,7 @@ exports[`Table.filter renders filter correctly 1`] = `
|
||||
data-row-key="3"
|
||||
>
|
||||
<td
|
||||
class="ant-table-column-has-filters"
|
||||
class="ant-table-column-has-actions ant-table-column-has-filters"
|
||||
>
|
||||
<span
|
||||
class="ant-table-row-indent indent-level-0"
|
||||
@ -190,7 +192,7 @@ exports[`Table.filter renders filter correctly 1`] = `
|
||||
exports[`Table.filter renders menu correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-dropdown ant-dropdown-placement-bottomLeft ant-dropdown-hidden"
|
||||
class="ant-dropdown ant-dropdown-placement-bottomRight ant-dropdown-hidden"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-dropdown"
|
||||
@ -285,7 +287,7 @@ exports[`Table.filter renders menu correctly 1`] = `
|
||||
exports[`Table.filter renders radio filter correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-dropdown ant-dropdown-placement-bottomLeft ant-dropdown-hidden"
|
||||
class="ant-dropdown ant-dropdown-placement-bottomRight ant-dropdown-hidden"
|
||||
>
|
||||
<div
|
||||
class="ant-table-filter-dropdown"
|
||||
|
@ -32,9 +32,11 @@ exports[`Table.pagination renders pagination correctly 1`] = `
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Name
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -36,7 +36,9 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
|
||||
<th
|
||||
class="ant-table-fixed-columns-in-body ant-table-selection-column"
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
<div
|
||||
class="ant-table-selection"
|
||||
>
|
||||
@ -56,14 +58,16 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Name
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -237,7 +241,9 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
|
||||
<th
|
||||
class="ant-table-selection-column"
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
<div
|
||||
class="ant-table-selection"
|
||||
>
|
||||
@ -257,7 +263,7 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -6,59 +6,52 @@ exports[`Table.sorter renders sorter icon correctly 1`] = `
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-column-has-filters"
|
||||
class="ant-table-column-has-actions ant-table-column-has-sorters"
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
class="ant-table-column-sorters"
|
||||
title="Sort"
|
||||
>
|
||||
Name
|
||||
<div
|
||||
class="ant-table-column-sorter"
|
||||
>
|
||||
<span
|
||||
class="ant-table-column-sorter-up off"
|
||||
title="↑"
|
||||
<i
|
||||
class="anticon anticon-caret-up ant-table-column-sorter-up off"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-caret-up"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="caret-up"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="caret-up"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M76.3 632.8l405.1-489.1a42.53 42.53 0 0 1 63.4 0l403.1 489.1c24.4 27.4 5 70.8-31.7 70.8H107.9c-36.6 0-56.1-43.4-31.6-70.8z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
<span
|
||||
class="ant-table-column-sorter-down off"
|
||||
title="↓"
|
||||
<path
|
||||
d="M76.3 632.8l405.1-489.1a42.53 42.53 0 0 1 63.4 0l403.1 489.1c24.4 27.4 5 70.8-31.7 70.8H107.9c-36.6 0-56.1-43.4-31.6-70.8z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<i
|
||||
class="anticon anticon-caret-down ant-table-column-sorter-down off"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-caret-down"
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="caret-down"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="caret-down"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M76.3 392.3l403.1 489.1a42.53 42.53 0 0 0 63.4 0l405.1-489.1c24.4-27.4 5-70.8-31.7-70.8H108.1c-36.8 0-56.3 43.4-31.8 70.8z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
<path
|
||||
d="M76.3 392.3l403.1 489.1a42.53 42.53 0 0 0 63.4 0l405.1-489.1c24.4-27.4 5-70.8-31.7-70.8H108.1c-36.8 0-56.3 43.4-31.8 70.8z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -35,33 +35,41 @@ exports[`Table renders JSX correctly 1`] = `
|
||||
class=""
|
||||
colspan="2"
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Name
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
rowspan="2"
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Age
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
First Name
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Last Name
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -39,58 +39,74 @@ exports[`Table renders empty table 1`] = `
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 1
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 2
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 3
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 4
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 5
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 6
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 7
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 8
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -150,58 +166,74 @@ exports[`Table renders empty table with custom emptyText 1`] = `
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 1
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 2
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 3
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 4
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 5
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 6
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 7
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 8
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -273,79 +305,101 @@ exports[`Table renders empty table with fixed columns 1`] = `
|
||||
<th
|
||||
class="ant-table-fixed-columns-in-body"
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Full Name
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-fixed-columns-in-body"
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Age
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 1
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 2
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 3
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 4
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 5
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 6
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 7
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 8
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class="ant-table-fixed-columns-in-body"
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Action
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -388,16 +442,20 @@ exports[`Table renders empty table with fixed columns 1`] = `
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Full Name
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Age
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -433,9 +491,11 @@ exports[`Table renders empty table with fixed columns 1`] = `
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Action
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -506,58 +566,74 @@ exports[`Table renders empty table without emptyText when loading 1`] = `
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 1
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 2
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 3
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 4
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 5
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 6
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 7
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
title="Sort"
|
||||
>
|
||||
Column 8
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -11,6 +11,13 @@ import Radio from '../radio';
|
||||
import FilterDropdownMenuWrapper from './FilterDropdownMenuWrapper';
|
||||
import { FilterMenuProps, FilterMenuState, ColumnProps, ColumnFilterItem } from './interface';
|
||||
|
||||
function stopPropagation(e: React.SyntheticEvent<any>) {
|
||||
e.stopPropagation();
|
||||
if (e.nativeEvent.stopImmediatePropagation) {
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
}
|
||||
}
|
||||
|
||||
export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, FilterMenuState> {
|
||||
static defaultProps = {
|
||||
handleFilter() {},
|
||||
@ -63,6 +70,10 @@ export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, F
|
||||
}
|
||||
}
|
||||
|
||||
getDropdownVisible() {
|
||||
return this.neverShown ? false : this.state.visible;
|
||||
}
|
||||
|
||||
setNeverShown = (column: ColumnProps<T>) => {
|
||||
const rootNode = ReactDOM.findDOMNode(this);
|
||||
const filterBelongToScrollBody = !!closest(rootNode, `.ant-table-scroll`);
|
||||
@ -179,13 +190,27 @@ export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, F
|
||||
if (typeof filterIcon === 'function') {
|
||||
filterIcon = filterIcon(filterd);
|
||||
}
|
||||
const dropdownSelectedClass = filterd ? `${prefixCls}-selected` : '';
|
||||
|
||||
const dropdownIconClass = classNames({
|
||||
[`${prefixCls}-selected`]: filterd,
|
||||
[`${prefixCls}-open`]: this.getDropdownVisible(),
|
||||
});
|
||||
|
||||
return filterIcon ? React.cloneElement(filterIcon as any, {
|
||||
title: locale.filterTitle,
|
||||
className: classNames(`${prefixCls}-icon`, filterIcon.props.className),
|
||||
}) : <Icon title={locale.filterTitle} type="filter" className={dropdownSelectedClass} />;
|
||||
className: classNames(`${prefixCls}-icon`, dropdownIconClass, filterIcon.props.className),
|
||||
onClick: stopPropagation,
|
||||
}) : (
|
||||
<Icon
|
||||
title={locale.filterTitle}
|
||||
type="filter"
|
||||
theme="filled"
|
||||
className={dropdownIconClass}
|
||||
onClick={stopPropagation}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { column, locale, prefixCls, dropdownPrefixCls, getPopupContainer } = this.props;
|
||||
// default multiple selection in filter dropdown
|
||||
@ -244,8 +269,9 @@ export default class FilterMenu<T> extends React.Component<FilterMenuProps<T>, F
|
||||
return (
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
placement="bottomRight"
|
||||
overlay={menus}
|
||||
visible={this.neverShown ? false : this.state.visible}
|
||||
visible={this.getDropdownVisible()}
|
||||
onVisibleChange={this.onVisibleChange}
|
||||
getPopupContainer={getPopupContainer}
|
||||
forceRender
|
||||
|
@ -74,7 +74,7 @@ const columns = [{
|
||||
| showHeader | Whether to show table header | boolean | `true` |
|
||||
| size | Size of table | `default` \| `middle` \| `small` | `default` |
|
||||
| title | Table title renderer | Function(currentPageData) | |
|
||||
| onChange | Callback executed when pagination, filters or sorter is changed | Function(pagination, filters, sorter) | |
|
||||
| onChange | Callback executed when pagination, filters or sorter is changed | Function(pagination, filters, sorter, extra: { currentDataSource: [] }) | |
|
||||
| onExpand | Callback executed when the row expand icon is clicked | Function(expanded, record) | |
|
||||
| onExpandedRowsChange | Callback executed when the expanded rows change | Function(expandedRows) | |
|
||||
| onHeaderRow | Set props on per header row | Function(column, index) | - |
|
||||
@ -124,7 +124,7 @@ One of the Table `columns` prop for describing the table's columns, Column has t
|
||||
| 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) {} | - |
|
||||
| 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 | - |
|
||||
| title | Title of this column | string\|ReactNode | - |
|
||||
| title | Title of this column | ReactNode\|({ sortOrder, filters }) => ReactNode | - |
|
||||
| width | Width of this column | string\|number | - |
|
||||
| onCell | Set props on per cell | Function(record) | - |
|
||||
| onFilter | Callback executed when the confirm filter button is clicked | Function | - |
|
||||
|
@ -79,7 +79,7 @@ const columns = [{
|
||||
| showHeader | 是否显示表头 | boolean | true |
|
||||
| size | 正常或迷你类型,`default` or `small` | string | default |
|
||||
| title | 表格标题 | Function(currentPageData) | |
|
||||
| onChange | 分页、排序、筛选变化时触发 | Function(pagination, filters, sorter) | |
|
||||
| onChange | 分页、排序、筛选变化时触发 | Function(pagination, filters, sorter, extra: { currentDataSource: [] }) | |
|
||||
| onExpand | 点击展开图标时触发 | Function(expanded, record) | |
|
||||
| onExpandedRowsChange | 展开的行变化时触发 | Function(expandedRows) | |
|
||||
| onHeaderRow | 设置头部行属性 | Function(column, index) | - |
|
||||
@ -129,7 +129,7 @@ const columns = [{
|
||||
| render | 生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return里面可以设置表格[行/列合并](#components-table-demo-colspan-rowspan) | Function(text, record, index) {} | - |
|
||||
| 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 | - |
|
||||
| title | 列头显示文字 | string\|ReactNode | - |
|
||||
| title | 列头显示文字 | ReactNode\|({ sortOrder, filters }) => ReactNode | - |
|
||||
| width | 列宽度 | string\|number | - |
|
||||
| onCell | 设置单元格属性 | Function(record) | - |
|
||||
| onFilter | 本地模式下,确定筛选的运行函数 | Function | - |
|
||||
|
@ -6,11 +6,14 @@ import { CheckboxChangeEvent } from '../checkbox';
|
||||
import { PaginationConfig } from '../pagination';
|
||||
export { PaginationConfig } from '../pagination';
|
||||
|
||||
export type CompareFn<T> = ((a: T, b: T, sortOrder?: 'ascend' | 'descend') => number);
|
||||
export type CompareFn<T> = ((a: T, b: T, sortOrder?: SortOrder) => number);
|
||||
export type ColumnFilterItem = { text: string; value: string, children?: ColumnFilterItem[] };
|
||||
|
||||
export interface ColumnProps<T> {
|
||||
title?: React.ReactNode;
|
||||
title?: React.ReactNode | ((options: {
|
||||
filters: TableStateFilters,
|
||||
sortOrder?: SortOrder,
|
||||
}) => React.ReactNode);
|
||||
key?: React.Key;
|
||||
dataIndex?: string;
|
||||
render?: (text: any, record: T, index: number) => React.ReactNode;
|
||||
@ -22,14 +25,14 @@ export interface ColumnProps<T> {
|
||||
filterDropdownVisible?: boolean;
|
||||
onFilterDropdownVisibleChange?: (visible: boolean) => void;
|
||||
sorter?: boolean | CompareFn<T>;
|
||||
defaultSortOrder?: 'ascend' | 'descend';
|
||||
defaultSortOrder?: SortOrder;
|
||||
colSpan?: number;
|
||||
width?: string | number;
|
||||
className?: string;
|
||||
fixed?: boolean | ('left' | 'right');
|
||||
filterIcon?: React.ReactNode | ((filtered: boolean) => React.ReactNode);
|
||||
filteredValue?: any[];
|
||||
sortOrder?: 'ascend' | 'descend';
|
||||
sortOrder?: SortOrder;
|
||||
children?: ColumnProps<T>[];
|
||||
onCellClick?: (record: T, event: any) => void;
|
||||
onCell?: (record: T) => any;
|
||||
@ -57,6 +60,7 @@ export interface TableLocale {
|
||||
emptyText?: React.ReactNode | (() => React.ReactNode);
|
||||
selectAll?: React.ReactNode;
|
||||
selectInvert?: React.ReactNode;
|
||||
sortTitle?: string;
|
||||
}
|
||||
|
||||
export type RowSelectionType = 'checkbox' | 'radio';
|
||||
@ -208,3 +212,12 @@ export interface FilterMenuState {
|
||||
keyPathOfSelectedItem: { [key: string]: string };
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
export type PrepareParamsArgumentsReturn<T> = [
|
||||
any,
|
||||
string[],
|
||||
Object,
|
||||
{
|
||||
currentDataSource: T[],
|
||||
}
|
||||
];
|
||||
|
@ -2,7 +2,7 @@
|
||||
@import "../../style/mixins/index";
|
||||
|
||||
@table-prefix-cls: ~"@{ant-prefix}-table";
|
||||
@table-header-icon-color: @text-color-secondary;
|
||||
@table-header-icon-color: #bfbfbf;
|
||||
|
||||
.@{table-prefix-cls}-wrapper {
|
||||
.clearfix;
|
||||
@ -42,32 +42,116 @@
|
||||
|
||||
.@{iconfont-css-prefix}-filter,
|
||||
.@{table-prefix-cls}-filter-icon {
|
||||
position: relative;
|
||||
margin-left: 8px;
|
||||
font-size: @font-size-base;
|
||||
font-size: @font-size-sm;
|
||||
cursor: pointer;
|
||||
color: @table-header-icon-color;
|
||||
transition: all .3s;
|
||||
width: 14px;
|
||||
font-weight: normal;
|
||||
vertical-align: text-bottom;
|
||||
width: 28px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
color: @text-color;
|
||||
> svg {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -@font-size-sm / 2 + 1px;
|
||||
margin-left: -@font-size-sm / 2;
|
||||
}
|
||||
}
|
||||
|
||||
.@{table-prefix-cls}-column-sorter + .@{iconfont-css-prefix}-filter {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.@{table-prefix-cls}-filter-selected.@{iconfont-css-prefix}-filter {
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/8979
|
||||
&.@{table-prefix-cls}-column-has-filters {
|
||||
overflow: hidden;
|
||||
.@{table-prefix-cls}-column-sorter {
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: 50%;
|
||||
width: 14px;
|
||||
height: @font-size-base;
|
||||
margin-top: -@font-size-base / 2;
|
||||
text-align: center;
|
||||
color: @table-header-icon-color;
|
||||
transition: all .3s;
|
||||
|
||||
&-up,
|
||||
&-down {
|
||||
.iconfont-size-under-12px(8px);
|
||||
line-height: 4px;
|
||||
height: 4px;
|
||||
transition: all .3s;
|
||||
display: block;
|
||||
&.on {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-down {
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
&.@{table-prefix-cls}-column-has-actions {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
// Very complicated styles logic but neccessary
|
||||
&:hover {
|
||||
background: #f5f5f5;
|
||||
.@{iconfont-css-prefix}-filter,
|
||||
.@{table-prefix-cls}-filter-icon {
|
||||
background: #f5f5f5;
|
||||
&:hover {
|
||||
color: @text-color-secondary;
|
||||
background: #ebebeb;
|
||||
}
|
||||
&:active {
|
||||
color: @text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-filter,
|
||||
.@{table-prefix-cls}-filter-icon {
|
||||
&.@{table-prefix-cls}-filter-open {
|
||||
color: @text-color-secondary;
|
||||
background: #ebebeb;
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
.@{table-prefix-cls}-column-sorter-up:not(.on),
|
||||
.@{table-prefix-cls}-column-sorter-down:not(.on) {
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{table-prefix-cls}-column-sorters {
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: transparent;
|
||||
transition: all .3s;
|
||||
}
|
||||
&:hover:before {
|
||||
background: rgba(0, 0, 0, .04);
|
||||
}
|
||||
}
|
||||
|
||||
&.@{table-prefix-cls}-column-has-filters .@{table-prefix-cls}-column-sorter {
|
||||
right: 28px + 6px;
|
||||
}
|
||||
|
||||
&.@{table-prefix-cls}-column-has-sorters {
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,6 +252,10 @@
|
||||
background: @table-header-sort-bg;
|
||||
}
|
||||
|
||||
&-tbody > tr > td.@{table-prefix-cls}-column-sort {
|
||||
background: @table-body-sort-bg;
|
||||
}
|
||||
|
||||
&-thead > tr > th,
|
||||
&-tbody > tr > td {
|
||||
padding: @table-padding-vertical @table-padding-horizontal;
|
||||
@ -228,72 +316,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-column-sorter {
|
||||
position: relative;
|
||||
margin-left: 8px;
|
||||
display: inline-block;
|
||||
vertical-align: text-bottom;
|
||||
top: -1.5px;
|
||||
width: 14px;
|
||||
height: @font-size-base;
|
||||
text-align: center;
|
||||
font-weight: normal;
|
||||
color: @table-header-icon-color;
|
||||
|
||||
&-up,
|
||||
&-down {
|
||||
display: block;
|
||||
width: 14px;
|
||||
height: @font-size-base / 2 - 1px;
|
||||
line-height: @font-size-base / 2 - 1px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
&:hover .@{iconfont-css-prefix} {
|
||||
color: @primary-4;
|
||||
}
|
||||
&.on {
|
||||
.@{iconfont-css-prefix}-caret-up,
|
||||
.@{iconfont-css-prefix}-caret-down {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
height: 30px;
|
||||
width: 14px;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-up:after {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&-down:after {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-caret-up,
|
||||
.@{iconfont-css-prefix}-caret-down {
|
||||
.iconfont-size-under-12px(8px);
|
||||
line-height: 4px;
|
||||
height: 4px;
|
||||
transition: all .3s;
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&-down {
|
||||
margin-top: 1.5px;
|
||||
}
|
||||
|
||||
.@{iconfont-css-prefix}-caret-up {
|
||||
margin-top: 0.5px;
|
||||
}
|
||||
}
|
||||
|
||||
&-bordered {
|
||||
.@{table-prefix-cls}-header > table,
|
||||
.@{table-prefix-cls}-body > table,
|
||||
|
@ -411,6 +411,41 @@ exports[`renders ./components/time-picker/demo/size.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/time-picker/demo/suffix.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-time-picker "
|
||||
>
|
||||
<input
|
||||
class="ant-time-picker-input"
|
||||
id=""
|
||||
placeholder="Select time"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-time-picker-icon"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-smile ant-time-picker-clock-icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/time-picker/demo/value.md correctly 1`] = `
|
||||
<span
|
||||
class="ant-time-picker "
|
||||
|
31
components/time-picker/demo/suffix.md
Normal file
31
components/time-picker/demo/suffix.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
order: 12
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 后缀图标
|
||||
en-US: Suffix
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
点击 TimePicker,然后可以在浮层中选择或者输入某一时间。
|
||||
|
||||
## en-US
|
||||
|
||||
Click `TimePicker`, and then we could select or input a time in panel.
|
||||
|
||||
````jsx
|
||||
import { TimePicker, Icon } from 'antd';
|
||||
import moment from 'moment';
|
||||
|
||||
function onChange(time, timeString) {
|
||||
console.log(time, timeString);
|
||||
}
|
||||
|
||||
const icon = <Icon type="smile" />;
|
||||
|
||||
ReactDOM.render(
|
||||
<TimePicker suffixIcon={icon} onChange={onChange} defaultOpenValue={moment('00:00:00', 'HH:mm:ss')} />,
|
||||
mountNode
|
||||
);
|
||||
````
|
@ -44,6 +44,7 @@ import moment from 'moment';
|
||||
| placeholder | display when there's no value | string | "Select a time" |
|
||||
| popupClassName | className of panel | string | '' |
|
||||
| secondStep | interval between seconds in picker | number | 1 |
|
||||
| suffixIcon | The custom suffix icon | ReactNode | - |
|
||||
| use12Hours | display as 12 hours format, with default format `h:mm:ss a` | boolean | false |
|
||||
| value | to set time | [moment](http://momentjs.com/) | - |
|
||||
| onChange | a callback function, can be executed when the selected time is changing | function(time: moment, timeString: string): void | - |
|
||||
|
@ -50,6 +50,7 @@ export interface TimePickerProps {
|
||||
clearText?: string;
|
||||
defaultOpenValue?: moment.Moment;
|
||||
popupClassName?: string;
|
||||
suffixIcon?: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface TimePickerLocale {
|
||||
@ -153,20 +154,35 @@ class TimePicker extends React.Component<TimePickerProps, any> {
|
||||
) : null
|
||||
);
|
||||
|
||||
const inputIcon = (
|
||||
<span className={`${props.prefixCls}-icon`}>
|
||||
const { suffixIcon, prefixCls } = props;
|
||||
const clockIcon = suffixIcon && (
|
||||
React.isValidElement<{ className?: string }>(suffixIcon)
|
||||
? React.cloneElement(
|
||||
suffixIcon,
|
||||
{
|
||||
className: classNames({
|
||||
[suffixIcon.props.className!]: suffixIcon.props.className,
|
||||
[`${prefixCls}-clock-icon`]: true,
|
||||
}),
|
||||
},
|
||||
) : <span className={`${prefixCls}-clock-icon`}>{suffixIcon}</span>) || (
|
||||
<Icon
|
||||
type="clock-circle"
|
||||
className={`${props.prefixCls}-clock-icon`}
|
||||
className={`${prefixCls}-clock-icon`}
|
||||
theme="outlined"
|
||||
/>
|
||||
);
|
||||
|
||||
const inputIcon = (
|
||||
<span className={`${prefixCls}-icon`}>
|
||||
{clockIcon}
|
||||
</span>
|
||||
);
|
||||
|
||||
const clearIcon = (
|
||||
<Icon
|
||||
type="close-circle"
|
||||
className={`${props.prefixCls}-panel-clear-btn-icon`}
|
||||
className={`${prefixCls}-panel-clear-btn-icon`}
|
||||
theme="filled"
|
||||
/>
|
||||
);
|
||||
|
@ -45,6 +45,7 @@ import moment from 'moment';
|
||||
| placeholder | 没有值的时候显示的内容 | string | "请选择时间" |
|
||||
| popupClassName | 弹出层类名 | string | '' |
|
||||
| secondStep | 秒选项间隔 | number | 1 |
|
||||
| suffixIcon | 自定义的选择框后缀图标 | ReactNode | - |
|
||||
| use12Hours | 使用 12 小时制,为 true 时 `format` 默认为 `h:mm:ss a` | boolean | false |
|
||||
| value | 当前时间 | [moment](http://momentjs.com/) | 无 |
|
||||
| onChange | 时间发生变化的回调 | function(time: moment, timeString: string): void | 无 |
|
||||
|
@ -248,235 +248,249 @@ exports[`renders ./components/transfer/demo/advanced.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/transfer/demo/basic.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-transfer"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-transfer-list"
|
||||
class="ant-transfer"
|
||||
>
|
||||
<div
|
||||
class="ant-transfer-list-header"
|
||||
class="ant-transfer-list"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
<div
|
||||
class="ant-transfer-list-header"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
<span
|
||||
class="ant-transfer-list-header-selected"
|
||||
>
|
||||
<span>
|
||||
14 items
|
||||
</span>
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
class="ant-transfer-list-header-selected"
|
||||
>
|
||||
Source
|
||||
<span>
|
||||
14 items
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
>
|
||||
Source
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-transfer-list-body"
|
||||
>
|
||||
<ul
|
||||
class="ant-transfer-list-content"
|
||||
>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
</ul>
|
||||
<div
|
||||
class="ant-transfer-list-body-not-found"
|
||||
>
|
||||
Not Found
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-transfer-list-body"
|
||||
class="ant-transfer-operation"
|
||||
>
|
||||
<ul
|
||||
class="ant-transfer-list-content"
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
</ul>
|
||||
<i
|
||||
class="anticon anticon-right"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="right"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-left"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 0 0 0 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-transfer-list"
|
||||
>
|
||||
<div
|
||||
class="ant-transfer-list-body-not-found"
|
||||
class="ant-transfer-list-header"
|
||||
>
|
||||
Not Found
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
<span
|
||||
class="ant-transfer-list-header-selected"
|
||||
>
|
||||
<span>
|
||||
6 items
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
>
|
||||
Target
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-transfer-list-body"
|
||||
>
|
||||
<ul
|
||||
class="ant-transfer-list-content"
|
||||
>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
</ul>
|
||||
<div
|
||||
class="ant-transfer-list-body-not-found"
|
||||
>
|
||||
Not Found
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-transfer-operation"
|
||||
<button
|
||||
aria-checked="false"
|
||||
class="ant-switch"
|
||||
role="switch"
|
||||
type="button"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
disabled=""
|
||||
type="button"
|
||||
<span
|
||||
class="ant-switch-inner"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-right"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="right"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-left"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 0 0 0 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-transfer-list"
|
||||
>
|
||||
<div
|
||||
class="ant-transfer-list-header"
|
||||
>
|
||||
<label
|
||||
class="ant-checkbox-wrapper"
|
||||
>
|
||||
<span
|
||||
class="ant-checkbox"
|
||||
>
|
||||
<input
|
||||
class="ant-checkbox-input"
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
class="ant-checkbox-inner"
|
||||
/>
|
||||
</span>
|
||||
</label>
|
||||
<span
|
||||
class="ant-transfer-list-header-selected"
|
||||
>
|
||||
<span>
|
||||
6 items
|
||||
</span>
|
||||
<span
|
||||
class="ant-transfer-list-header-title"
|
||||
>
|
||||
Target
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-transfer-list-body"
|
||||
>
|
||||
<ul
|
||||
class="ant-transfer-list-content"
|
||||
>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
<div
|
||||
class="LazyLoad"
|
||||
style="height:32px"
|
||||
/>
|
||||
</ul>
|
||||
<div
|
||||
class="ant-transfer-list-body-not-found"
|
||||
>
|
||||
Not Found
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
disabled
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
@ -14,7 +14,7 @@ title:
|
||||
The most basic usage of `Transfer` involves providing the source data and target keys arrays, plus the rendering and some callback functions.
|
||||
|
||||
````jsx
|
||||
import { Transfer } from 'antd';
|
||||
import { Transfer, Switch } from 'antd';
|
||||
|
||||
const mockData = [];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
@ -26,20 +26,21 @@ for (let i = 0; i < 20; i++) {
|
||||
});
|
||||
}
|
||||
|
||||
const targetKeys = mockData
|
||||
const oriTargetKeys = mockData
|
||||
.filter(item => +item.key % 3 > 1)
|
||||
.map(item => item.key);
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
targetKeys,
|
||||
targetKeys: oriTargetKeys,
|
||||
selectedKeys: [],
|
||||
disabled: false,
|
||||
}
|
||||
|
||||
handleChange = (nextTargetKeys, direction, moveKeys) => {
|
||||
this.setState({ targetKeys: nextTargetKeys });
|
||||
|
||||
console.log('targetKeys: ', targetKeys);
|
||||
console.log('targetKeys: ', nextTargetKeys);
|
||||
console.log('direction: ', direction);
|
||||
console.log('moveKeys: ', moveKeys);
|
||||
}
|
||||
@ -56,19 +57,28 @@ class App extends React.Component {
|
||||
console.log('target:', e.target);
|
||||
}
|
||||
|
||||
handleDisable = (disabled) => {
|
||||
this.setState({ disabled });
|
||||
};
|
||||
|
||||
render() {
|
||||
const state = this.state;
|
||||
const { targetKeys, selectedKeys, disabled } = this.state;
|
||||
return (
|
||||
<Transfer
|
||||
dataSource={mockData}
|
||||
titles={['Source', 'Target']}
|
||||
targetKeys={state.targetKeys}
|
||||
selectedKeys={state.selectedKeys}
|
||||
onChange={this.handleChange}
|
||||
onSelectChange={this.handleSelectChange}
|
||||
onScroll={this.handleScroll}
|
||||
render={item => item.title}
|
||||
/>
|
||||
<div>
|
||||
<Transfer
|
||||
dataSource={mockData}
|
||||
titles={['Source', 'Target']}
|
||||
targetKeys={targetKeys}
|
||||
selectedKeys={selectedKeys}
|
||||
onChange={this.handleChange}
|
||||
onSelectChange={this.handleSelectChange}
|
||||
onScroll={this.handleScroll}
|
||||
render={item => item.title}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
<Switch unCheckedChildren="disabled" checkedChildren="disabled" checked={disabled} onChange={this.handleDisable} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,9 @@ One or more elements can be selected from either column, one click on the proper
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| className | A custom CSS class. | string | ['', ''] |
|
||||
| dataSource | Used for setting the source data. The elements that are part of this array will be present the left column. Except the elements whose keys are included in `targetKeys` prop. | [TransferItem](https://git.io/vMM64)\[] | \[] |
|
||||
| dataSource | Used for setting the source data. The elements that are part of this array will be present the left column.
|
||||
Except the elements whose keys are included in `targetKeys` prop. | [TransferItem](https://git.io/vMM64)\[] | \[] |
|
||||
| disabled | Whether disabled transfer | boolean | false |
|
||||
| filterOption | A function to determine whether an item should show in search result list | (inputValue, option): boolean | |
|
||||
| footer | A function used for rendering the footer. | (props): ReactNode | |
|
||||
| lazy | property of [react-lazy-load](https://github.com/loktar00/react-lazy-load) for lazy rendering items. Turn off it by set to `false`. | object\|boolean | `{ height: 32, offset: 32 }` |
|
||||
|
@ -27,6 +27,7 @@ export interface TransferItem {
|
||||
export interface TransferProps {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
dataSource: TransferItem[];
|
||||
targetKeys?: string[];
|
||||
selectedKeys?: string[];
|
||||
@ -74,6 +75,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
|
||||
static propTypes = {
|
||||
prefixCls: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
dataSource: PropTypes.array,
|
||||
render: PropTypes.func,
|
||||
targetKeys: PropTypes.array,
|
||||
@ -348,6 +350,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
const {
|
||||
prefixCls = 'ant-transfer',
|
||||
className,
|
||||
disabled,
|
||||
operations = [],
|
||||
showSearch,
|
||||
body,
|
||||
@ -366,7 +369,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
const leftActive = targetSelectedKeys.length > 0;
|
||||
const rightActive = sourceSelectedKeys.length > 0;
|
||||
|
||||
const cls = classNames(className, prefixCls);
|
||||
const cls = classNames(className, prefixCls, disabled && `${prefixCls}-disabled`);
|
||||
|
||||
const titles = this.getTitles(locale);
|
||||
return (
|
||||
@ -389,6 +392,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
footer={footer}
|
||||
lazy={lazy}
|
||||
onScroll={this.handleLeftScroll}
|
||||
disabled={disabled}
|
||||
{...locale}
|
||||
/>
|
||||
<Operation
|
||||
@ -400,6 +404,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
leftArrowText={operations[1]}
|
||||
moveToLeft={this.moveToLeft}
|
||||
style={operationStyle}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<List
|
||||
prefixCls={`${prefixCls}-list`}
|
||||
@ -419,6 +424,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
||||
footer={footer}
|
||||
lazy={lazy}
|
||||
onScroll={this.handleRightScroll}
|
||||
disabled={disabled}
|
||||
{...locale}
|
||||
/>
|
||||
</div>
|
||||
|
@ -21,6 +21,7 @@ title: Transfer
|
||||
| --- | --- | --- | --- |
|
||||
| className | 自定义类 | string | |
|
||||
| dataSource | 数据源,其中的数据将会被渲染到左边一栏中,`targetKeys` 中指定的除外。 | [TransferItem](https://git.io/vMM64)\[] | \[] |
|
||||
| disabled | 是否禁用 | boolean | false |
|
||||
| filterOption | 接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 `true`,反之则返回 `false`。 | (inputValue, option): boolean | |
|
||||
| footer | 底部渲染函数 | (props): ReactNode | |
|
||||
| lazy | Transfer 使用了 [react-lazy-load](https://github.com/loktar00/react-lazy-load) 优化性能,这里可以设置相关参数。设为 `false` 可以关闭懒加载。 | object\|boolean | `{ height: 32, offset: 32 }` |
|
||||
|
@ -9,11 +9,14 @@ export default class Item extends React.Component<any, any> {
|
||||
return PureRenderMixin.shouldComponentUpdate.apply(this, args);
|
||||
}
|
||||
render() {
|
||||
const { renderedText, renderedEl, item, lazy, checked, prefixCls, onClick } = this.props;
|
||||
const {
|
||||
renderedText, renderedEl, item, lazy,
|
||||
checked, disabled, prefixCls, onClick,
|
||||
} = this.props;
|
||||
|
||||
const className = classNames({
|
||||
[`${prefixCls}-content-item`]: true,
|
||||
[`${prefixCls}-content-item-disabled`]: item.disabled,
|
||||
[`${prefixCls}-content-item-disabled`]: disabled || item.disabled,
|
||||
});
|
||||
|
||||
let title: string | undefined = undefined;
|
||||
@ -25,9 +28,9 @@ export default class Item extends React.Component<any, any> {
|
||||
<li
|
||||
className={className}
|
||||
title={title}
|
||||
onClick={item.disabled ? undefined : () => onClick(item)}
|
||||
onClick={(disabled || item.disabled) ? undefined : () => onClick(item)}
|
||||
>
|
||||
<Checkbox checked={checked} disabled={item.disabled} />
|
||||
<Checkbox checked={checked} disabled={disabled || item.disabled} />
|
||||
<span>{renderedEl}</span>
|
||||
</li>
|
||||
);
|
||||
|
@ -43,6 +43,7 @@ export interface TransferListProps {
|
||||
footer?: (props: TransferListProps) => React.ReactNode;
|
||||
lazy?: boolean | {};
|
||||
onScroll: Function;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export default class TransferList extends React.Component<TransferListProps, any> {
|
||||
@ -160,7 +161,7 @@ export default class TransferList extends React.Component<TransferListProps, any
|
||||
|
||||
render() {
|
||||
const {
|
||||
prefixCls, dataSource, titleText, checkedKeys, lazy,
|
||||
prefixCls, dataSource, titleText, checkedKeys, lazy, disabled,
|
||||
body, footer, showSearch, style, filter,
|
||||
searchPlaceholder, notFoundContent, itemUnit, itemsUnit, onScroll,
|
||||
} = this.props;
|
||||
@ -192,6 +193,7 @@ export default class TransferList extends React.Component<TransferListProps, any
|
||||
const checked = checkedKeys.indexOf(item.key) >= 0;
|
||||
return (
|
||||
<Item
|
||||
disabled={disabled}
|
||||
key={item.key}
|
||||
item={item}
|
||||
lazy={lazy}
|
||||
@ -219,7 +221,7 @@ export default class TransferList extends React.Component<TransferListProps, any
|
||||
) : null;
|
||||
|
||||
const listBody = bodyDom || (
|
||||
<div className={showSearch ? `${prefixCls}-body ${prefixCls}-body-with-search` : `${prefixCls}-body`}>
|
||||
<div className={classNames(showSearch ? `${prefixCls}-body ${prefixCls}-body-with-search` : `${prefixCls}-body`)}>
|
||||
{search}
|
||||
<Animate
|
||||
component="ul"
|
||||
@ -247,6 +249,7 @@ export default class TransferList extends React.Component<TransferListProps, any
|
||||
const checkAllCheckbox = (
|
||||
<Checkbox
|
||||
ref="checkbox"
|
||||
disabled={disabled}
|
||||
checked={checkedAll}
|
||||
indeterminate={checkStatus === 'part'}
|
||||
onChange={() => this.props.handleSelectAll(filteredDataSource, checkedAll)}
|
||||
|
@ -10,11 +10,13 @@ export interface TransferOperationProps {
|
||||
leftActive?: boolean;
|
||||
rightActive?: boolean;
|
||||
style?: React.CSSProperties;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export default class Operation extends React.Component<TransferOperationProps, any> {
|
||||
render() {
|
||||
const {
|
||||
disabled,
|
||||
moveToLeft,
|
||||
moveToRight,
|
||||
leftArrowText = '',
|
||||
@ -29,7 +31,7 @@ export default class Operation extends React.Component<TransferOperationProps, a
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
disabled={!rightActive}
|
||||
disabled={disabled || !rightActive}
|
||||
onClick={moveToRight}
|
||||
icon="right"
|
||||
>
|
||||
@ -38,7 +40,7 @@ export default class Operation extends React.Component<TransferOperationProps, a
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
disabled={!leftActive}
|
||||
disabled={disabled || !leftActive}
|
||||
onClick={moveToLeft}
|
||||
icon="left"
|
||||
>
|
||||
|
@ -8,6 +8,12 @@
|
||||
.reset-component;
|
||||
position: relative;
|
||||
|
||||
&-disabled {
|
||||
.@{transfer-prefix-cls}-list {
|
||||
background: @transfer-disabled-bg;
|
||||
}
|
||||
}
|
||||
|
||||
&-list {
|
||||
border: @border-width-base @border-style-base @border-color-base;
|
||||
display: inline-block;
|
||||
|
@ -172,6 +172,52 @@ exports[`renders ./components/tree-select/demo/multiple.md correctly 1`] = `
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/tree-select/demo/suffix.md correctly 1`] = `
|
||||
<span
|
||||
aria-haspopup="listbox"
|
||||
class="ant-select ant-select-enabled ant-select-allow-clear"
|
||||
role="combobox"
|
||||
style="width:300px"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection ant-select-selection--single"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection__rendered"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection__placeholder"
|
||||
>
|
||||
Please select
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-arrow"
|
||||
style="outline:none"
|
||||
>
|
||||
<i
|
||||
class="anticon anticon-smile"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="smile"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/tree-select/demo/treeData.md correctly 1`] = `
|
||||
<span
|
||||
aria-haspopup="listbox"
|
||||
|
61
components/tree-select/demo/suffix.md
Normal file
61
components/tree-select/demo/suffix.md
Normal file
@ -0,0 +1,61 @@
|
||||
---
|
||||
order: 12
|
||||
debug: true
|
||||
title:
|
||||
zh-CN: 后缀图标
|
||||
en-US: Suffix
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
最简单的用法。
|
||||
|
||||
## en-US
|
||||
|
||||
The most basic usage.
|
||||
|
||||
````jsx
|
||||
import { TreeSelect, Icon } from 'antd';
|
||||
|
||||
const TreeNode = TreeSelect.TreeNode;
|
||||
const icon = <Icon type="smile" />;
|
||||
|
||||
class Demo extends React.Component {
|
||||
state = {
|
||||
value: undefined,
|
||||
}
|
||||
|
||||
onChange = (value) => {
|
||||
console.log(value);
|
||||
this.setState({ value });
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<TreeSelect
|
||||
showSearch
|
||||
suffixIcon={icon}
|
||||
style={{ width: 300 }}
|
||||
value={this.state.value}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
placeholder="Please select"
|
||||
allowClear
|
||||
treeDefaultExpandAll
|
||||
onChange={this.onChange}
|
||||
>
|
||||
<TreeNode value="parent 1" title="parent 1" key="0-1">
|
||||
<TreeNode value="parent 1-0" title="parent 1-0" key="0-1-1">
|
||||
<TreeNode value="leaf1" title="my leaf" key="random" />
|
||||
<TreeNode value="leaf2" title="your leaf" key="random1" />
|
||||
</TreeNode>
|
||||
<TreeNode value="parent 1-1" title="parent 1-1" key="random2">
|
||||
<TreeNode value="sss" title={<b style={{ color: '#08c' }}>sss</b>} key="random3" />
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
````
|
@ -37,18 +37,21 @@ Any data whose entries are defined in a hierarchical manner is fit to use this c
|
||||
| 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 | Whether to display a search input in the dropdown menu(valid only in the single mode) | boolean | false |
|
||||
| size | To set the size of the select input, options: `large` `small` | string | 'default' |
|
||||
| suffixIcon | The custom suffix icon | 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] }> | \[] |
|
||||
| treeDataSimpleMode | Enable simple mode of treeData. Changes the `treeData` schema to: [{id:1, pId:0, value:'1', title:"test1",...},...] where pId is parent node's id). It is possible to replace the default `id` and `pId` keys by providing object to `treeDataSimpleMode` | false\|Array<{ id: string, pId: string, rootPId: null }> | false |
|
||||
| treeDefaultExpandAll | Whether to expand all treeNodes by default | boolean | false |
|
||||
| treeDefaultExpandedKeys | Default expanded treeNodes | string\[] | - |
|
||||
| treeExpandedKeys | Set expanded keys | string\[] | - |
|
||||
| treeNodeFilterProp | Will be used for filtering if `filterTreeNode` returns true | string | 'value' |
|
||||
| treeNodeLabelProp | Will render as content of select | string | 'title' |
|
||||
| value | To set the current selected treeNode(s). | string\|string\[] | - |
|
||||
| onChange | A callback function, can be executed when selected treeNodes or input value change | function(value, label, extra) | - |
|
||||
| onSearch | A callback function, can be executed when the search input changes. | function(value: string) | - |
|
||||
| onSelect | A callback function, can be executed when you select a treeNode. | function(value, node, extra) | - |
|
||||
| onTreeExpand | A callback function, can be executed when treeNode expanded | function(expandedKeys) | - |
|
||||
|
||||
### Tree Methods
|
||||
|
||||
|
@ -7,6 +7,7 @@ import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
import warning from '../_util/warning';
|
||||
import Icon from '../icon';
|
||||
import { AntTreeNodeProps } from '../tree';
|
||||
import omit from 'omit.js';
|
||||
|
||||
export { TreeNode, TreeSelectProps } from './interface';
|
||||
|
||||
@ -74,22 +75,26 @@ export default class TreeSelect extends React.Component<TreeSelectProps, any> {
|
||||
notFoundContent,
|
||||
dropdownStyle,
|
||||
dropdownClassName,
|
||||
suffixIcon,
|
||||
...restProps
|
||||
} = this.props;
|
||||
const rest = omit(restProps, ['inputIcon', 'removeIcon', 'clearIcon', 'switcherIcon']);
|
||||
|
||||
const cls = classNames({
|
||||
[`${prefixCls}-lg`]: size === 'large',
|
||||
[`${prefixCls}-sm`]: size === 'small',
|
||||
}, className);
|
||||
|
||||
let checkable = restProps.treeCheckable;
|
||||
let checkable = rest.treeCheckable;
|
||||
if (checkable) {
|
||||
checkable = <span className={`${prefixCls}-tree-checkbox-inner`} />;
|
||||
}
|
||||
|
||||
const inputIcon = (
|
||||
<Icon type="down" className={`${prefixCls}-arrow-icon`} />
|
||||
);
|
||||
const inputIcon = suffixIcon && (
|
||||
React.isValidElement<{ className?: string }>(suffixIcon)
|
||||
? React.cloneElement(suffixIcon) : suffixIcon) || (
|
||||
<Icon type="down" className={`${prefixCls}-arrow-icon`} />
|
||||
);
|
||||
|
||||
const removeIcon = (
|
||||
<Icon type="close" className={`${prefixCls}-remove-icon`} />
|
||||
@ -101,7 +106,11 @@ export default class TreeSelect extends React.Component<TreeSelectProps, any> {
|
||||
|
||||
return (
|
||||
<RcTreeSelect
|
||||
{...restProps}
|
||||
switcherIcon={this.renderSwitcherIcon}
|
||||
inputIcon={inputIcon}
|
||||
removeIcon={removeIcon}
|
||||
clearIcon={clearIcon}
|
||||
{...rest}
|
||||
dropdownClassName={classNames(dropdownClassName, `${prefixCls}-tree-dropdown`)}
|
||||
prefixCls={prefixCls}
|
||||
className={cls}
|
||||
@ -109,10 +118,6 @@ export default class TreeSelect extends React.Component<TreeSelectProps, any> {
|
||||
treeCheckable={checkable}
|
||||
notFoundContent={notFoundContent || locale.notFoundContent}
|
||||
ref={this.saveTreeSelect}
|
||||
switcherIcon={this.renderSwitcherIcon}
|
||||
inputIcon={inputIcon}
|
||||
removeIcon={removeIcon}
|
||||
clearIcon={clearIcon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -37,18 +37,21 @@ 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 |
|
||||
| size | 选择框大小,可选 `large` `small` | string | 'default' |
|
||||
| suffixIcon | 自定义的选择框后缀图标 | ReactNode | - |
|
||||
| treeCheckable | 显示 checkbox | boolean | false |
|
||||
| treeCheckStrictly | checkable 状态下节点选择完全受控(父子节点选中状态不再关联),会使得 `labelInValue` 强制为 true | boolean | false |
|
||||
| treeData | treeNodes 数据,如果设置则不需要手动构造 TreeNode 节点(value 在整个树范围内唯一) | array<{value, title, children, [disabled, disableCheckbox, selectable]}> | \[] |
|
||||
| treeDataSimpleMode | 使用简单格式的 treeData,具体设置参考可设置的类型 (此时 treeData 应变为这样的数据结构: [{id:1, pId:0, value:'1', title:"test1",...},...], `pId` 是父节点的 id) | false\|Array<{ id: string, pId: string, rootPId: null }> | false |
|
||||
| treeDefaultExpandAll | 默认展开所有树节点 | boolean | false |
|
||||
| treeDefaultExpandedKeys | 默认展开的树节点 | string\[] | - |
|
||||
| treeExpandedKeys | 设置展开的树节点 | string\[] | - |
|
||||
| treeNodeFilterProp | 输入项过滤对应的 treeNode 属性 | string | 'value' |
|
||||
| treeNodeLabelProp | 作为显示的 prop 设置 | string | 'title' |
|
||||
| value | 指定当前选中的条目 | string/string\[] | - |
|
||||
| onChange | 选中树节点时调用此函数 | function(value, label, extra) | - |
|
||||
| onSearch | 文本框值变化时回调 | function(value: string) | - |
|
||||
| onSelect | 被选中时调用 | function(value, node, extra) | - |
|
||||
| onTreeExpand | 展示节点时调用 | function(expandedKeys) | - |
|
||||
|
||||
### Tree 方法
|
||||
|
||||
|
@ -52,4 +52,5 @@ export interface TreeSelectProps extends AbstractSelectProps {
|
||||
labelInValue?: boolean;
|
||||
treeCheckStrictly?: boolean;
|
||||
getPopupContainer?: (triggerNode: Element) => HTMLElement;
|
||||
suffixIcon?: React.ReactNode;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ Uploading is the process of publishing information (web pages, text, pictures, v
|
||||
| showUploadList | Whether to show default upload list, could be an object to specify `showPreviewIcon` and `showRemoveIcon` individually | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean } | true |
|
||||
| supportServerRender | Need to be turned on while the server side is rendering. | boolean | false |
|
||||
| withCredentials | ajax upload with cookie sent | boolean | false |
|
||||
| openFileDialogOnClick | click open file dialog | boolean | true |
|
||||
| onChange | A callback function, can be executed when uploading state is changing. See [onChange](#onChange) | Function | - |
|
||||
| onPreview | A callback function, will be executed when file link or preview icon is clicked. | Function(file) | - |
|
||||
| onRemove | A callback function, will be executed when removing file button is clicked, remove event will be prevented when return value is `false` or a Promise which resolve(false) or reject. | Function(file): `boolean | Promise` | - |
|
||||
|
@ -37,6 +37,7 @@ title: Upload
|
||||
| showUploadList | 是否展示 uploadList, 可设为一个对象,用于单独设定 showPreviewIcon 和 showRemoveIcon | Boolean or { showPreviewIcon?: boolean, showRemoveIcon?: boolean } | true |
|
||||
| supportServerRender | 服务端渲染时需要打开这个 | boolean | false |
|
||||
| withCredentials | 上传请求时是否携带 cookie | boolean | false |
|
||||
| openFileDialogOnClick | 点击打开文件对话框 | boolean | true |
|
||||
| onChange | 上传文件改变时的状态,详见 [onChange](#onChange) | Function | 无 |
|
||||
| onPreview | 点击文件链接或预览图标时的回调 | Function(file) | 无 |
|
||||
| onRemove | 点击移除文件时的回调,返回值为 false 时不移除。支持返回一个 Promise 对象,Promise 对象 resolve(false) 或 reject 时不移除。 | Function(file): `boolean | Promise` | 无 |
|
||||
|
@ -74,6 +74,7 @@ export interface UploadProps {
|
||||
prefixCls?: string;
|
||||
customRequest?: (option: any) => void;
|
||||
withCredentials?: boolean;
|
||||
openFileDialogOnClick?: boolean;
|
||||
locale?: UploadLocale;
|
||||
}
|
||||
|
||||
|
10
package.json
10
package.json
@ -65,24 +65,24 @@
|
||||
"rc-dropdown": "~2.2.0",
|
||||
"rc-editor-mention": "^1.0.2",
|
||||
"rc-form": "^2.1.0",
|
||||
"rc-input-number": "~4.0.0",
|
||||
"rc-input-number": "~4.1.0",
|
||||
"rc-menu": "~7.4.1",
|
||||
"rc-notification": "~3.2.0",
|
||||
"rc-pagination": "~1.17.0",
|
||||
"rc-progress": "~2.2.2",
|
||||
"rc-rate": "~2.4.0",
|
||||
"rc-select": "~8.2.6",
|
||||
"rc-select": "~8.3.0",
|
||||
"rc-slider": "~8.6.0",
|
||||
"rc-steps": "~3.3.0",
|
||||
"rc-switch": "~1.7.0",
|
||||
"rc-switch": "~1.8.0",
|
||||
"rc-table": "~6.3.2",
|
||||
"rc-tabs": "~9.4.0",
|
||||
"rc-time-picker": "~3.4.0",
|
||||
"rc-tooltip": "~3.7.0",
|
||||
"rc-tree": "~1.14.5",
|
||||
"rc-tree-select": "~2.2.0",
|
||||
"rc-tree-select": "~2.3.0",
|
||||
"rc-trigger": "^2.5.4",
|
||||
"rc-upload": "~2.5.0",
|
||||
"rc-upload": "~2.6.0",
|
||||
"rc-util": "^4.0.4",
|
||||
"react-lazy-load": "^3.0.12",
|
||||
"react-lifecycles-compat": "^3.0.2",
|
||||
|
Loading…
Reference in New Issue
Block a user