feat: TreeSelect support status (#34093)

* feat: TreeSelect support status

* chore: code clean

* docs: add demo version
This commit is contained in:
MadCcc 2022-02-17 16:41:12 +08:00 committed by GitHub
parent 533bc8740a
commit fb1955573e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 466 additions and 3 deletions

View File

@ -18836,7 +18836,7 @@ exports[`renders ./components/form/demo/validate-static.md extend context correc
class="ant-form-item-control-input-content"
>
<div
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow"
class="ant-select ant-tree-select ant-select-status-warning ant-select-has-feedback ant-select-single ant-select-allow-clear ant-select-show-arrow"
>
<div
class="ant-select-selector"
@ -18967,6 +18967,29 @@ exports[`renders ./components/form/demo/validate-static.md extend context correc
/>
</svg>
</span>
<span
class="ant-select-feedback-icon"
>
<span
aria-label="exclamation-circle"
class="anticon anticon-exclamation-circle"
role="img"
>
<svg
aria-hidden="true"
data-icon="exclamation-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 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"
/>
</svg>
</span>
</span>
</span>
</div>
</div>

View File

@ -8012,7 +8012,7 @@ exports[`renders ./components/form/demo/validate-static.md correctly 1`] = `
class="ant-form-item-control-input-content"
>
<div
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow"
class="ant-select ant-tree-select ant-select-status-warning ant-select-has-feedback ant-select-single ant-select-allow-clear ant-select-show-arrow"
>
<div
class="ant-select-selector"
@ -8066,6 +8066,29 @@ exports[`renders ./components/form/demo/validate-static.md correctly 1`] = `
/>
</svg>
</span>
<span
class="ant-select-feedback-icon"
>
<span
aria-label="exclamation-circle"
class="anticon anticon-exclamation-circle"
role="img"
>
<svg
aria-hidden="true"
data-icon="exclamation-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 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"
/>
</svg>
</span>
</span>
</span>
</div>
</div>

View File

@ -1571,6 +1571,249 @@ Array [
]
`;
exports[`renders ./components/tree-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-tree-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-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"
>
Error
</span>
</div>
<div>
<div
class="ant-select-dropdown ant-tree-select-dropdown ant-select-dropdown-empty"
style="opacity:0;pointer-events:none"
>
<div>
<div
class="ant-select-empty"
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-tree-select ant-select-status-warning ant-select-multiple ant-select-show-search"
style="width:100%"
>
<div
class="ant-select-selector"
>
<div
class="ant-select-selection-overflow"
>
<div
class="ant-select-selection-overflow-item ant-select-selection-overflow-item-suffix"
style="opacity:1"
>
<div
class="ant-select-selection-search"
style="width:0"
>
<input
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
aria-hidden="true"
class="ant-select-selection-search-mirror"
>
 
</span>
</div>
</div>
</div>
<span
class="ant-select-selection-placeholder"
>
Warning multiple
</span>
</div>
<div>
<div
class="ant-select-dropdown ant-tree-select-dropdown ant-select-dropdown-empty"
style="opacity:0;pointer-events:none"
>
<div>
<div
class="ant-select-empty"
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>
</div>
</div>
</div>
`;
exports[`renders ./components/tree-select/demo/suffix.md extend context correctly 1`] = `
<div
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"

View File

@ -399,6 +399,129 @@ Array [
]
`;
exports[`renders ./components/tree-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-tree-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-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"
>
Error
</span>
</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-tree-select ant-select-status-warning ant-select-multiple ant-select-show-search"
style="width:100%"
>
<div
class="ant-select-selector"
>
<div
class="ant-select-selection-overflow"
>
<div
class="ant-select-selection-overflow-item ant-select-selection-overflow-item-suffix"
style="opacity:1"
>
<div
class="ant-select-selection-search"
style="width:0"
>
<input
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
aria-hidden="true"
class="ant-select-selection-search-mirror"
>
 
</span>
</div>
</div>
</div>
<span
class="ant-select-selection-placeholder"
>
Warning multiple
</span>
</div>
</div>
</div>
</div>
`;
exports[`renders ./components/tree-select/demo/suffix.md correctly 1`] = `
<div
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"

View File

@ -0,0 +1,33 @@
---
order: 9
version: 4.19.0
title:
zh-CN: 自定义状态
en-US: Status
---
## zh-CN
使用 `status` 为 TreeSelect 添加状态,可选 `error` 或者 `warning`
## en-US
Add status to TreeSelect with `status`, which could be `error` or `warning`.
```tsx
import { TreeSelect, Space } from 'antd';
const Status: React.FC = () => (
<Space direction="vertical" style={{ width: '100%' }}>
<TreeSelect status="error" style={{ width: '100%' }} placeholder="Error" />
<TreeSelect
status="warning"
style={{ width: '100%' }}
multiple
placeholder="Warning multiple"
/>
</Space>
);
ReactDOM.render(<Status />, mountNode);
```

View File

@ -43,6 +43,7 @@ Tree selection control.
| showCheckedStrategy | The way show selected item in box when `treeCheckable` set. **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) | `TreeSelect.SHOW_ALL` \| `TreeSelect.SHOW_PARENT` \| `TreeSelect.SHOW_CHILD` | `TreeSelect.SHOW_CHILD` | |
| showSearch | Support search or not | boolean | single: false \| multiple: true | |
| size | To set the size of the select input | `large` \| `middle` \| `small` | - | |
| status | Set validation status | 'error' \| 'warning' | - | 4.19.0 |
| suffixIcon | The custom suffix icon,you must set `showArrow` to `true` manually in multiple selection mode | ReactNode | - | |
| switcherIcon | customize collapse \| expand icon of tree node | ReactNode | - | |
| tagRender | Customize tag render when `multiple` | (props) => ReactNode | - | |

View File

@ -10,6 +10,7 @@ import classNames from 'classnames';
import omit from 'rc-util/lib/omit';
import type { BaseOptionType, DefaultOptionType } from 'rc-tree-select/lib/TreeSelect';
import type { BaseSelectRef } from 'rc-select';
import { useContext } from 'react';
import { ConfigContext } from '../config-provider';
import devWarning from '../_util/devWarning';
import { AntTreeNodeProps, TreeProps } from '../tree';
@ -17,6 +18,8 @@ import getIcons from '../select/utils/iconUtil';
import renderSwitcherIcon from '../tree/utils/iconUtil';
import SizeContext, { SizeType } from '../config-provider/SizeContext';
import { getTransitionName, getTransitionDirection, SelectCommonPlacement } from '../_util/motion';
import { FormItemStatusContext } from '../form/context';
import { getMergedStatus, getStatusClassNames, InputStatus } from '../_util/statusUtils';
type RawValue = string | number;
@ -46,6 +49,7 @@ export interface TreeSelectProps<
placement?: SelectCommonPlacement;
bordered?: boolean;
treeLine?: TreeProps['showLine'];
status?: InputStatus;
}
const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionType = BaseOptionType>(
@ -67,6 +71,8 @@ const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionTyp
treeIcon = false,
transitionName,
choiceTransitionName = '',
status: customStatus,
showArrow,
...props
}: TreeSelectProps<OptionType>,
ref: React.Ref<BaseSelectRef>,
@ -96,11 +102,19 @@ const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionTyp
});
const isMultiple = !!(treeCheckable || multiple);
const mergedShowArrow = showArrow !== undefined ? showArrow : props.loading || !isMultiple;
// ===================== Status =====================
const { status: contextStatus, hasFeedback } = useContext(FormItemStatusContext);
const mergedStatus = getMergedStatus(contextStatus, customStatus);
// ===================== Icons =====================
const { suffixIcon, removeIcon, clearIcon } = getIcons({
...props,
multiple: isMultiple,
status: mergedStatus,
showArrow: mergedShowArrow,
hasFeedback,
prefixCls,
});
@ -140,6 +154,7 @@ const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionTyp
[`${prefixCls}-rtl`]: direction === 'rtl',
[`${prefixCls}-borderless`]: !bordered,
},
getStatusClassNames(prefixCls, mergedStatus, hasFeedback),
className,
);
const rootPrefixCls = getPrefixCls();
@ -177,6 +192,7 @@ const InternalTreeSelect = <OptionType extends BaseOptionType | DefaultOptionTyp
getTransitionDirection(placement),
transitionName,
)}
showArrow={hasFeedback || showArrow}
/>
);
};

