mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 17:44:35 +08:00
feat: select support status (#34084)
* feat: select support status * test: fix lint
This commit is contained in:
parent
8054abe81f
commit
2258335e6c
@ -14510,7 +14510,7 @@ exports[`renders ./components/form/demo/validate-other.md extend context correct
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-select-has-feedback ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -18483,7 +18483,7 @@ exports[`renders ./components/form/demo/validate-static.md extend context correc
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||
class="ant-select ant-select-status-error ant-select-has-feedback ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -18637,6 +18637,29 @@ exports[`renders ./components/form/demo/validate-static.md extend context correc
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-feedback-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="close-circle"
|
||||
class="anticon anticon-close-circle"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="close-circle"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -5922,7 +5922,7 @@ exports[`renders ./components/form/demo/validate-other.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-single ant-select-show-arrow"
|
||||
class="ant-select ant-select-has-feedback ant-select-single ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -7789,7 +7789,7 @@ exports[`renders ./components/form/demo/validate-static.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||
class="ant-select ant-select-status-error ant-select-has-feedback ant-select-single ant-select-allow-clear ant-select-show-arrow"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
@ -7844,6 +7844,29 @@ exports[`renders ./components/form/demo/validate-static.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-feedback-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="close-circle"
|
||||
class="anticon anticon-close-circle"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="close-circle"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7589,6 +7589,259 @@ Array [
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/select/demo/status.md extend context correctly 1`] = `
|
||||
<div
|
||||
class="ant-space ant-space-vertical"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="margin-bottom:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-status-error ant-select-single ant-select-show-arrow"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant="undefined_list_0"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
type="search"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-item-empty"
|
||||
id="undefined_list"
|
||||
role="listbox"
|
||||
>
|
||||
<div
|
||||
class="ant-empty ant-empty-normal ant-empty-small"
|
||||
>
|
||||
<div
|
||||
class="ant-empty-image"
|
||||
>
|
||||
<svg
|
||||
class="ant-empty-img-simple"
|
||||
height="41"
|
||||
viewBox="0 0 64 41"
|
||||
width="64"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
transform="translate(0 1)"
|
||||
>
|
||||
<ellipse
|
||||
class="ant-empty-img-simple-ellipse"
|
||||
cx="32"
|
||||
cy="33"
|
||||
rx="32"
|
||||
ry="7"
|
||||
/>
|
||||
<g
|
||||
class="ant-empty-img-simple-g"
|
||||
fill-rule="nonzero"
|
||||
>
|
||||
<path
|
||||
d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"
|
||||
/>
|
||||
<path
|
||||
class="ant-empty-img-simple-path"
|
||||
d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="ant-empty-description"
|
||||
>
|
||||
No Data
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-select-suffix"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-status-warning ant-select-single ant-select-show-arrow"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant="undefined_list_0"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
type="search"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-dropdown ant-select-dropdown-empty"
|
||||
style="opacity:0;pointer-events:none"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-select-item-empty"
|
||||
id="undefined_list"
|
||||
role="listbox"
|
||||
>
|
||||
<div
|
||||
class="ant-empty ant-empty-normal ant-empty-small"
|
||||
>
|
||||
<div
|
||||
class="ant-empty-image"
|
||||
>
|
||||
<svg
|
||||
class="ant-empty-img-simple"
|
||||
height="41"
|
||||
viewBox="0 0 64 41"
|
||||
width="64"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
transform="translate(0 1)"
|
||||
>
|
||||
<ellipse
|
||||
class="ant-empty-img-simple-ellipse"
|
||||
cx="32"
|
||||
cy="33"
|
||||
rx="32"
|
||||
ry="7"
|
||||
/>
|
||||
<g
|
||||
class="ant-empty-img-simple-g"
|
||||
fill-rule="nonzero"
|
||||
>
|
||||
<path
|
||||
d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"
|
||||
/>
|
||||
<path
|
||||
class="ant-empty-img-simple-path"
|
||||
d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="ant-empty-description"
|
||||
>
|
||||
No Data
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-select-suffix"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/select/demo/suffix.md extend context correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
|
@ -2438,6 +2438,137 @@ Array [
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders ./components/select/demo/status.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-space ant-space-vertical"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
style="margin-bottom:8px"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-status-error ant-select-single ant-select-show-arrow"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant="undefined_list_0"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
type="search"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-select-suffix"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-space-item"
|
||||
>
|
||||
<div
|
||||
class="ant-select ant-select-status-warning ant-select-single ant-select-show-arrow"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-select-selector"
|
||||
>
|
||||
<span
|
||||
class="ant-select-selection-search"
|
||||
>
|
||||
<input
|
||||
aria-activedescendant="undefined_list_0"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="undefined_list"
|
||||
aria-haspopup="listbox"
|
||||
aria-owns="undefined_list"
|
||||
autocomplete="off"
|
||||
class="ant-select-selection-search-input"
|
||||
readonly=""
|
||||
role="combobox"
|
||||
style="opacity:0"
|
||||
type="search"
|
||||
unselectable="on"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
class="ant-select-selection-placeholder"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="ant-select-arrow"
|
||||
style="user-select:none;-webkit-user-select:none"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-select-suffix"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/select/demo/suffix.md correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
|
34
components/select/demo/status.md
Normal file
34
components/select/demo/status.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
order: 25
|
||||
version: 4.19.0
|
||||
title:
|
||||
zh-CN: 自定义状态
|
||||
en-US: Status
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `status` 为 Select 添加状态,可选 `error` 或者 `warning`。
|
||||
|
||||
## en-US
|
||||
|
||||
Add status to Select with `status`, which could be `error` or `warning`.
|
||||
|
||||
```tsx
|
||||
import { Select, Space } from 'antd';
|
||||
|
||||
const Status: React.FC = () => (
|
||||
<Space direction="vertical" style={{ width: '100%' }}>
|
||||
<Select status="error" style={{ width: '100%' }} />
|
||||
<Select status="warning" style={{ width: '100%' }} />
|
||||
</Space>
|
||||
);
|
||||
|
||||
ReactDOM.render(<Status />, mountNode);
|
||||
```
|
||||
|
||||
```css
|
||||
#components-select-demo-status .ant-select {
|
||||
margin: 0;
|
||||
}
|
||||
```
|
@ -61,6 +61,7 @@ Select component to select value from options.
|
||||
| showArrow | Whether to show the drop-down arrow | boolean | true(for single select), false(for multiple select) | |
|
||||
| showSearch | Whether show search input in single mode | boolean | false | |
|
||||
| size | Size of Select input | `large` \| `middle` \| `small` | `middle` | |
|
||||
| status | Set validation status | 'error' \| 'warning' | - | 4.19.0 |
|
||||
| suffixIcon | The custom suffix icon | ReactNode | - | |
|
||||
| tagRender | Customize tag render, only applies when `mode` is set to `multiple` or `tags` | (props) => ReactNode | - | |
|
||||
| tokenSeparators | Separator used to tokenize on `tag` and `multiple` mode | string\[] | - | |
|
||||
|
@ -6,9 +6,12 @@ import classNames from 'classnames';
|
||||
import RcSelect, { Option, OptGroup, SelectProps as RcSelectProps, BaseSelectRef } from 'rc-select';
|
||||
import type { BaseOptionType, DefaultOptionType } from 'rc-select/lib/Select';
|
||||
import { OptionProps } from 'rc-select/lib/Option';
|
||||
import { useContext } from 'react';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import getIcons from './utils/iconUtil';
|
||||
import SizeContext, { SizeType } from '../config-provider/SizeContext';
|
||||
import { FormItemStatusContext } from '../form/context';
|
||||
import { getMergedStatus, getStatusClassNames, InputStatus } from '../_util/statusUtils';
|
||||
import { getTransitionName, getTransitionDirection, SelectCommonPlacement } from '../_util/motion';
|
||||
|
||||
type RawValue = string | number;
|
||||
@ -42,6 +45,7 @@ export interface SelectProps<
|
||||
> {
|
||||
placement?: SelectCommonPlacement;
|
||||
mode?: 'multiple' | 'tags';
|
||||
status?: InputStatus;
|
||||
}
|
||||
|
||||
const SECRET_COMBOBOX_MODE_DO_NOT_USE = 'SECRET_COMBOBOX_MODE_DO_NOT_USE';
|
||||
@ -58,6 +62,8 @@ const InternalSelect = <OptionType extends BaseOptionType | DefaultOptionType =
|
||||
listItemHeight = 24,
|
||||
size: customizeSize,
|
||||
notFoundContent,
|
||||
status: customStatus,
|
||||
showArrow,
|
||||
...props
|
||||
}: SelectProps<OptionType>,
|
||||
ref: React.Ref<BaseSelectRef>,
|
||||
@ -90,6 +96,12 @@ const InternalSelect = <OptionType extends BaseOptionType | DefaultOptionType =
|
||||
}, [props.mode]);
|
||||
|
||||
const isMultiple = mode === 'multiple' || mode === 'tags';
|
||||
const mergedShowArrow =
|
||||
showArrow !== undefined ? showArrow : props.loading || !(isMultiple || mode === 'combobox');
|
||||
|
||||
// ===================== Validation Status =====================
|
||||
const { status: contextStatus, hasFeedback } = useContext(FormItemStatusContext);
|
||||
const mergedStatus = getMergedStatus(contextStatus, customStatus);
|
||||
|
||||
// ===================== Empty =====================
|
||||
let mergedNotFound: React.ReactNode;
|
||||
@ -105,6 +117,9 @@ const InternalSelect = <OptionType extends BaseOptionType | DefaultOptionType =
|
||||
const { suffixIcon, itemIcon, removeIcon, clearIcon } = getIcons({
|
||||
...props,
|
||||
multiple: isMultiple,
|
||||
status: mergedStatus,
|
||||
hasFeedback,
|
||||
showArrow: mergedShowArrow,
|
||||
prefixCls,
|
||||
});
|
||||
|
||||
@ -122,6 +137,7 @@ const InternalSelect = <OptionType extends BaseOptionType | DefaultOptionType =
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
[`${prefixCls}-borderless`]: !bordered,
|
||||
},
|
||||
getStatusClassNames(prefixCls, mergedStatus, hasFeedback),
|
||||
className,
|
||||
);
|
||||
|
||||
@ -160,6 +176,7 @@ const InternalSelect = <OptionType extends BaseOptionType | DefaultOptionType =
|
||||
className={mergedClassName}
|
||||
getPopupContainer={getPopupContainer || getContextPopupContainer}
|
||||
dropdownClassName={rcSelectRtlDropDownClassName}
|
||||
showArrow={hasFeedback || showArrow}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -62,6 +62,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
|
||||
| showArrow | 是否显示下拉小箭头 | boolean | 单选为 true,多选为 false | |
|
||||
| showSearch | 使单选模式可搜索 | boolean | false | |
|
||||
| size | 选择框大小 | `large` \| `middle` \| `small` | `middle` | |
|
||||
| status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 |
|
||||
| suffixIcon | 自定义的选择框后缀图标 | ReactNode | - | |
|
||||
| tagRender | 自定义 tag 内容 render,仅在 `mode` 为 `multiple` 或 `tags` 时生效 | (props) => ReactNode | - | |
|
||||
| tokenSeparators | 在 `tags` 和 `multiple` 模式下自动分词的分隔符 | string\[] | - | |
|
||||
|
@ -3,6 +3,7 @@
|
||||
@import '../../input/style/mixin';
|
||||
@import './single';
|
||||
@import './multiple';
|
||||
@import './status';
|
||||
|
||||
@select-prefix-cls: ~'@{ant-prefix}-select';
|
||||
@select-height-without-border: @input-height-base - 2 * @border-width-base;
|
||||
@ -120,7 +121,8 @@
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: @control-padding-horizontal - 1px;
|
||||
width: @font-size-sm;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: @font-size-sm;
|
||||
margin-top: (-@font-size-sm / 2);
|
||||
color: @disabled-color;
|
||||
|
@ -3,3 +3,5 @@ import './index.less';
|
||||
|
||||
// style dependencies
|
||||
import '../../empty/style';
|
||||
|
||||
// deps-lint-skip: form
|
||||
|
80
components/select/style/status.less
Normal file
80
components/select/style/status.less
Normal file
@ -0,0 +1,80 @@
|
||||
@import '../../input/style/mixin';
|
||||
|
||||
@select-prefix-cls: ~'@{ant-prefix}-select';
|
||||
|
||||
.status-color(
|
||||
@text-color;
|
||||
@border-color;
|
||||
@background-color;
|
||||
@hoverBorderColor;
|
||||
@outlineColor;
|
||||
) {
|
||||
&.@{select-prefix-cls}:not(.@{select-prefix-cls}-disabled):not(.@{select-prefix-cls}-customize-input) {
|
||||
.@{select-prefix-cls}-selector {
|
||||
background-color: @background-color;
|
||||
border-color: @border-color !important;
|
||||
}
|
||||
&.@{select-prefix-cls}-open .@{select-prefix-cls}-selector,
|
||||
&.@{select-prefix-cls}-focused .@{select-prefix-cls}-selector {
|
||||
.active(@border-color, @hoverBorderColor, @outlineColor);
|
||||
}
|
||||
}
|
||||
|
||||
.@{select-prefix-cls}-feedback-icon {
|
||||
color: @text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.select-status-base(@prefix-cls) {
|
||||
.@{prefix-cls} {
|
||||
&-status-error {
|
||||
.status-color(@error-color, @error-color, @select-background, @error-color-hover, @error-color-outline);
|
||||
}
|
||||
|
||||
&-status-warning {
|
||||
.status-color(@warning-color, @warning-color, @input-bg, @warning-color-hover, @warning-color-outline);
|
||||
}
|
||||
|
||||
&-status-success {
|
||||
.@{prefix-cls}-feedback-icon {
|
||||
color: @success-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-status-validating {
|
||||
.@{prefix-cls}-feedback-icon {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-status-error,
|
||||
&-status-warning,
|
||||
&-status-success,
|
||||
&-status-validating {
|
||||
&.@{prefix-cls}-has-feedback {
|
||||
//.@{prefix-cls}-arrow,
|
||||
.@{prefix-cls}-clear {
|
||||
right: 32px;
|
||||
}
|
||||
|
||||
.@{prefix-cls}-selection-selected-value {
|
||||
padding-right: 42px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-feedback-icon {
|
||||
font-size: @font-size-base;
|
||||
text-align: center;
|
||||
visibility: visible;
|
||||
animation: zoomIn 0.3s @ease-out-back;
|
||||
pointer-events: none;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select-status-base(@select-prefix-cls);
|
@ -1,10 +1,13 @@
|
||||
import * as React from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
import DownOutlined from '@ant-design/icons/DownOutlined';
|
||||
import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
|
||||
import CheckOutlined from '@ant-design/icons/CheckOutlined';
|
||||
import CloseOutlined from '@ant-design/icons/CloseOutlined';
|
||||
import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
|
||||
import SearchOutlined from '@ant-design/icons/SearchOutlined';
|
||||
import { ValidateStatus } from '../../form/FormItem';
|
||||
import { getFeedbackIcon } from '../../_util/statusUtils';
|
||||
|
||||
export default function getIcons({
|
||||
suffixIcon,
|
||||
@ -13,7 +16,10 @@ export default function getIcons({
|
||||
removeIcon,
|
||||
loading,
|
||||
multiple,
|
||||
hasFeedback,
|
||||
status,
|
||||
prefixCls,
|
||||
showArrow,
|
||||
}: {
|
||||
suffixIcon?: React.ReactNode;
|
||||
clearIcon?: React.ReactNode;
|
||||
@ -21,7 +27,10 @@ export default function getIcons({
|
||||
removeIcon?: React.ReactNode;
|
||||
loading?: boolean;
|
||||
multiple?: boolean;
|
||||
hasFeedback?: boolean;
|
||||
status?: ValidateStatus;
|
||||
prefixCls: string;
|
||||
showArrow?: boolean;
|
||||
}) {
|
||||
// Clear Icon
|
||||
let mergedClearIcon = clearIcon;
|
||||
@ -29,19 +38,27 @@ export default function getIcons({
|
||||
mergedClearIcon = <CloseCircleFilled />;
|
||||
}
|
||||
|
||||
// Validation Feedback Icon
|
||||
const getSuffixIconNode = (arrowIcon?: ReactNode) => (
|
||||
<>
|
||||
{showArrow !== false && arrowIcon}
|
||||
{hasFeedback && getFeedbackIcon(prefixCls, status)}
|
||||
</>
|
||||
);
|
||||
|
||||
// Arrow item icon
|
||||
let mergedSuffixIcon = null;
|
||||
if (suffixIcon !== undefined) {
|
||||
mergedSuffixIcon = suffixIcon;
|
||||
mergedSuffixIcon = getSuffixIconNode(suffixIcon);
|
||||
} else if (loading) {
|
||||
mergedSuffixIcon = <LoadingOutlined spin />;
|
||||
mergedSuffixIcon = getSuffixIconNode(<LoadingOutlined spin />);
|
||||
} else {
|
||||
const iconCls = `${prefixCls}-suffix`;
|
||||
mergedSuffixIcon = ({ open, showSearch }: { open: boolean; showSearch: boolean }) => {
|
||||
if (open && showSearch) {
|
||||
return <SearchOutlined className={iconCls} />;
|
||||
return getSuffixIconNode(<SearchOutlined className={iconCls} />);
|
||||
}
|
||||
return <DownOutlined className={iconCls} />;
|
||||
return getSuffixIconNode(<DownOutlined className={iconCls} />);
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user