feat: TreeSelect use virtual scroll (#19040)

* use new rc-tree-select

* support not found

* add switch icon support

* support function

* support selection motion

* show search icon if open

* clean up

* fix lint

* fix lint
This commit is contained in:
二货机器人 2019-09-27 22:31:28 -05:00 committed by GitHub
parent 808d4075dc
commit 4907996b97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 1318 additions and 1328 deletions

View File

@ -233,49 +233,60 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
<div
class="ant-form-item-control-input"
>
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled"
role="combobox"
tabindex="0"
<div
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
>
<span
class="ant-select-selection ant-select-selection--single"
<div
class="ant-select-selector"
>
<span
class="ant-select-selection__rendered"
class="ant-select-selection-search"
>
<span
class="ant-select-selection__placeholder"
<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"
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-arrow"
style="outline:none"
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"
role="img"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-arrow-icon"
role="img"
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<svg
aria-hidden="true"
class=""
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>
<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>
</span>
</div>
</div>
</div>
</div>
@ -301,50 +312,61 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
<span
class="ant-input-group ant-input-group-compact"
>
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled"
role="combobox"
<div
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
style="width:30%"
tabindex="0"
>
<span
class="ant-select-selection ant-select-selection--single"
<div
class="ant-select-selector"
>
<span
class="ant-select-selection__rendered"
class="ant-select-selection-search"
>
<span
class="ant-select-selection__placeholder"
<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"
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-arrow"
style="outline:none"
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"
role="img"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-arrow-icon"
role="img"
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<svg
aria-hidden="true"
class=""
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>
<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>
</span>
</div>
<div
class="ant-select ant-select-auto-complete ant-select-single ant-select-show-search"
>
@ -474,50 +496,61 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
<span
class="ant-input-group ant-input-group-compact"
>
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled"
role="combobox"
<div
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
style="width:30%"
tabindex="0"
>
<span
class="ant-select-selection ant-select-selection--single"
<div
class="ant-select-selector"
>
<span
class="ant-select-selection__rendered"
class="ant-select-selection-search"
>
<span
class="ant-select-selection__placeholder"
<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"
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-arrow"
style="outline:none"
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"
role="img"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-arrow-icon"
role="img"
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<svg
aria-hidden="true"
class=""
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>
<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>
</span>
</div>
<div
class="ant-select ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
>
@ -599,50 +632,61 @@ exports[`renders ./components/auto-complete/demo/form-debug.md correctly 1`] = `
<span
class="ant-input-group ant-input-group-compact"
>
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled"
role="combobox"
<div
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
style="width:30%"
tabindex="0"
>
<span
class="ant-select-selection ant-select-selection--single"
<div
class="ant-select-selector"
>
<span
class="ant-select-selection__rendered"
class="ant-select-selection-search"
>
<span
class="ant-select-selection__placeholder"
<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"
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-arrow"
style="outline:none"
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"
role="img"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-arrow-icon"
role="img"
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<svg
aria-hidden="true"
class=""
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>
<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>
</span>
</div>
<div
class="ant-select ant-select-auto-complete ant-select-single ant-select-customize-input ant-select-show-search"
>

View File

@ -17134,267 +17134,321 @@ exports[`ConfigProvider components Tree prefixCls 1`] = `
`;
exports[`ConfigProvider components TreeSelect configProvider 1`] = `
Array [
<span
aria-controls="rc-tree-select-list_3"
aria-expanded="true"
aria-haspopup="listbox"
aria-owns="rc-tree-select-list_3"
class="config-select config-select-open config-select-focused config-select-enabled"
role="combobox"
tabindex="0"
<div
class="config-select config-tree-select config-select-single config-select-show-arrow config-select-open"
>
<div
class="config-select-selector"
>
<span
class="config-select-selection config-select-selection--single"
class="config-select-selection-search"
>
<span
class="config-select-selection__rendered"
>
<span
class="config-select-selection__placeholder"
/>
</span>
<span
class="config-select-arrow"
style="outline:none"
>
<span
aria-label="down"
class="anticon anticon-down config-select-arrow-icon"
role="img"
>
<svg
aria-hidden="true"
class=""
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>
<input
aria-activedescendant="undefined_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-owns="undefined_list"
autocomplete="off"
class="config-select-selection-search-input"
role="combobox"
style="opacity:0"
value=""
/>
</span>
</span>,
<span
class="config-select-selection-placeholder"
/>
</div>
<div>
<div
class="config-select-dropdown config-select-tree-dropdown config-select-dropdown--single config-select-dropdown-placement-bottomLeft "
style="visibility:hidden;max-height:100vh;overflow:auto"
class="config-select-dropdown config-tree-select-dropdown config-select-dropdown-placement-bottomLeft "
>
<div
id="rc-tree-select-list_3"
role="listbox"
tabindex="-1"
>
<ul
class="config-select-tree"
role="tree"
unselectable="on"
>
<li
class="config-select-tree-treenode-switcher-close"
role="treeitem"
<div>
<div>
<div
role="tree"
>
<span
class="config-select-tree-switcher config-select-tree-switcher-noop"
<input
disabled=""
style="width:0;height:0;display:flex;overflow:hidden;opacity:0;border:0;padding:0;margin:0"
value=""
/>
<span
class="config-select-tree-node-content-wrapper config-select-tree-node-content-wrapper-normal"
title="bamboo"
>
<span
class="config-select-tree-title"
</div>
<div
class="config-select-tree-list config-select-tree"
style="height:256px"
>
<div>
<div
class="config-select-tree-list-holder-inner"
style="display:flex;flex-direction:column"
>
bamboo
</span>
</span>
</li>
</ul>
<div
class="config-select-tree-treenode config-select-tree-treenode-switcher-close"
>
<span
class="config-select-tree-switcher config-select-tree-switcher-noop"
/>
<span
class="config-select-tree-node-content-wrapper config-select-tree-node-content-wrapper-normal"
title="bamboo"
>
<span
class="config-select-tree-title"
>
bamboo
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>,
]
</div>
<span
aria-hidden="true"
class="config-select-arrow"
style="user-select:none;-webkit-user-select:none"
unselectable="on"
>
<span
aria-label="down"
class="anticon anticon-down"
role="img"
>
<svg
aria-hidden="true"
class=""
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>
`;
exports[`ConfigProvider components TreeSelect normal 1`] = `
Array [
<span
aria-controls="rc-tree-select-list_1"
aria-expanded="true"
aria-haspopup="listbox"
aria-owns="rc-tree-select-list_1"
class="ant-select ant-select-open ant-select-focused ant-select-enabled"
role="combobox"
tabindex="0"
<div
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow ant-select-open"
>
<div
class="ant-select-selector"
>
<span
class="ant-select-selection ant-select-selection--single"
class="ant-select-selection-search"
>
<span
class="ant-select-selection__rendered"
>
<span
class="ant-select-selection__placeholder"
/>
</span>
<span
class="ant-select-arrow"
style="outline:none"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-arrow-icon"
role="img"
>
<svg
aria-hidden="true"
class=""
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>
<input
aria-activedescendant="undefined_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-owns="undefined_list"
autocomplete="off"
class="ant-select-selection-search-input"
role="combobox"
style="opacity:0"
value=""
/>
</span>
</span>,
<span
class="ant-select-selection-placeholder"
/>
</div>
<div>
<div
class="ant-select-dropdown ant-select-tree-dropdown ant-select-dropdown--single ant-select-dropdown-placement-bottomLeft "
style="visibility:hidden;max-height:100vh;overflow:auto"
class="ant-select-dropdown ant-tree-select-dropdown ant-select-dropdown-placement-bottomLeft "
>
<div
id="rc-tree-select-list_1"
role="listbox"
tabindex="-1"
>
<ul
class="ant-select-tree"
role="tree"
unselectable="on"
>
<li
class="ant-select-tree-treenode-switcher-close"
role="treeitem"
<div>
<div>
<div
role="tree"
>
<span
class="ant-select-tree-switcher ant-select-tree-switcher-noop"
<input
disabled=""
style="width:0;height:0;display:flex;overflow:hidden;opacity:0;border:0;padding:0;margin:0"
value=""
/>
<span
class="ant-select-tree-node-content-wrapper ant-select-tree-node-content-wrapper-normal"
title="bamboo"
>
<span
class="ant-select-tree-title"
</div>
<div
class="ant-select-tree-list ant-select-tree"
style="height:256px"
>
<div>
<div
class="ant-select-tree-list-holder-inner"
style="display:flex;flex-direction:column"
>
bamboo
</span>
</span>
</li>
</ul>
<div
class="ant-select-tree-treenode ant-select-tree-treenode-switcher-close"
>
<span
class="ant-select-tree-switcher ant-select-tree-switcher-noop"
/>
<span
class="ant-select-tree-node-content-wrapper ant-select-tree-node-content-wrapper-normal"
title="bamboo"
>
<span
class="ant-select-tree-title"
>
bamboo
</span>
</span>
</div>
</div>
</div>
</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"
role="img"
>
<svg
aria-hidden="true"
class=""
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>
`;
exports[`ConfigProvider components TreeSelect prefixCls 1`] = `
Array [
<span
aria-controls="rc-tree-select-list_2"
aria-expanded="true"
aria-haspopup="listbox"
aria-owns="rc-tree-select-list_2"
class="prefix-TreeSelect prefix-TreeSelect-open prefix-TreeSelect-focused prefix-TreeSelect-enabled"
role="combobox"
tabindex="0"
<div
class="prefix-TreeSelect prefix-TreeSelect-single prefix-TreeSelect-show-arrow prefix-TreeSelect-open"
>
<div
class="prefix-TreeSelect-selector"
>
<span
class="prefix-TreeSelect-selection prefix-TreeSelect-selection--single"
class="prefix-TreeSelect-selection-search"
>
<span
class="prefix-TreeSelect-selection__rendered"
>
<span
class="prefix-TreeSelect-selection__placeholder"
/>
</span>
<span
class="prefix-TreeSelect-arrow"
style="outline:none"
>
<span
aria-label="down"
class="anticon anticon-down prefix-TreeSelect-arrow-icon"
role="img"
>
<svg
aria-hidden="true"
class=""
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>
<input
aria-activedescendant="undefined_list_0"
aria-autocomplete="list"
aria-controls="undefined_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-owns="undefined_list"
autocomplete="off"
class="prefix-TreeSelect-selection-search-input"
role="combobox"
style="opacity:0"
value=""
/>
</span>
</span>,
<span
class="prefix-TreeSelect-selection-placeholder"
/>
</div>
<div>
<div
class="prefix-TreeSelect-dropdown prefix-TreeSelect-tree-dropdown prefix-TreeSelect-dropdown--single prefix-TreeSelect-dropdown-placement-bottomLeft "
style="visibility:hidden;max-height:100vh;overflow:auto"
class="prefix-TreeSelect-dropdown prefix-TreeSelect-dropdown prefix-TreeSelect-dropdown-placement-bottomLeft "
>
<div
id="rc-tree-select-list_2"
role="listbox"
tabindex="-1"
>
<ul
class="prefix-TreeSelect-tree"
role="tree"
unselectable="on"
>
<li
class="prefix-TreeSelect-tree-treenode-switcher-close"
role="treeitem"
<div>
<div>
<div
role="tree"
>
<span
class="prefix-TreeSelect-tree-switcher prefix-TreeSelect-tree-switcher-noop"
<input
disabled=""
style="width:0;height:0;display:flex;overflow:hidden;opacity:0;border:0;padding:0;margin:0"
value=""
/>
<span
class="prefix-TreeSelect-tree-node-content-wrapper prefix-TreeSelect-tree-node-content-wrapper-normal"
title="bamboo"
>
<span
class="prefix-TreeSelect-tree-title"
</div>
<div
class="prefix-TreeSelect-tree-list prefix-TreeSelect-tree"
style="height:256px"
>
<div>
<div
class="prefix-TreeSelect-tree-list-holder-inner"
style="display:flex;flex-direction:column"
>
bamboo
</span>
</span>
</li>
</ul>
<div
class="prefix-TreeSelect-tree-treenode prefix-TreeSelect-tree-treenode-switcher-close"
>
<span
class="prefix-TreeSelect-tree-switcher prefix-TreeSelect-tree-switcher-noop"
/>
<span
class="prefix-TreeSelect-tree-node-content-wrapper prefix-TreeSelect-tree-node-content-wrapper-normal"
title="bamboo"
>
<span
class="prefix-TreeSelect-tree-title"
>
bamboo
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>,
]
</div>
<span
aria-hidden="true"
class="prefix-TreeSelect-arrow"
style="user-select:none;-webkit-user-select:none"
unselectable="on"
>
<span
aria-label="down"
class="anticon anticon-down"
role="img"
>
<svg
aria-hidden="true"
class=""
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>
`;
exports[`ConfigProvider components Upload configProvider 1`] = `

View File

@ -157,50 +157,61 @@ exports[`renders ./components/empty/demo/config-provider.md correctly 1`] = `
<h3>
TreeSelect
</h3>
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled"
role="combobox"
<div
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
style="width:200px"
tabindex="0"
>
<span
class="ant-select-selection ant-select-selection--single"
<div
class="ant-select-selector"
>
<span
class="ant-select-selection__rendered"
class="ant-select-selection-search"
>
<span
class="ant-select-selection__placeholder"
<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"
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-arrow"
style="outline:none"
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"
role="img"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-arrow-icon"
role="img"
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<svg
aria-hidden="true"
class=""
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>
<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>
</span>
</div>
<h3>
Cascader
</h3>

View File

@ -554,50 +554,61 @@ exports[`renders ./components/input/demo/align.md correctly 1`] = `
</span>
</span>
</div>
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled"
role="combobox"
<div
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
style="width:100px"
tabindex="0"
>
<span
class="ant-select-selection ant-select-selection--single"
<div
class="ant-select-selector"
>
<span
class="ant-select-selection__rendered"
class="ant-select-selection-search"
>
<span
class="ant-select-selection__placeholder"
<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"
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-arrow"
style="outline:none"
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"
role="img"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-arrow-icon"
role="img"
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<svg
aria-hidden="true"
class=""
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>
<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>
</span>
</div>
<span
class="ant-cascader-picker"
tabindex="0"

View File

@ -4,11 +4,13 @@ import * as React from 'react';
import omit from 'omit.js';
import classNames from 'classnames';
import RcSelect, { Option, OptGroup, SelectProps as RcSelectProps } from 'rc-select';
import { Down, Loading, Check, Close, CloseCircleFilled } from '@ant-design/icons';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import getIcons from './utils/iconUtil';
type RawValue = string | number;
export type Size = 'large' | 'default' | 'small';
export type OptionType = typeof Option;
export interface LabeledValue {
@ -21,7 +23,7 @@ export type SelectValue = RawValue | RawValue[] | LabeledValue | LabeledValue[];
export interface InternalSelectProps<VT> extends Omit<RcSelectProps<VT>, 'mode'> {
suffixIcon?: React.ReactNode;
size?: 'large' | 'default' | 'small';
size?: Size;
mode?: 'multiple' | 'tags' | 'SECRET_COMBOBOX_MODE_DO_NOT_USE';
}
@ -73,19 +75,19 @@ class Select<ValueType extends SelectValue = SelectValue> extends React.Componen
return mode;
};
renderSelect = ({ getPrefixCls, renderEmpty }: ConfigConsumerProps) => {
renderSelect = ({
getPopupContainer: getContextPopupContainer,
getPrefixCls,
renderEmpty,
}: ConfigConsumerProps) => {
const {
prefixCls: customizePrefixCls,
suffixIcon,
clearIcon,
menuItemSelectedIcon,
removeIcon,
loading,
notFoundContent,
className,
size,
listHeight = 256,
listItemHeight = 32,
getPopupContainer,
} = this.props as InternalSelectProps<ValueType>;
const prefixCls = getPrefixCls('select', customizePrefixCls);
@ -104,40 +106,19 @@ class Select<ValueType extends SelectValue = SelectValue> extends React.Componen
}
// ===================== Icons =====================
// Clear Icon
let mergedClearIcon = clearIcon;
if (!clearIcon) {
mergedClearIcon = <CloseCircleFilled />;
}
const { suffixIcon, itemIcon, removeIcon, clearIcon } = getIcons({
...this.props,
multiple: isMultiple,
});
// Arrow item icon
let mergedSuffixIcon = null;
if (suffixIcon !== undefined) {
mergedSuffixIcon = suffixIcon;
} else if (loading) {
mergedSuffixIcon = <Loading spin />;
} else {
mergedSuffixIcon = <Down />;
}
// Checked item icon
let mergedItemIcon = null;
if (menuItemSelectedIcon !== undefined) {
mergedItemIcon = menuItemSelectedIcon;
} else if (isMultiple) {
mergedItemIcon = <Check />;
} else {
mergedItemIcon = null;
}
let mergedRemoveIcon = null;
if (removeIcon !== undefined) {
mergedRemoveIcon = removeIcon;
} else {
mergedRemoveIcon = <Close />;
}
const selectProps = omit(this.props, ['prefixCls', 'suffixIcon', 'size']);
const selectProps = omit(this.props, [
'prefixCls',
'suffixIcon',
'itemIcon',
'removeIcon',
'clearIcon',
'size',
]);
const mergedClassName = classNames(className, {
[`${prefixCls}-lg`]: size === 'large',
@ -152,12 +133,13 @@ class Select<ValueType extends SelectValue = SelectValue> extends React.Componen
listItemHeight={listItemHeight}
mode={mode}
prefixCls={prefixCls}
inputIcon={mergedSuffixIcon}
menuItemSelectedIcon={mergedItemIcon}
removeIcon={mergedRemoveIcon}
clearIcon={mergedClearIcon}
inputIcon={suffixIcon}
menuItemSelectedIcon={itemIcon}
removeIcon={removeIcon}
clearIcon={clearIcon}
notFoundContent={mergedNotFound}
className={mergedClassName}
getPopupContainer={getPopupContainer || getContextPopupContainer}
/>
);
};

View File

@ -71,7 +71,7 @@
.iconfont-mixin();
position: absolute;
top: 55%;
top: 53%;
right: @control-padding-horizontal - 1px;
width: @font-size-sm;
height: @font-size-sm;
@ -80,12 +80,15 @@
font-size: @font-size-sm;
line-height: 1;
text-align: center;
transform-origin: 50% 50%;
transition: transform 0.3s;
// transform-origin: 50% 50%;
pointer-events: none;
.@{select-prefix-cls}-open & {
transform: rotate(180deg);
.anticon {
transition: transform 0.3s;
.@{select-prefix-cls}-open &.anticon-down {
transform: rotate(180deg);
}
}
}

View File

@ -0,0 +1,63 @@
import React from 'react';
import { Down, Loading, Check, Close, CloseCircleFilled, Search } from '@ant-design/icons';
export default function getIcons({
suffixIcon,
clearIcon,
menuItemSelectedIcon,
removeIcon,
loading,
multiple,
}: {
suffixIcon?: React.ReactNode;
clearIcon?: React.ReactNode;
menuItemSelectedIcon?: React.ReactNode;
removeIcon?: React.ReactNode;
loading?: boolean;
multiple?: boolean;
}) {
// Clear Icon
let mergedClearIcon = clearIcon;
if (!clearIcon) {
mergedClearIcon = <CloseCircleFilled />;
}
// Arrow item icon
let mergedSuffixIcon = null;
if (suffixIcon !== undefined) {
mergedSuffixIcon = suffixIcon;
} else if (loading) {
mergedSuffixIcon = <Loading spin />;
} else {
mergedSuffixIcon = ({ open, showSearch }: { open: boolean; showSearch: boolean }) => {
if (open && showSearch) {
return <Search />;
}
return <Down />;
};
}
// Checked item icon
let mergedItemIcon = null;
if (menuItemSelectedIcon !== undefined) {
mergedItemIcon = menuItemSelectedIcon;
} else if (multiple) {
mergedItemIcon = <Check />;
} else {
mergedItemIcon = null;
}
let mergedRemoveIcon = null;
if (removeIcon !== undefined) {
mergedRemoveIcon = removeIcon;
} else {
mergedRemoveIcon = <Close />;
}
return {
clearIcon: mergedClearIcon,
suffixIcon: mergedSuffixIcon,
itemIcon: mergedItemIcon,
removeIcon: mergedRemoveIcon,
};
}

View File

@ -1,328 +1,353 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders ./components/tree-select/demo/async.md correctly 1`] = `
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled"
role="combobox"
<div
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
style="width:300px"
tabindex="0"
>
<span
class="ant-select-selection ant-select-selection--single"
<div
class="ant-select-selector"
>
<span
class="ant-select-selection__rendered"
class="ant-select-selection-search"
>
<span
class="ant-select-selection__placeholder"
>
Please select
</span>
<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"
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-arrow"
style="outline:none"
class="ant-select-selection-placeholder"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-arrow-icon"
role="img"
Please select
</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"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<svg
aria-hidden="true"
class=""
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>
<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>
</span>
</div>
`;
exports[`renders ./components/tree-select/demo/basic.md correctly 1`] = `
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled ant-select-allow-clear"
role="combobox"
<div
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
style="width:300px"
tabindex="0"
>
<span
class="ant-select-selection ant-select-selection--single"
<div
class="ant-select-selector"
>
<span
class="ant-select-selection__rendered"
class="ant-select-selection-search"
>
<span
class="ant-select-selection__placeholder"
>
Please select
</span>
<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"
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-arrow"
style="outline:none"
class="ant-select-selection-placeholder"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-arrow-icon"
role="img"
Please select
</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"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<svg
aria-hidden="true"
class=""
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>
<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>
</span>
</div>
`;
exports[`renders ./components/tree-select/demo/checkable.md correctly 1`] = `
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled"
role="combobox"
<div
class="ant-select ant-tree-select ant-select-multiple ant-select-show-search"
style="width:300px"
tabindex="-1"
>
<span
class="ant-select-selection ant-select-selection--multiple"
<div
class="ant-select-selector"
>
<ul
class="ant-select-selection__rendered"
role="menubar"
>
<li
class="ant-select-selection__choice"
role="menuitem"
style="user-select:none;-webkit-user-select:none"
title="Node1"
unselectable="unselectable"
>
<span
class="ant-select-selection__choice__remove"
>
<span
aria-label="close"
class="anticon anticon-close ant-select-remove-icon"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="close"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
/>
</svg>
</span>
</span>
<span
class="ant-select-selection__choice__content"
>
Node1
</span>
</li>
<li
class="ant-select-search ant-select-search--inline"
>
<span
class="ant-select-search__field__wrap"
>
<input
aria-autocomplete="list"
aria-label="filter select"
aria-multiline="false"
class="ant-select-search__field"
type="text"
value=""
/>
<span
class="ant-select-search__field__mirror"
>
 
</span>
</span>
</li>
</ul>
<span
class="ant-select-search__field__placeholder"
style="display:none"
class="ant-select-selection-item"
>
Please select
<span
class="ant-select-selection-item-content"
>
Node1
</span>
<span
aria-hidden="true"
class="ant-select-selection-item-remove"
style="user-select:none;-webkit-user-select:none"
unselectable="on"
>
<span
aria-label="close"
class="anticon anticon-close"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="close"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
/>
</svg>
</span>
</span>
</span>
</span>
</span>
<span
class="ant-select-selection-search"
style="width:0"
>
<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"
role="combobox"
style="opacity:0"
value=""
/>
<span
aria-hidden="true"
class="ant-select-selection-search-mirror"
>
 
</span>
</span>
</div>
</div>
`;
exports[`renders ./components/tree-select/demo/multiple.md correctly 1`] = `
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled ant-select-allow-clear"
role="combobox"
<div
class="ant-select ant-tree-select ant-select-multiple ant-select-allow-clear ant-select-show-search"
multiple=""
style="width:300px"
tabindex="-1"
>
<span
class="ant-select-selection ant-select-selection--multiple"
<div
class="ant-select-selector"
>
<ul
class="ant-select-selection__rendered"
role="menubar"
>
<li
class="ant-select-search ant-select-search--inline"
>
<span
class="ant-select-search__field__wrap"
>
<input
aria-autocomplete="list"
aria-label="filter select"
aria-multiline="false"
class="ant-select-search__field"
type="text"
value=""
/>
<span
class="ant-select-search__field__mirror"
>
 
</span>
</span>
</li>
</ul>
<span
class="ant-select-search__field__placeholder"
style="display:block"
class="ant-select-selection-search"
style="width:0"
>
<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"
role="combobox"
style="opacity:0"
value=""
/>
<span
aria-hidden="true"
class="ant-select-selection-search-mirror"
>
 
</span>
</span>
<span
class="ant-select-selection-placeholder"
>
Please select
</span>
</span>
</span>
</div>
</div>
`;
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"
<div
class="ant-select ant-tree-select ant-select-single ant-select-allow-clear ant-select-show-arrow ant-select-show-search"
style="width:300px"
tabindex="0"
>
<span
class="ant-select-selection ant-select-selection--single"
<div
class="ant-select-selector"
>
<span
class="ant-select-selection__rendered"
class="ant-select-selection-search"
>
<span
class="ant-select-selection__placeholder"
>
Please select
</span>
<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"
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-arrow"
style="outline:none"
class="ant-select-selection-placeholder"
>
<span
aria-label="smile"
class="anticon anticon-smile"
role="img"
Please select
</span>
</div>
<span
aria-hidden="true"
class="ant-select-arrow"
style="user-select:none;-webkit-user-select:none"
unselectable="on"
>
<span
aria-label="smile"
class="anticon anticon-smile"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="smile"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<svg
aria-hidden="true"
class=""
data-icon="smile"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-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 01248.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 01249 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 01775.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 01775 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 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"
/>
</svg>
</span>
<path
d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-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 01248.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 01249 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 01775.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 01775 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 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"
/>
</svg>
</span>
</span>
</span>
</div>
`;
exports[`renders ./components/tree-select/demo/treeData.md correctly 1`] = `
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled"
role="combobox"
<div
class="ant-select ant-tree-select ant-select-single ant-select-show-arrow"
style="width:300px"
tabindex="0"
>
<span
class="ant-select-selection ant-select-selection--single"
<div
class="ant-select-selector"
>
<span
class="ant-select-selection__rendered"
class="ant-select-selection-search"
>
<span
class="ant-select-selection__placeholder"
>
Please select
</span>
<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"
role="combobox"
style="opacity:0"
value=""
/>
</span>
<span
class="ant-select-arrow"
style="outline:none"
class="ant-select-selection-placeholder"
>
<span
aria-label="down"
class="anticon anticon-down ant-select-arrow-icon"
role="img"
Please select
</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"
role="img"
>
<svg
aria-hidden="true"
class=""
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<svg
aria-hidden="true"
class=""
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>
<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>
</span>
</div>
`;

View File

@ -1,93 +1,84 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TreeSelect TreeSelect Custom Icons should support customized icons 1`] = `
<span
aria-haspopup="listbox"
class="ant-select ant-select-enabled ant-select-allow-clear"
role="combobox"
tabindex="-1"
<div
class="ant-select ant-tree-select ant-select-multiple ant-select-allow-clear ant-select-show-search"
>
<span
class="ant-select-selection ant-select-selection--multiple"
<div
class="ant-select-selector"
>
<ul
class="ant-select-selection__rendered"
role="menubar"
>
<li
class="ant-select-selection__choice"
role="menuitem"
style="user-select: none;"
unselectable="unselectable"
>
<span
class="ant-select-selection__choice__remove"
>
<span>
remove
</span>
</span>
<span
class="ant-select-selection__choice__content"
>
leaf1
</span>
</li>
<li
class="ant-select-selection__choice"
role="menuitem"
style="user-select: none;"
unselectable="unselectable"
>
<span
class="ant-select-selection__choice__remove"
>
<span>
remove
</span>
</span>
<span
class="ant-select-selection__choice__content"
>
leaf2
</span>
</li>
<li
class="ant-select-search ant-select-search--inline"
>
<span
class="ant-select-search__field__wrap"
>
<input
aria-autocomplete="list"
aria-label="filter select"
aria-multiline="false"
class="ant-select-search__field"
style="width: 0px;"
type="text"
value=""
/>
<span
class="ant-select-search__field__mirror"
>
 
</span>
</span>
</li>
</ul>
<span
class="ant-select-selection__clear"
class="ant-select-selection-item"
>
<span>
clear
<span
class="ant-select-selection-item-content"
>
my leaf
</span>
<span
aria-hidden="true"
class="ant-select-selection-item-remove"
style="user-select: none;"
unselectable="on"
>
<span>
remove
</span>
</span>
</span>
<span
class="ant-select-search__field__placeholder"
style="display: none;"
class="ant-select-selection-item"
>
Please select
<span
class="ant-select-selection-item-content"
>
your leaf
</span>
<span
aria-hidden="true"
class="ant-select-selection-item-remove"
style="user-select: none;"
unselectable="on"
>
<span>
remove
</span>
</span>
</span>
<span
class="ant-select-selection-search"
style="width: 0px;"
>
<input
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
aria-autocomplete="list"
aria-controls="rc_select_TEST_OR_SSR_list"
aria-haspopup="listbox"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="ant-select-selection-search-input"
id="rc_select_TEST_OR_SSR"
role="combobox"
style="opacity: 0;"
value=""
/>
<span
aria-hidden="true"
class="ant-select-selection-search-mirror"
>
 
</span>
</span>
</div>
<span
aria-hidden="true"
class="ant-select-clear"
style="user-select: none;"
unselectable="on"
>
<span>
clear
</span>
</span>
</span>
</div>
`;

View File

@ -8,16 +8,6 @@ describe('TreeSelect', () => {
focusTest(TreeSelect);
mountTest(TreeSelect);
describe('showSearch', () => {
it('keep default logic', () => {
const single = mount(<TreeSelect open />);
expect(single.find('.ant-select-search__field').length).toBeFalsy();
const multiple = mount(<TreeSelect multiple open />);
expect(multiple.find('.ant-select-search__field').length).toBeTruthy();
});
});
describe('TreeSelect Custom Icons', () => {
it('should support customized icons', () => {
const wrapper = mount(

View File

@ -1,21 +1,40 @@
import * as React from 'react';
import RcTreeSelect, { TreeNode, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from 'rc-tree-select';
import RcTreeSelect, {
TreeNode,
SHOW_ALL,
SHOW_PARENT,
SHOW_CHILD,
TreeSelectProps as RcTreeSelectProps,
} from 'rc-tree-select';
import classNames from 'classnames';
import omit from 'omit.js';
import { Loading, CaretDown, Down, Close, CloseCircleFilled } from '@ant-design/icons';
import { TreeSelectProps, TreeNodeValue } from './interface';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import collapseMotion from '../_util/motion';
import warning from '../_util/warning';
import { cloneElement } from '../_util/reactNode';
import { AntTreeNodeProps } from '../tree';
import { Size } from '../select';
import getIcons from '../select/utils/iconUtil';
import renderSwitcherIcon from '../tree/utils/iconUtil';
export { TreeNode, TreeSelectProps } from './interface';
type RawValue = string | number;
export default class TreeSelect<T extends TreeNodeValue> extends React.Component<
TreeSelectProps<T>,
any
> {
export interface LabeledValue {
key?: string;
value: RawValue;
label: React.ReactNode;
}
export type SelectValue = RawValue | RawValue[] | LabeledValue | LabeledValue[];
export interface TreeSelectProps<T>
extends Omit<
RcTreeSelectProps<T>,
'showTreeIcon' | 'treeMotion' | 'inputIcon' | 'mode' | 'getInputElement' | 'backfill'
> {
size?: Size;
}
class TreeSelect<T> extends React.Component<TreeSelectProps<T>, {}> {
static TreeNode = TreeNode;
static SHOW_ALL = SHOW_ALL;
@ -29,7 +48,7 @@ export default class TreeSelect<T extends TreeNodeValue> extends React.Component
choiceTransitionName: 'zoom',
};
private rcTreeSelect: any;
selectRef = React.createRef<RcTreeSelect>();
constructor(props: TreeSelectProps<T>) {
super(props);
@ -41,28 +60,18 @@ export default class TreeSelect<T extends TreeNodeValue> extends React.Component
);
}
saveTreeSelect = (node: typeof RcTreeSelect) => {
this.rcTreeSelect = node;
};
focus() {
this.rcTreeSelect.focus();
if (this.selectRef.current) {
this.selectRef.current.focus();
}
}
blur() {
this.rcTreeSelect.blur();
if (this.selectRef.current) {
this.selectRef.current.blur();
}
}
renderSwitcherIcon = (prefixCls: string, { isLeaf, loading }: AntTreeNodeProps) => {
if (loading) {
return <Loading className={`${prefixCls}-switcher-loading-icon`} />;
}
if (isLeaf) {
return null;
}
return <CaretDown className={`${prefixCls}-switcher-icon`} />;
};
renderTreeSelect = ({
getPopupContainer: getContextPopupContainer,
getPrefixCls,
@ -70,21 +79,25 @@ export default class TreeSelect<T extends TreeNodeValue> extends React.Component
}: ConfigConsumerProps) => {
const {
prefixCls: customizePrefixCls,
className,
size,
className,
treeCheckable,
multiple,
listHeight = 256,
listItemHeight = 32,
notFoundContent,
dropdownStyle,
dropdownClassName,
suffixIcon,
removeIcon,
clearIcon,
switcherIcon,
treeLine,
getPopupContainer,
...restProps
dropdownClassName,
} = this.props;
const rest = omit(restProps, ['inputIcon', 'removeIcon', 'clearIcon', 'switcherIcon']);
const prefixCls = getPrefixCls('select', customizePrefixCls);
const cls = classNames(
const treePrefixCls = getPrefixCls('select-tree', customizePrefixCls);
const treeSelectPrefixCls = getPrefixCls('tree-select', customizePrefixCls);
const mergedClassName = classNames(
!customizePrefixCls && treeSelectPrefixCls,
{
[`${prefixCls}-lg`]: size === 'large',
[`${prefixCls}-sm`]: size === 'small',
@ -92,53 +105,61 @@ export default class TreeSelect<T extends TreeNodeValue> extends React.Component
className,
);
// showSearch: single - false, multiple - true
let { showSearch } = restProps;
if (!('showSearch' in restProps)) {
showSearch = !!(restProps.multiple || restProps.treeCheckable);
const mergedDropdownClassName = classNames(
dropdownClassName,
`${treeSelectPrefixCls}-dropdown`,
);
const isMultiple = !!(treeCheckable || multiple);
// ===================== Icons =====================
const { suffixIcon, itemIcon, removeIcon, clearIcon } = getIcons({
...this.props,
multiple: isMultiple,
});
// ===================== Empty =====================
let mergedNotFound;
if (notFoundContent !== undefined) {
mergedNotFound = notFoundContent;
} else {
mergedNotFound = renderEmpty('Select');
}
let checkable = rest.treeCheckable;
if (checkable) {
checkable = <span className={`${prefixCls}-tree-checkbox-inner`} />;
}
const inputIcon = suffixIcon ? (
cloneElement(suffixIcon)
) : (
<Down className={`${prefixCls}-arrow-icon`} />
);
const finalRemoveIcon = removeIcon ? (
cloneElement(removeIcon)
) : (
<Close className={`${prefixCls}-remove-icon`} />
);
const finalClearIcon = clearIcon ? (
cloneElement(clearIcon)
) : (
<CloseCircleFilled className={`${prefixCls}-clear-icon`} />
);
// ==================== Render =====================
const selectProps = omit(this.props, [
'prefixCls',
'suffixIcon',
'itemIcon',
'removeIcon',
'clearIcon',
'switcherIcon',
'size',
]);
return (
<RcTreeSelect
switcherIcon={(nodeProps: AntTreeNodeProps) =>
this.renderSwitcherIcon(prefixCls, nodeProps)
}
inputIcon={inputIcon}
removeIcon={finalRemoveIcon}
clearIcon={finalClearIcon}
{...rest}
showSearch={showSearch}
getPopupContainer={getPopupContainer || getContextPopupContainer}
dropdownClassName={classNames(dropdownClassName, `${prefixCls}-tree-dropdown`)}
{...selectProps}
ref={this.selectRef}
prefixCls={prefixCls}
className={cls}
dropdownStyle={{ maxHeight: '100vh', overflow: 'auto', ...dropdownStyle }}
treeCheckable={checkable}
notFoundContent={notFoundContent || renderEmpty('Select')}
ref={this.saveTreeSelect}
className={mergedClassName}
listHeight={listHeight}
listItemHeight={listItemHeight}
treeCheckable={
treeCheckable ? <span className={`${prefixCls}-tree-checkbox-inner`} /> : treeCheckable
}
inputIcon={suffixIcon}
menuItemSelectedIcon={itemIcon}
removeIcon={removeIcon}
clearIcon={clearIcon}
switcherIcon={(nodeProps: AntTreeNodeProps) =>
renderSwitcherIcon(treePrefixCls, switcherIcon, treeLine, nodeProps)
}
showTreeIcon={false}
notFoundContent={mergedNotFound}
getPopupContainer={getPopupContainer || getContextPopupContainer}
treeMotion={collapseMotion}
dropdownClassName={mergedDropdownClassName}
/>
);
};
@ -147,3 +168,7 @@ export default class TreeSelect<T extends TreeNodeValue> extends React.Component
return <ConfigConsumer>{this.renderTreeSelect}</ConfigConsumer>;
}
}
export { TreeNode };
export default TreeSelect;

View File

@ -1,66 +0,0 @@
import * as React from 'react';
import { SelectProps } from '../select';
export type TreeNode = TreeNodeNormal | TreeNodeSimpleMode;
export type TreeNodeValue = string | number | string[] | number[];
export interface TreeNodeNormal {
value: TreeNodeValue;
/**
* @deprecated Please use `title` instead.
*/
label?: React.ReactNode;
title?: React.ReactNode;
key: string;
isLeaf?: boolean;
disabled?: boolean;
disableCheckbox?: boolean;
selectable?: boolean;
children?: TreeNodeNormal[];
}
export interface TreeNodeSimpleMode {
/* It is possible to change `id` and `pId` prop keys using TreeDataSimpleMode so those keys can be anything */
[key: string]: string | boolean | React.ReactNode;
}
export interface TreeDataSimpleMode {
id?: string;
pId?: string;
rootPId?: string;
}
export interface TreeSelectProps<T extends TreeNodeValue> extends Omit<SelectProps<T>, 'onChange'> {
autoFocus?: boolean;
defaultValue?: T;
dropdownStyle?: React.CSSProperties;
filterTreeNode?: (inputValue: string, treeNode: any) => boolean | boolean;
labelInValue?: boolean;
loadData?: (node: any) => void;
multiple?: boolean;
notFoundContent?: React.ReactNode;
onChange?: (value: T, label: any, extra: any) => void;
onSearch?: (value: any) => void;
onSelect?: (value: any) => void;
onTreeExpand?: (keys: Array<string>) => void;
onFocus?: React.FocusEventHandler<HTMLInputElement>;
onBlur?: React.FocusEventHandler<HTMLInputElement>;
searchPlaceholder?: string;
searchValue?: string;
showCheckedStrategy?: 'SHOW_ALL' | 'SHOW_PARENT' | 'SHOW_CHILD';
suffixIcon?: React.ReactNode;
removeIcon?: React.ReactNode;
clearIcon?: React.ReactNode;
treeCheckable?: boolean | React.ReactNode;
treeCheckStrictly?: boolean;
treeData?: Array<TreeNode>;
treeDataSimpleMode?: boolean | TreeDataSimpleMode;
treeDefaultExpandAll?: boolean;
treeDefaultExpandedKeys?: Array<string>;
treeExpandedKeys?: Array<string>;
treeIcon?: boolean;
treeNodeFilterProp?: string;
treeNodeLabelProp?: string;
value?: T;
}

View File

@ -1,191 +1,36 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@import '../../tree/style/mixin';
@import '../../tree/style/index';
@import '../../checkbox/style/mixin';
@select-prefix-cls: ~'@{ant-prefix}-select';
@tree-select-prefix-cls: ~'@{ant-prefix}-tree-select';
@select-tree-prefix-cls: ~'@{ant-prefix}-select-tree';
.antCheckboxFn(@checkbox-prefix-cls: ~'@{ant-prefix}-select-tree-checkbox');
.antCheckboxFn(@checkbox-prefix-cls: ~'@{select-tree-prefix-cls}-checkbox');
.@{select-tree-prefix-cls} {
.reset-component;
.@{tree-select-prefix-cls} {
// ======================= Dropdown =======================
&-dropdown {
padding: @padding-xs (@padding-xs / 2) 0;
margin: 0;
margin-top: -4px;
padding: 0 4px;
li {
margin: 8px 0;
padding: 0;
white-space: nowrap;
list-style: none;
outline: 0;
&.filter-node {
> span {
font-weight: 500;
}
}
ul {
margin: 0;
padding: 0 0 0 18px;
}
.@{select-tree-prefix-cls}-node-content-wrapper {
display: inline-block;
width: ~'calc(100% - 24px)';
margin: 0;
padding: 3px 5px;
color: @text-color;
text-decoration: none;
border-radius: @border-radius-sm;
cursor: pointer;
transition: all 0.3s;
&:hover {
background-color: @item-hover-bg;
}
&.@{select-tree-prefix-cls}-node-selected {
background-color: @primary-2;
}
}
span {
&.@{select-tree-prefix-cls}-checkbox {
margin: 0 4px 0 0;
+ .@{select-tree-prefix-cls}-node-content-wrapper {
width: ~'calc(100% - 46px)';
}
}
&.@{select-tree-prefix-cls}-switcher,
&.@{select-tree-prefix-cls}-iconEle {
display: inline-block;
width: 24px;
height: 24px;
margin: 0;
line-height: 22px;
text-align: center;
vertical-align: middle;
border: 0 none;
outline: none;
cursor: pointer;
}
&.@{select-prefix-cls}-icon_loading {
.@{select-prefix-cls}-switcher-loading-icon {
position: absolute;
left: 0;
display: inline-block;
color: @primary-color;
font-size: 14px;
transform: none;
svg {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
}
}
&.@{select-tree-prefix-cls}-switcher {
position: relative;
&.@{select-tree-prefix-cls}-switcher-noop {
cursor: auto;
}
&.@{select-tree-prefix-cls}-switcher_open {
.antTreeSwitcherIcon();
}
&.@{select-tree-prefix-cls}-switcher_close {
.antTreeSwitcherIcon();
.@{select-prefix-cls}-switcher-icon {
svg {
transform: rotate(-90deg);
}
}
}
// ======================== Tree ========================
.@{select-tree-prefix-cls} {
border-radius: 0;
&.@{select-tree-prefix-cls}-switcher_open,
&.@{select-tree-prefix-cls}-switcher_close {
.@{select-prefix-cls}-switcher-loading-icon {
position: absolute;
left: 0;
display: inline-block;
width: 24px;
height: 24px;
color: @primary-color;
font-size: 14px;
transform: none;
svg {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
&-list-holder-inner {
align-items: stretch;
.@{select-tree-prefix-cls}-treenode {
padding-bottom: @padding-xs;
.@{select-tree-prefix-cls}-node-content-wrapper {
flex: auto;
}
}
}
}
}
.@{select-tree-prefix-cls}-treenode-loading {
.@{select-tree-prefix-cls}-iconEle {
display: none;
}
}
&-child-tree {
display: none;
&-open {
display: block;
}
}
li&-treenode-disabled {
> span:not(.@{select-tree-prefix-cls}-switcher),
> .@{select-tree-prefix-cls}-node-content-wrapper,
> .@{select-tree-prefix-cls}-node-content-wrapper span {
color: @disabled-color;
cursor: not-allowed;
}
> .@{select-tree-prefix-cls}-node-content-wrapper:hover {
background: transparent;
}
}
&-icon__open {
margin-right: 2px;
vertical-align: top;
}
&-icon__close {
margin-right: 2px;
vertical-align: top;
}
}
.@{select-prefix-cls}-tree-dropdown {
.reset-component;
.@{select-prefix-cls}-dropdown-search {
position: sticky;
top: 0;
z-index: 1;
display: block;
padding: 4px;
background: @component-background;
.@{select-prefix-cls}-search__field__wrap {
width: 100%;
}
.@{select-prefix-cls}-search__field {
box-sizing: border-box;
width: 100%;
padding: 4px 7px;
border: @border-width-base @border-style-base @border-color-base;
border-radius: 4px;
outline: none;
}
&.@{select-prefix-cls}-search--hide {
display: none;
}
}
.@{select-prefix-cls}-not-found {
display: block;
padding: 7px 16px;
color: @disabled-color;
cursor: not-allowed;
}
}
// ========================== Tree ==========================
.antTreeFn(@select-tree-prefix-cls);

View File

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

View File

@ -15,7 +15,7 @@ import Tree, {
AntTreeNodeSelectedEvent,
AntTreeNode,
} from './Tree';
import { calcRangeKeys, convertDirectoryKeysToNodes } from './util';
import { calcRangeKeys, convertDirectoryKeysToNodes } from './utils/dictUtil';
export type ExpandAction = false | 'click' | 'doubleClick';

View File

@ -1,12 +1,12 @@
import * as React from 'react';
import RcTree, { TreeNode } from 'rc-tree';
import { Loading, File, MinusSquare, PlusSquare, CaretDownFilled } from '@ant-design/icons';
import classNames from 'classnames';
import { DataNode } from 'rc-tree/lib/interface';
import DirectoryTree from './DirectoryTree';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import collapseMotion from '../_util/motion';
import renderSwitcherIcon from './utils/iconUtil';
export interface AntdTreeNodeAttribute {
eventKey: string;
@ -187,38 +187,6 @@ export default class Tree extends React.Component<TreeProps, any> {
tree: any;
renderSwitcherIcon = (
prefixCls: string,
switcherIcon: React.ReactElement<any> | undefined,
{ isLeaf, expanded, loading }: AntTreeNodeProps,
) => {
const { showLine } = this.props;
if (loading) {
return <Loading className={`${prefixCls}-switcher-loading-icon`} />;
}
if (isLeaf) {
if (showLine) {
return <File className={`${prefixCls}-switcher-line-icon`} />;
}
return null;
}
const switcherCls = `${prefixCls}-switcher-icon`;
if (switcherIcon) {
const switcherOriginCls = switcherIcon.props.className || '';
return React.cloneElement(switcherIcon, {
className: classNames(switcherOriginCls, switcherCls),
});
}
if (showLine) {
return expanded ? (
<MinusSquare className={`${prefixCls}-switcher-line-icon`} />
) : (
<PlusSquare className={`${prefixCls}-switcher-line-icon`} />
);
}
return <CaretDownFilled className={switcherCls} />;
};
setTreeRef = (node: any) => {
this.tree = node;
};
@ -229,6 +197,7 @@ export default class Tree extends React.Component<TreeProps, any> {
prefixCls: customizePrefixCls,
className,
showIcon,
showLine,
switcherIcon,
blockNode,
children,
@ -246,7 +215,7 @@ export default class Tree extends React.Component<TreeProps, any> {
})}
checkable={checkable ? <span className={`${prefixCls}-checkbox-inner`} /> : checkable}
switcherIcon={(nodeProps: AntTreeNodeProps) =>
this.renderSwitcherIcon(prefixCls, switcherIcon, nodeProps)
renderSwitcherIcon(prefixCls, switcherIcon, showLine, nodeProps)
}
>
{children}

View File

@ -1,4 +1,4 @@
import { calcRangeKeys } from '../util';
import { calcRangeKeys } from '../utils/dictUtil';
describe('Tree util', () => {
it('calc range keys', () => {

View File

@ -10,200 +10,204 @@
.antCheckboxFn(@checkbox-prefix-cls: ~'@{ant-prefix}-tree-checkbox');
.@{tree-prefix-cls} {
.reset-component;
background: @component-background;
border-radius: @border-radius-base;
transition: background-color 0.3s;
.antTreeFn(@tree-prefix-cls) {
.@{tree-prefix-cls} {
.reset-component;
background: @component-background;
border-radius: @border-radius-base;
transition: background-color 0.3s;
&-focused:not(:hover):not(&-active-focused) {
background: @primary-1;
}
// =================== Virtual List ===================
&-list-holder-inner {
align-items: flex-start;
}
&.@{tree-prefix-cls}-block-node {
.@{tree-prefix-cls}-list-holder-inner {
align-items: stretch;
// >>> Title
.@{tree-prefix-cls}-node-content-wrapper {
flex: auto;
}
&-focused:not(:hover):not(&-active-focused) {
background: @primary-1;
}
}
// ===================== TreeNode =====================
.@{tree-node-prefix-cls} {
display: flex;
align-items: flex-start;
padding: 0 0 4px 0;
outline: none;
// =================== Virtual List ===================
&-list-holder-inner {
align-items: flex-start;
}
// Disabled
&-disabled {
// >>> Title
.@{tree-prefix-cls}-node-content-wrapper {
color: @disabled-color;
cursor: not-allowed;
&.@{tree-prefix-cls}-block-node {
.@{tree-prefix-cls}-list-holder-inner {
align-items: stretch;
&:hover {
background: transparent;
// >>> Title
.@{tree-prefix-cls}-node-content-wrapper {
flex: auto;
}
}
}
&-active .@{tree-prefix-cls}-node-content-wrapper {
background: @tree-node-hover-bg;
}
}
// ===================== TreeNode =====================
.@{tree-node-prefix-cls} {
display: flex;
align-items: flex-start;
padding: 0 0 (@padding-xs / 2) 0;
outline: none;
// >>> Indent
&-indent {
align-self: stretch;
user-select: none;
// Disabled
&-disabled {
// >>> Title
.@{tree-prefix-cls}-node-content-wrapper {
color: @disabled-color;
cursor: not-allowed;
&-unit {
display: inline-block;
width: @tree-title-height;
}
}
// >>> Switcher
& &-switcher {
.antTreeSwitcherIcon();
width: @tree-title-height;
height: @tree-title-height;
margin: 0;
line-height: @tree-title-height;
text-align: center;
cursor: pointer;
&-noop {
cursor: default;
}
&_close {
.@{tree-prefix-cls}-switcher-icon {
svg {
transform: rotate(-90deg);
&:hover {
background: transparent;
}
}
}
}
}
// >>> Checkbox
& &-checkbox {
top: initial;
margin: ((@tree-title-height - @checkbox-size) / 2) 8px 0 0;
}
// >>> Title
& &-node-content-wrapper {
min-height: @tree-title-height;
margin: 0;
padding: 0 4px;
color: inherit;
line-height: @tree-title-height;
background: transparent;
border-radius: @border-radius-sm;
cursor: pointer;
transition: all 0.3s;
&:hover {
background-color: @tree-node-hover-bg;
}
&.@{tree-prefix-cls}-node-selected {
background-color: @tree-node-selected-bg;
&-active .@{tree-prefix-cls}-node-content-wrapper {
background: @tree-node-hover-bg;
}
}
// Icon
.@{tree-prefix-cls}-iconEle {
display: inline-block;
// >>> Indent
&-indent {
align-self: stretch;
user-select: none;
&-unit {
display: inline-block;
width: @tree-title-height;
}
}
// >>> Switcher
& &-switcher {
.antTreeSwitcherIcon();
width: @tree-title-height;
height: @tree-title-height;
margin: 0;
line-height: @tree-title-height;
text-align: center;
vertical-align: top;
}
}
cursor: pointer;
// ===================== Loading ======================
.@{tree-node-prefix-cls}-loading {
// Icon
.@{tree-prefix-cls}-iconEle {
display: none;
}
}
&-noop {
cursor: default;
}
// ==================== Draggable =====================
&-node-content-wrapper[draggable='true'] {
line-height: @tree-title-height - 4px;
border-top: 2px transparent solid;
border-bottom: 2px transparent solid;
user-select: none;
}
.@{tree-node-prefix-cls}.drag-over {
> [draggable] {
color: white;
background-color: @primary-color;
opacity: 0.8;
}
}
.@{tree-node-prefix-cls}.drag-over-gap-top {
> [draggable] {
border-top-color: @primary-color;
}
}
.@{tree-node-prefix-cls}.drag-over-gap-bottom {
> [draggable] {
border-bottom-color: @primary-color;
}
}
// ==================== Show Line =====================
&-show-line {
// ================ Indent lines ================
.@{tree-prefix-cls}-indent {
&-unit {
position: relative;
height: 100%;
&::before {
position: absolute;
top: calc(100% - 4px);
right: -@tree-title-height / 2;
bottom: -@tree-title-height - 4px;
border-right: 1px solid @border-color-base;
content: '';
}
&-end {
&::before {
display: none;
&_close {
.@{tree-prefix-cls}-switcher-icon {
svg {
transform: rotate(-90deg);
}
}
}
}
/* Motion should hide line of measure */
.@{tree-node-prefix-cls}-motion:not(.@{tree-motion}-leave):not(.@{tree-motion}-appear-active) {
.@{tree-prefix-cls}-indent-unit {
&::before {
display: none;
}
// >>> Checkbox
& &-checkbox {
top: initial;
margin: ((@tree-title-height - @checkbox-size) / 2) 8px 0 0;
}
// >>> Title
& &-node-content-wrapper {
min-height: @tree-title-height;
margin: 0;
padding: 0 4px;
color: inherit;
line-height: @tree-title-height;
background: transparent;
border-radius: @border-radius-sm;
cursor: pointer;
transition: all 0.3s;
&:hover {
background-color: @tree-node-hover-bg;
}
&.@{tree-prefix-cls}-node-selected {
background-color: @tree-node-selected-bg;
}
// Icon
.@{tree-prefix-cls}-iconEle {
display: inline-block;
width: @tree-title-height;
height: @tree-title-height;
line-height: @tree-title-height;
text-align: center;
vertical-align: top;
}
}
// ============== Cover Background ==============
.@{tree-prefix-cls}-switcher {
z-index: 1;
background: @component-background;
// ===================== Loading ======================
.@{tree-node-prefix-cls}-loading {
// Icon
.@{tree-prefix-cls}-iconEle {
display: none;
}
}
// ==================== Draggable =====================
&-node-content-wrapper[draggable='true'] {
line-height: @tree-title-height - 4px;
border-top: 2px transparent solid;
border-bottom: 2px transparent solid;
user-select: none;
}
.@{tree-node-prefix-cls}.drag-over {
> [draggable] {
color: white;
background-color: @primary-color;
opacity: 0.8;
}
}
.@{tree-node-prefix-cls}.drag-over-gap-top {
> [draggable] {
border-top-color: @primary-color;
}
}
.@{tree-node-prefix-cls}.drag-over-gap-bottom {
> [draggable] {
border-bottom-color: @primary-color;
}
}
// ==================== Show Line =====================
&-show-line {
// ================ Indent lines ================
.@{tree-prefix-cls}-indent {
&-unit {
position: relative;
height: 100%;
&::before {
position: absolute;
top: calc(100% - 4px);
right: -@tree-title-height / 2;
bottom: -@tree-title-height - 4px;
border-right: 1px solid @border-color-base;
content: '';
}
&-end {
&::before {
display: none;
}
}
}
}
/* Motion should hide line of measure */
.@{tree-node-prefix-cls}-motion:not(.@{tree-motion}-leave):not(.@{tree-motion}-appear-active) {
.@{tree-prefix-cls}-indent-unit {
&::before {
display: none;
}
}
}
// ============== Cover Background ==============
.@{tree-prefix-cls}-switcher {
z-index: 1;
background: @component-background;
}
}
}
}
.antTreeFn(@tree-prefix-cls);

View File

@ -1,11 +1,11 @@
@import '../../style/mixins/index';
@tree-prefix-cls: ~'@{ant-prefix}-tree';
@tree-select-prefix-cls: ~'@{ant-prefix}-select';
@select-tree-prefix-cls: ~'@{ant-prefix}-select-tree';
.antTreeSwitcherIcon(@type: 'tree-default-open-icon') {
.@{tree-prefix-cls}-switcher-icon,
.@{tree-select-prefix-cls}-switcher-icon {
.@{select-tree-prefix-cls}-switcher-icon {
.iconfont-size-under-12px(10px);
display: inline-block;

View File

@ -0,0 +1,41 @@
import React from 'react';
import classNames from 'classnames';
import { Loading, File, MinusSquare, PlusSquare, CaretDownFilled } from '@ant-design/icons';
import { AntTreeNodeProps } from '../Tree';
export default function renderSwitcherIcon(
prefixCls: string,
switcherIcon: React.ReactNode | null | undefined,
showLine: boolean | undefined,
{ isLeaf, expanded, loading }: AntTreeNodeProps,
) {
if (loading) {
return <Loading className={`${prefixCls}-switcher-loading-icon`} />;
}
if (isLeaf) {
if (showLine) {
return <File className={`${prefixCls}-switcher-line-icon`} />;
}
return null;
}
const switcherCls = `${prefixCls}-switcher-icon`;
if (React.isValidElement(switcherIcon)) {
const switcherOriginCls = switcherIcon.props.className || '';
return React.cloneElement(switcherIcon, {
className: classNames(switcherOriginCls, switcherCls),
});
}
if (switcherIcon) {
return switcherIcon;
}
if (showLine) {
return expanded ? (
<MinusSquare className={`${prefixCls}-switcher-line-icon`} />
) : (
<PlusSquare className={`${prefixCls}-switcher-line-icon`} />
);
}
return <CaretDownFilled className={switcherCls} />;
}

View File

@ -122,7 +122,7 @@
"rc-pagination": "~1.20.5",
"rc-progress": "~2.5.0",
"rc-rate": "~2.5.0",
"rc-select": "~10.0.0-alpha.15",
"rc-select": "~10.0.0-alpha.27",
"rc-slider": "~8.6.11",
"rc-steps": "~3.5.0",
"rc-switch": "~1.9.0",
@ -130,8 +130,8 @@
"rc-tabs": "~9.6.4",
"rc-time-picker": "~3.7.1",
"rc-tooltip": "~3.7.3",
"rc-tree": "~3.0.0-alpha.22",
"rc-tree-select": "~2.9.1",
"rc-tree": "~3.0.0-alpha.36",
"rc-tree-select": "~3.0.0-alpha.4",
"rc-trigger": "^2.6.2",
"rc-upload": "~2.7.0",
"rc-util": "^4.10.0",

View File

@ -65,8 +65,6 @@ declare module 'rc-switch';
declare module 'rc-table';
declare module 'rc-tree-select';
declare module 'rc-upload';
declare module 'rc-form*';