View File

@ -44,6 +44,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/Ax4DA0njr/TreeSelect.svg
| showCheckedStrategy | 配置 `treeCheckable` 时,定义选中项回填的方式。`TreeSelect.SHOW_ALL`: 显示所有选中节点(包括父节点)。`TreeSelect.SHOW_PARENT`: 只显示父节点(当父节点下所有子节点都选中时)。 默认只显示子节点 | `TreeSelect.SHOW_ALL` \| `TreeSelect.SHOW_PARENT` \| `TreeSelect.SHOW_CHILD` | `TreeSelect.SHOW_CHILD` | |
| showSearch | 是否支持搜索框 | boolean | 单选false \| 多选true | |
| size | 选择框大小 | `large` \| `middle` \| `small` | - | |
| status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 |
| suffixIcon | 自定义的选择框后缀图标, 多选模式下必须同时设置 `showArrow` 为 true | ReactNode | - | |
| switcherIcon | 自定义树节点的展开/折叠图标 | ReactNode | - | |
| tagRender | 自定义 tag 内容,多选时生效 | (props) => ReactNode | - | |

View File

@ -2,6 +2,6 @@ import '../../style/index.less';
import './index.less';
// style dependencies
// deps-lint-skip: tree
// deps-lint-skip: tree, form
import '../../select/style';
import '../../empty/style';