| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491 | 
							- import React, { Fragment } from 'react';
 
- import ReactDOM from 'react-dom';
 
- import cls from 'classnames';
 
- import PropTypes from 'prop-types';
 
- import { isEqual, isString, isEmpty, noop, get, isFunction, isUndefined, isNull } from 'lodash';
 
- import TreeSelectFoundation, {
 
-     Size,
 
-     BasicTriggerRenderProps,
 
-     /* Corresponding props */
 
-     BasicTreeSelectProps,
 
-     /* Corresponding state */
 
-     BasicTreeSelectInnerData,
 
-     TreeSelectAdapter
 
- } from '@douyinfe/semi-foundation/treeSelect/foundation';
 
- import {
 
-     convertDataToEntities,
 
-     flattenTreeData,
 
-     calcExpandedKeysForValues,
 
-     calcMotionKeys,
 
-     findKeysForValues,
 
-     calcCheckedKeys,
 
-     calcExpandedKeys,
 
-     getValueOrKey,
 
-     normalizeKeyList,
 
-     calcDisabledKeys,
 
-     normalizeValue,
 
-     updateKeys,
 
- } from '@douyinfe/semi-foundation/tree/treeUtil';
 
- import { cssClasses, strings } from '@douyinfe/semi-foundation/treeSelect/constants';
 
- import { numbers as popoverNumbers } from '@douyinfe/semi-foundation/popover/constants';
 
- import { FixedSizeList as VirtualList, ListItemKeySelector } from 'react-window';
 
- import '@douyinfe/semi-foundation/tree/tree.scss';
 
- import '@douyinfe/semi-foundation/treeSelect/treeSelect.scss';
 
- import BaseComponent, { ValidateStatus } from '../_base/baseComponent';
 
- import ConfigContext, { ContextValue } from '../configProvider/context';
 
- import TagGroup from '../tag/group';
 
- import Tag, { TagProps } from '../tag/index';
 
- import Input, { InputProps } from '../input/index';
 
- import AutoSizer from '../tree/autoSizer';
 
- import TreeContext from '../tree/treeContext';
 
- import TreeNode from '../tree/treeNode';
 
- import NodeList from '../tree/nodeList';
 
- import { cloneDeep } from '../tree/treeUtil';
 
- import LocaleConsumer from '../locale/localeConsumer';
 
- import { Locale } from '../locale/interface';
 
- import Trigger from '../trigger';
 
- import TagInput from '../tagInput';
 
- import { isSemiIcon } from '../_utils';
 
- import { OptionProps, TreeProps, TreeState, FlattenNode, TreeNodeData, TreeNodeProps } from '../tree/interface';
 
- import { IconChevronDown, IconClear, IconSearch } from '@douyinfe/semi-icons';
 
- import CheckboxGroup from '../checkbox/checkboxGroup';
 
- import Popover, { PopoverProps } from '../popover/index';
 
- import VirtualRow from '../select/virtualRow';
 
- export type ExpandAction = false | 'click' | 'doubleClick';
 
- export interface TriggerRenderProps extends Omit<BasicTriggerRenderProps, 'componentProps'> {
 
-     [x: string]: any;
 
-     componentProps: TreeSelectProps;
 
-     value: TreeNodeData[];
 
-     onClear: (e: React.MouseEvent) => void
 
- }
 
- export interface OnChange {
 
-     /* onChangeWithObject is false */
 
-     (
 
-         value: TreeNodeData['value'] | Array<TreeNodeData['value']>,
 
-         node: TreeNodeData[] | TreeNodeData,
 
-         e: React.MouseEvent
 
-     ): void;
 
-     /* onChangeWithObject is true */
 
-     (node: TreeNodeData[] | TreeNodeData, e: React.MouseEvent): void
 
- }
 
- export type RenderSelectedItemInSingle = (treeNode: TreeNodeData) => React.ReactNode;
 
- export type RenderSelectedItemInMultiple = (
 
-     treeNode: TreeNodeData,
 
-     otherProps: { index: number | string; onClose: (tagContent: any, e: React.MouseEvent) => void }
 
- ) => {
 
-     isRenderInTag: boolean;
 
-     content: React.ReactNode
 
- };
 
- export type RenderSelectedItem = RenderSelectedItemInSingle | RenderSelectedItemInMultiple;
 
- export type OverrideCommonProps =
 
-     'renderFullLabel'
 
-     | 'renderLabel'
 
-     | 'defaultValue'
 
-     | 'emptyContent'
 
-     | 'filterTreeNode'
 
-     | 'style'
 
-     | 'treeData'
 
-     | 'value'
 
-     | 'onExpand';
 
- /**
 
- * Type definition description:
 
- * TreeSelectProps inherits some properties from BasicTreeSelectProps (from foundation) and TreeProps (from semi-ui-react).
 
- */
 
- // eslint-disable-next-line max-len
 
- export interface TreeSelectProps extends Omit<BasicTreeSelectProps, OverrideCommonProps | 'validateStatus' | 'searchRender'>, Pick<TreeProps, OverrideCommonProps> {
 
-     'aria-describedby'?: React.AriaAttributes['aria-describedby'];
 
-     'aria-errormessage'?: React.AriaAttributes['aria-errormessage'];
 
-     'aria-invalid'?: React.AriaAttributes['aria-invalid'];
 
-     'aria-labelledby'?: React.AriaAttributes['aria-labelledby'];
 
-     'aria-required'?: React.AriaAttributes['aria-required'];
 
-     motion?: boolean;
 
-     mouseEnterDelay?: number;
 
-     mouseLeaveDelay?: number;
 
-     arrowIcon?: React.ReactNode;
 
-     autoAdjustOverflow?: boolean;
 
-     clickToHide?: boolean;
 
-     clearIcon?: React.ReactNode;
 
-     defaultOpen?: boolean;
 
-     dropdownClassName?: string;
 
-     dropdownMatchSelectWidth?: boolean;
 
-     dropdownStyle?: React.CSSProperties;
 
-     dropdownMargin?: PopoverProps['margin'];
 
-     insetLabel?: React.ReactNode;
 
-     insetLabelId?: string;
 
-     maxTagCount?: number;
 
-     motionExpand?: boolean;
 
-     optionListStyle?: React.CSSProperties;
 
-     outerBottomSlot?: React.ReactNode;
 
-     outerTopSlot?: React.ReactNode;
 
-     placeholder?: string;
 
-     prefix?: React.ReactNode;
 
-     position?: PopoverProps['position'];
 
-     searchAutoFocus?: boolean;
 
-     searchPlaceholder?: string;
 
-     showSearchClear?: boolean;
 
-     size?: Size;
 
-     suffix?: React.ReactNode;
 
-     treeNodeLabelProp?: string;
 
-     validateStatus?: ValidateStatus;
 
-     zIndex?: number;
 
-     searchPosition?: string;
 
-     stopPropagation?: boolean | string;
 
-     restTagsPopoverProps?: PopoverProps;
 
-     searchRender?: boolean | ((inputProps: InputProps) => React.ReactNode);
 
-     onSelect?: (selectedKeys: string, selected: boolean, selectedNode: TreeNodeData) => void;
 
-     renderSelectedItem?: RenderSelectedItem;
 
-     getPopupContainer?: () => HTMLElement;
 
-     triggerRender?: (props?: TriggerRenderProps) => React.ReactNode;
 
-     onBlur?: (e: React.MouseEvent) => void;
 
-     onChange?: OnChange;
 
-     onFocus?: (e: React.MouseEvent) => void;
 
-     onVisibleChange?: (isVisible: boolean) => void
 
- }
 
- export type OverrideCommonState =
 
-     'keyEntities'
 
-     | 'treeData'
 
-     | 'disabledKeys'
 
-     | 'flattenNodes';
 
- // eslint-disable-next-line max-len
 
- export interface TreeSelectState extends Omit<BasicTreeSelectInnerData, OverrideCommonState | 'prevProps'>, Pick<TreeState, OverrideCommonState> {
 
-     inputTriggerFocus: boolean;
 
-     isOpen: boolean;
 
-     // isInput: boolean;
 
-     rePosKey: number;
 
-     dropdownMinWidth: null | number;
 
-     isHovering: boolean;
 
-     prevProps: TreeSelectProps;
 
-     isFocus: boolean
 
- }
 
- const prefixcls = cssClasses.PREFIX;
 
- const prefixTree = cssClasses.PREFIX_TREE;
 
- const key = 0;
 
- class TreeSelect extends BaseComponent<TreeSelectProps, TreeSelectState> {
 
-     static contextType = ConfigContext;
 
-     static propTypes = {
 
-         'aria-describedby': PropTypes.string,
 
-         'aria-errormessage': PropTypes.string,
 
-         'aria-invalid': PropTypes.bool,
 
-         'aria-labelledby': PropTypes.string,
 
-         'aria-required': PropTypes.bool,
 
-         loadedKeys: PropTypes.arrayOf(PropTypes.string),
 
-         loadData: PropTypes.func,
 
-         onLoad: PropTypes.func,
 
-         arrowIcon: PropTypes.node,
 
-         clearIcon: PropTypes.node,
 
-         defaultOpen: PropTypes.bool,
 
-         defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.array, PropTypes.object]),
 
-         defaultExpandAll: PropTypes.bool,
 
-         defaultExpandedKeys: PropTypes.array,
 
-         expandAll: PropTypes.bool,
 
-         disabled: PropTypes.bool,
 
-         disableStrictly: PropTypes.bool,
 
-         // Whether to turn on the input box filtering function, when it is a function, it represents a custom filtering function
 
-         filterTreeNode: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
 
-         multiple: PropTypes.bool,
 
-         searchPlaceholder: PropTypes.string,
 
-         searchAutoFocus: PropTypes.bool,
 
-         virtualize: PropTypes.object,
 
-         treeNodeFilterProp: PropTypes.string,
 
-         onChange: PropTypes.func,
 
-         onSearch: PropTypes.func,
 
-         onSelect: PropTypes.func,
 
-         onExpand: PropTypes.func,
 
-         onChangeWithObject: PropTypes.bool,
 
-         onBlur: PropTypes.func,
 
-         onFocus: PropTypes.func,
 
-         value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array, PropTypes.object]),
 
-         expandedKeys: PropTypes.array,
 
-         autoExpandParent: PropTypes.bool,
 
-         showClear: PropTypes.bool,
 
-         showSearchClear: PropTypes.bool,
 
-         autoAdjustOverflow: PropTypes.bool,
 
-         showFilteredOnly: PropTypes.bool,
 
-         motionExpand: PropTypes.bool,
 
-         emptyContent: PropTypes.node,
 
-         leafOnly: PropTypes.bool,
 
-         treeData: PropTypes.arrayOf(
 
-             PropTypes.shape({
 
-                 key: PropTypes.string.isRequired,
 
-                 value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
 
-                 label: PropTypes.any,
 
-             })
 
-         ),
 
-         dropdownClassName: PropTypes.string,
 
-         dropdownStyle: PropTypes.object,
 
-         dropdownMargin: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
 
-         motion: PropTypes.bool,
 
-         placeholder: PropTypes.string,
 
-         maxTagCount: PropTypes.number,
 
-         size: PropTypes.oneOf<TreeSelectProps['size']>(strings.SIZE_SET),
 
-         className: PropTypes.string,
 
-         style: PropTypes.object,
 
-         treeNodeLabelProp: PropTypes.string,
 
-         suffix: PropTypes.node,
 
-         prefix: PropTypes.node,
 
-         insetLabel: PropTypes.node,
 
-         insetLabelId: PropTypes.string,
 
-         zIndex: PropTypes.number,
 
-         getPopupContainer: PropTypes.func,
 
-         dropdownMatchSelectWidth: PropTypes.bool,
 
-         validateStatus: PropTypes.oneOf(strings.STATUS),
 
-         mouseEnterDelay: PropTypes.number,
 
-         mouseLeaveDelay: PropTypes.number,
 
-         triggerRender: PropTypes.func,
 
-         stopPropagation: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
 
-         outerBottomSlot: PropTypes.node,
 
-         outerTopSlot: PropTypes.node,
 
-         onVisibleChange: PropTypes.func,
 
-         expandAction: PropTypes.oneOf(['click' as const, 'doubleClick' as const, false as const]),
 
-         searchPosition: PropTypes.oneOf([strings.SEARCH_POSITION_DROPDOWN, strings.SEARCH_POSITION_TRIGGER]),
 
-         clickToHide: PropTypes.bool,
 
-         renderLabel: PropTypes.func,
 
-         renderFullLabel: PropTypes.func,
 
-         labelEllipsis: PropTypes.bool,
 
-         optionListStyle: PropTypes.object,
 
-         searchRender: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
 
-         renderSelectedItem: PropTypes.func,
 
-         checkRelation: PropTypes.string,
 
-         'aria-label': PropTypes.string,
 
-         showRestTagsPopover: PropTypes.bool,
 
-         restTagsPopoverProps: PropTypes.object,
 
-         preventScroll: PropTypes.bool,
 
-         clickTriggerToHide: PropTypes.bool,
 
-     };
 
-     static defaultProps: Partial<TreeSelectProps> = {
 
-         searchPosition: strings.SEARCH_POSITION_DROPDOWN,
 
-         arrowIcon: <IconChevronDown />,
 
-         autoExpandParent: false,
 
-         autoAdjustOverflow: true,
 
-         stopPropagation: true,
 
-         motion: true,
 
-         motionExpand: true,
 
-         expandAll: false,
 
-         zIndex: popoverNumbers.DEFAULT_Z_INDEX,
 
-         disableStrictly: false,
 
-         multiple: false,
 
-         filterTreeNode: false,
 
-         size: 'default' as const,
 
-         treeNodeFilterProp: 'label' as const,
 
-         onChangeWithObject: false,
 
-         treeNodeLabelProp: 'label' as const,
 
-         dropdownMatchSelectWidth: true,
 
-         defaultOpen: false,
 
-         showSearchClear: true,
 
-         showClear: false,
 
-         onVisibleChange: noop,
 
-         expandAction: false,
 
-         clickToHide: true,
 
-         searchAutoFocus: false,
 
-         checkRelation: 'related',
 
-         'aria-label': 'TreeSelect',
 
-         showRestTagsPopover: false,
 
-         restTagsPopoverProps: {},
 
-         clickTriggerToHide: true,
 
-     };
 
-     inputRef: React.RefObject<typeof Input>;
 
-     tagInputRef: React.RefObject<TagInput>;
 
-     triggerRef: React.RefObject<HTMLDivElement>;
 
-     optionsRef: React.RefObject<any>;
 
-     clickOutsideHandler: any;
 
-     _flattenNodes: TreeState['flattenNodes'];
 
-     onNodeClick: any;
 
-     onNodeDoubleClick: any;
 
-     onMotionEnd: any;
 
-     treeSelectID: string;
 
-     context: ContextValue;
 
-     constructor(props: TreeSelectProps) {
 
-         super(props);
 
-         this.state = {
 
-             inputTriggerFocus: false,
 
-             isOpen: false,
 
-             isFocus: false,
 
-             // isInput: false,
 
-             rePosKey: key,
 
-             dropdownMinWidth: null,
 
-             inputValue: '',
 
-             keyEntities: {},
 
-             treeData: [],
 
-             flattenNodes: [],
 
-             selectedKeys: [],
 
-             checkedKeys: new Set(),
 
-             halfCheckedKeys: new Set(),
 
-             realCheckedKeys: new Set([]),
 
-             disabledKeys: new Set(),
 
-             motionKeys: new Set([]),
 
-             motionType: 'hide',
 
-             expandedKeys: new Set(props.expandedKeys),
 
-             filteredKeys: new Set(),
 
-             filteredExpandedKeys: new Set(),
 
-             filteredShownKeys: new Set(),
 
-             prevProps: null,
 
-             isHovering: false,
 
-             cachedKeyValuePairs: {},
 
-             loadedKeys: new Set(),
 
-             loadingKeys: new Set(),
 
-         };
 
-         this.inputRef = React.createRef();
 
-         this.tagInputRef = React.createRef();
 
-         this.triggerRef = React.createRef();
 
-         this.optionsRef = React.createRef();
 
-         this.clickOutsideHandler = null;
 
-         this.foundation = new TreeSelectFoundation(this.adapter);
 
-         this.treeSelectID = Math.random().toString(36).slice(2);
 
-         this.onMotionEnd = () => {
 
-             this.adapter.rePositionDropdown();
 
-         };
 
-     }
 
-     // eslint-disable-next-line max-lines-per-function
 
-     static getDerivedStateFromProps(props: TreeSelectProps, prevState: TreeSelectState) {
 
-         const { prevProps, rePosKey } = prevState;
 
-         const needUpdate = (name: string) => (
 
-             (!prevProps && name in props) ||
 
-             (prevProps && !isEqual(prevProps[name], props[name]))
 
-         );
 
-         let treeData;
 
-         const withObject = props.onChangeWithObject;
 
-         let keyEntities = prevState.keyEntities || {};
 
-         let valueEntities = prevState.cachedKeyValuePairs || {};
 
-         const newState: Partial<TreeSelectState> = {
 
-             prevProps: props,
 
-         };
 
-         // TreeNode
 
-         if (needUpdate('treeData')) {
 
-             treeData = props.treeData;
 
-             newState.treeData = treeData;
 
-             const entitiesMap = convertDataToEntities(treeData);
 
-             newState.keyEntities = {
 
-                 ...entitiesMap.keyEntities,
 
-             };
 
-             keyEntities = newState.keyEntities;
 
-             newState.cachedKeyValuePairs = { ...entitiesMap.valueEntities };
 
-             valueEntities = newState.cachedKeyValuePairs;
 
-         }
 
-         // if treeData keys changes, we won't show animation
 
-         if (
 
-             treeData &&
 
-             props.motion &&
 
-             !isEqual(Object.keys(newState.keyEntities), Object.keys(prevState.keyEntities))
 
-         ) {
 
-             if (prevProps && props.motion) {
 
-                 newState.motionKeys = new Set([]);
 
-                 newState.motionType = null;
 
-             }
 
-         }
 
-         const expandAllWhenDataChange = needUpdate('treeData') && props.expandAll;
 
-         // expandedKeys
 
-         if (needUpdate('expandedKeys') || (prevProps && needUpdate('autoExpandParent'))) {
 
-             newState.expandedKeys = calcExpandedKeys(
 
-                 props.expandedKeys,
 
-                 keyEntities,
 
-                 props.autoExpandParent || !prevProps
 
-             );
 
-             // only show animation when treeData does not change
 
-             if (prevProps && props.motion && !treeData) {
 
-                 const { motionKeys, motionType } = calcMotionKeys(
 
-                     prevState.expandedKeys,
 
-                     newState.expandedKeys,
 
-                     keyEntities
 
-                 );
 
-                 newState.motionKeys = new Set(motionKeys);
 
-                 newState.motionType = motionType;
 
-             }
 
-         } else if ((!prevProps && (props.defaultExpandAll || props.expandAll)) || expandAllWhenDataChange) {
 
-             newState.expandedKeys = new Set(Object.keys(keyEntities));
 
-         } else if (!prevProps && props.defaultExpandedKeys) {
 
-             newState.expandedKeys = calcExpandedKeys(props.defaultExpandedKeys, keyEntities);
 
-         } else if (!prevProps && props.defaultValue) {
 
-             newState.expandedKeys = calcExpandedKeysForValues(
 
-                 normalizeValue(props.defaultValue, withObject),
 
-                 keyEntities,
 
-                 props.multiple,
 
-                 valueEntities
 
-             );
 
-         } else if (!prevProps && props.value) {
 
-             newState.expandedKeys = calcExpandedKeysForValues(
 
-                 normalizeValue(props.value, withObject),
 
-                 keyEntities,
 
-                 props.multiple,
 
-                 valueEntities
 
-             );
 
-         }
 
-         // flattenNodes
 
-         if (treeData || needUpdate('expandedKeys')) {
 
-             const flattenNodes = flattenTreeData(
 
-                 treeData || prevState.treeData,
 
-                 newState.expandedKeys || prevState.expandedKeys
 
-             );
 
-             newState.flattenNodes = flattenNodes;
 
-         }
 
-         // selectedKeys: single mode controlled
 
-         const isMultiple = props.multiple;
 
-         if (!isMultiple) {
 
-             if (needUpdate('value')) {
 
-                 newState.selectedKeys = findKeysForValues(
 
-                     normalizeValue(props.value, withObject),
 
-                     valueEntities,
 
-                     isMultiple
 
-                 );
 
-             } else if (!prevProps && props.defaultValue) {
 
-                 newState.selectedKeys = findKeysForValues(
 
-                     normalizeValue(props.defaultValue, withObject),
 
-                     valueEntities,
 
-                     isMultiple
 
-                 );
 
-             } else if (treeData) {
 
-                 // If `treeData` changed, we also need check it
 
-                 if (props.value) {
 
-                     newState.selectedKeys = findKeysForValues(
 
-                         normalizeValue(props.value, withObject) || '',
 
-                         valueEntities,
 
-                         isMultiple
 
-                     );
 
-                 } else {
 
-                     newState.selectedKeys = updateKeys(prevState.selectedKeys, keyEntities);
 
-                 }
 
-             }
 
-         } else {
 
-             // checkedKeys: multiple mode controlled || data changed
 
-             let checkedKeyValues;
 
-             if (needUpdate('value')) {
 
-                 checkedKeyValues = findKeysForValues(
 
-                     normalizeValue(props.value, withObject),
 
-                     valueEntities,
 
-                     isMultiple
 
-                 );
 
-             } else if (!prevProps && props.defaultValue) {
 
-                 checkedKeyValues = findKeysForValues(
 
-                     normalizeValue(props.defaultValue, withObject),
 
-                     valueEntities,
 
-                     isMultiple
 
-                 );
 
-             } else if (treeData) {
 
-                 // If `treeData` changed, we also need check it
 
-                 if (props.value) {
 
-                     checkedKeyValues = findKeysForValues(
 
-                         normalizeValue(props.value, withObject) || [],
 
-                         valueEntities,
 
-                         isMultiple
 
-                     );
 
-                 } else {
 
-                     checkedKeyValues = updateKeys(prevState.checkedKeys, keyEntities);
 
-                 }
 
-             }
 
-             if (checkedKeyValues) {
 
-                 if (props.checkRelation === 'unRelated') {
 
-                     newState.realCheckedKeys = new Set(checkedKeyValues);
 
-                 } else if (props.checkRelation === 'related') {
 
-                     const { checkedKeys, halfCheckedKeys } = calcCheckedKeys(checkedKeyValues, keyEntities);
 
-                     newState.checkedKeys = checkedKeys;
 
-                     newState.halfCheckedKeys = halfCheckedKeys;
 
-                 }
 
-             }
 
-         }
 
-         // loadedKeys
 
-         if (needUpdate('loadedKeys')) {
 
-             newState.loadedKeys = new Set(props.loadedKeys);
 
-         }
 
-         // ================== rePosKey ==================
 
-         if (needUpdate('treeData') || needUpdate('value')) {
 
-             newState.rePosKey = rePosKey + 1;
 
-         }
 
-         // ================ disableStrictly =================
 
-         if (treeData && props.disableStrictly && props.checkRelation === 'related') {
 
-             newState.disabledKeys = calcDisabledKeys(keyEntities);
 
-         }
 
-         return newState;
 
-     }
 
-     get adapter(): TreeSelectAdapter<TreeSelectProps, TreeSelectState> {
 
-         const filterAdapter: Pick<TreeSelectAdapter, 'updateInputValue'> = {
 
-             updateInputValue: value => {
 
-                 this.setState({ inputValue: value });
 
-             }
 
-         };
 
-         const treeSelectAdapter: Pick<TreeSelectAdapter,
 
-         'registerClickOutsideHandler'
 
-         | 'unregisterClickOutsideHandler'
 
-         | 'rePositionDropdown'
 
-         > = {
 
-             registerClickOutsideHandler: cb => {
 
-                 const clickOutsideHandler = (e: Event) => {
 
-                     const optionInstance = this.optionsRef && this.optionsRef.current as React.ReactInstance;
 
-                     const triggerDom = this.triggerRef && this.triggerRef.current;
 
-                     // eslint-disable-next-line
 
-                     const optionsDom = ReactDOM.findDOMNode(optionInstance);
 
-                     const target = e.target as Element;
 
-                     if (
 
-                         optionsDom &&
 
-                         (
 
-                             !optionsDom.contains(target) ||
 
-                             !optionsDom.contains(target.parentNode)
 
-                         ) &&
 
-                         triggerDom &&
 
-                         !triggerDom.contains(target)
 
-                     ) {
 
-                         cb(e);
 
-                     }
 
-                 };
 
-                 this.clickOutsideHandler = clickOutsideHandler;
 
-                 document.addEventListener('mousedown', clickOutsideHandler, false);
 
-             },
 
-             unregisterClickOutsideHandler: () => {
 
-                 document.removeEventListener('mousedown', this.clickOutsideHandler, false);
 
-                 this.clickOutsideHandler = null;
 
-             },
 
-             rePositionDropdown: () => {
 
-                 let { rePosKey } = this.state;
 
-                 rePosKey = rePosKey + 1;
 
-                 this.setState({ rePosKey });
 
-             },
 
-         };
 
-         const treeAdapter: Pick<TreeSelectAdapter,
 
-         'updateState'
 
-         | 'notifySelect'
 
-         | 'notifySearch'
 
-         | 'cacheFlattenNodes'
 
-         | 'notifyLoad'
 
-         > = {
 
-             updateState: states => {
 
-                 this.setState({ ...states } as TreeSelectState);
 
-             },
 
-             notifySelect: ((selectKey, bool, node) => {
 
-                 this.props.onSelect && this.props.onSelect(selectKey, bool, node);
 
-             }),
 
-             notifySearch: (input, filteredExpandedKeys) => {
 
-                 this.props.onSearch && this.props.onSearch(input, filteredExpandedKeys);
 
-             },
 
-             cacheFlattenNodes: bool => {
 
-                 this._flattenNodes = bool ? cloneDeep(this.state.flattenNodes) : null;
 
-             },
 
-             notifyLoad: (newLoadedKeys, data) => {
 
-                 const { onLoad } = this.props;
 
-                 isFunction(onLoad) && onLoad(newLoadedKeys, data);
 
-             }
 
-         };
 
-         return {
 
-             ...super.adapter,
 
-             ...filterAdapter,
 
-             ...treeSelectAdapter,
 
-             ...treeAdapter,
 
-             updateLoadKeys: (data, resolve) => {
 
-                 this.setState(({ loadedKeys, loadingKeys }) =>
 
-                     this.foundation.handleNodeLoad(loadedKeys, loadingKeys, data, resolve));
 
-             },
 
-             updateState: states => {
 
-                 this.setState({ ...states } as TreeSelectState);
 
-             },
 
-             openMenu: () => {
 
-                 this.setState({ isOpen: true }, () => {
 
-                     this.props.onVisibleChange(true);
 
-                 });
 
-             },
 
-             closeMenu: cb => {
 
-                 this.setState({ isOpen: false }, () => {
 
-                     cb && cb();
 
-                     this.props.onVisibleChange(false);
 
-                 });
 
-             },
 
-             getTriggerWidth: () => {
 
-                 const el = this.triggerRef.current;
 
-                 return el && el.getBoundingClientRect().width;
 
-             },
 
-             setOptionWrapperWidth: width => {
 
-                 this.setState({ dropdownMinWidth: width });
 
-             },
 
-             notifyChange: (value, node, e) => {
 
-                 this.props.onChange && this.props.onChange(value, node, e);
 
-             },
 
-             notifyChangeWithObject: (node, e) => {
 
-                 this.props.onChange && this.props.onChange(node, e);
 
-             },
 
-             notifyExpand: (expandedKeys, { expanded: bool, node }) => {
 
-                 this.props.onExpand && this.props.onExpand([...expandedKeys], { expanded: bool, node });
 
-                 if (bool && this.props.loadData) {
 
-                     this.onNodeLoad(node);
 
-                 }
 
-             },
 
-             notifyFocus: (...v) => {
 
-                 this.props.onFocus && this.props.onFocus(...v);
 
-             },
 
-             notifyBlur: (...v) => {
 
-                 this.props.onBlur && this.props.onBlur(...v);
 
-             },
 
-             toggleHovering: bool => {
 
-                 this.setState({ isHovering: bool });
 
-             },
 
-             updateInputFocus: bool => { 
 
-                 if (bool) {
 
-                     if (this.inputRef && this.inputRef.current) {
 
-                         const { preventScroll } = this.props;
 
-                         (this.inputRef.current as any).focus({ preventScroll });
 
-                     }
 
-                     if (this.tagInputRef && this.tagInputRef.current) {
 
-                         this.tagInputRef.current.focus();
 
-                     }
 
-                 } else {
 
-                     if (this.inputRef && this.inputRef.current) {
 
-                         (this.inputRef.current as any).blur();
 
-                     }
 
-                     if (this.tagInputRef && this.tagInputRef.current) {
 
-                         this.tagInputRef.current.blur();
 
-                     }
 
-                 }
 
-             },
 
-             updateIsFocus: bool => {
 
-                 this.setState({ isFocus: bool });
 
-             } 
 
-         };
 
-     }
 
-     componentDidMount() {
 
-         this.foundation.init();
 
-     }
 
-     componentWillUnmount() {
 
-         this.foundation.destroy();
 
-     }
 
-     renderSuffix = () => {
 
-         const { suffix }: any = this.props;
 
-         const suffixWrapperCls = cls({
 
-             [`${prefixcls}-suffix`]: true,
 
-             [`${prefixcls}-suffix-text`]: suffix && isString(suffix),
 
-             [`${prefixcls}-suffix-icon`]: isSemiIcon(suffix),
 
-         });
 
-         return (
 
-             <div className={suffixWrapperCls} x-semi-prop="suffix">
 
-                 {suffix}
 
-             </div>
 
-         );
 
-     };
 
-     renderPrefix = () => {
 
-         const { prefix, insetLabel, insetLabelId }: any = this.props;
 
-         const labelNode = prefix || insetLabel;
 
-         const prefixWrapperCls = cls({
 
-             [`${prefixcls}-prefix`]: true,
 
-             // to be doublechecked
 
-             [`${prefixcls}-inset-label`]: insetLabel,
 
-             [`${prefixcls}-prefix-text`]: labelNode && isString(labelNode),
 
-             [`${prefixcls}-prefix-icon`]: isSemiIcon(labelNode),
 
-         });
 
-         return (
 
-             <div className={prefixWrapperCls} id={insetLabelId} x-semi-prop="prefix,insetLabel">
 
-                 {labelNode}
 
-             </div>
 
-         );
 
-     };
 
-     renderContent = () => {
 
-         const { dropdownMinWidth } = this.state;
 
-         const { dropdownStyle, dropdownClassName } = this.props;
 
-         const style = { minWidth: dropdownMinWidth, ...dropdownStyle };
 
-         const popoverCls = cls(dropdownClassName, `${prefixcls}-popover`);
 
-         return (
 
-             <div className={popoverCls} style={style}>
 
-                 {this.renderTree()}
 
-             </div>
 
-         );
 
-     };
 
-     removeTag = (removedKey: TreeNodeData['key']) => {
 
-         this.foundation.removeTag(removedKey);
 
-     };
 
-     handleClick = (e: React.MouseEvent) => {
 
-         this.foundation.handleClick(e);
 
-     };
 
-     getDataForKeyNotInKeyEntities = (key: string) => {
 
-         return this.foundation.getDataForKeyNotInKeyEntities(key);
 
-     }
 
-     /* istanbul ignore next */
 
-     handleSelectionEnterPress = (e: React.KeyboardEvent<HTMLDivElement>) => {
 
-         this.foundation.handleSelectionEnterPress(e);
 
-     };
 
-     hasValue = (): boolean => {
 
-         const { multiple, checkRelation } = this.props;
 
-         const { realCheckedKeys, checkedKeys, selectedKeys } = this.state;
 
-         let hasValue = false;
 
-         if (multiple) {
 
-             if (checkRelation === 'related') {
 
-                 hasValue = Boolean(checkedKeys.size);
 
-             } else if (checkRelation === 'unRelated') {
 
-                 hasValue = Boolean(realCheckedKeys.size);
 
-             }
 
-         } else {
 
-             hasValue = Boolean(selectedKeys.length);
 
-         }
 
-         return hasValue;
 
-     }
 
-     showClearBtn = () => {
 
-         const { showClear, disabled, searchPosition } = this.props;
 
-         const { inputValue, isOpen, isHovering } = this.state;
 
-         const triggerSearchHasInputValue = searchPosition === strings.SEARCH_POSITION_TRIGGER && inputValue;
 
-         return showClear && (this.hasValue() || triggerSearchHasInputValue) && !disabled && (isOpen || isHovering);
 
-     };
 
-     renderTagList = () => {
 
-         const { checkedKeys, keyEntities, disabledKeys, realCheckedKeys } = this.state;
 
-         const {
 
-             treeNodeLabelProp,
 
-             leafOnly,
 
-             disabled,
 
-             disableStrictly,
 
-             size,
 
-             checkRelation,
 
-             renderSelectedItem: propRenderSelectedItem
 
-         } = this.props;
 
-         const renderSelectedItem = isFunction(propRenderSelectedItem) ?
 
-             propRenderSelectedItem :
 
-             (item: TreeNodeData) => ({
 
-                 isRenderInTag: true,
 
-                 content: get(item, treeNodeLabelProp, null)
 
-             });
 
-         let renderKeys = [];
 
-         if (checkRelation === 'related') {
 
-             renderKeys = normalizeKeyList([...checkedKeys], keyEntities, leafOnly, true);
 
-         } else if (checkRelation === 'unRelated' && Object.keys(keyEntities).length > 0) {
 
-             renderKeys = [...realCheckedKeys];
 
-         }
 
-         const tagList: Array<React.ReactNode> = [];
 
-         // eslint-disable-next-line @typescript-eslint/no-shadow
 
-         renderKeys.forEach((key: TreeNodeData['key'], index) => {
 
-             const item = (keyEntities[key] && keyEntities[key].data.key === key) ? keyEntities[key].data : this.getDataForKeyNotInKeyEntities(key);
 
-             const onClose = (tagContent: any, e: React.MouseEvent) => {
 
-                 if (e && typeof e.preventDefault === 'function') {
 
-                     // make sure that tag will not hidden immediately in controlled mode
 
-                     e.preventDefault();
 
-                 }
 
-                 this.removeTag(key);
 
-             };
 
-             const { content, isRenderInTag } = (item && treeNodeLabelProp in item) ?
 
-                 (renderSelectedItem as RenderSelectedItemInMultiple)(item, { index, onClose }) :
 
-                 null;
 
-             if (isNull(content) || isUndefined(content)) {
 
-                 return;
 
-             }
 
-             const isDisabled = disabled || item.disabled || (disableStrictly && disabledKeys.has(item.key));
 
-             const tag: Partial<TagProps> & React.Attributes = {
 
-                 closable: !isDisabled,
 
-                 color: 'white',
 
-                 visible: true,
 
-                 onClose,
 
-                 key: `tag-${key}-${index}`,
 
-                 size: size === 'small' ? 'small' : 'large'
 
-             };
 
-             if (isRenderInTag) {
 
-                 // pass ReactNode list to tagList when using tagGroup custom mode
 
-                 tagList.push(<Tag {...tag}>{content}</Tag>);
 
-             } else {
 
-                 tagList.push(content);
 
-             }
 
-         });
 
-         return tagList;
 
-     };
 
-     /**
 
-      * When single selection and the search box is on trigger, the items displayed in the rendered search box
 
-      */
 
-     renderSingleTriggerSearchItem = () => {
 
-         const { placeholder, disabled } = this.props;
 
-         const { inputTriggerFocus } = this.state;
 
-         const renderText = this.foundation.getRenderTextInSingle();
 
-         const spanCls = cls(`${prefixcls}-selection-TriggerSearchItem`, {
 
-             [`${prefixcls}-selection-TriggerSearchItem-placeholder`]: (inputTriggerFocus || !renderText) && !disabled,
 
-             [`${prefixcls}-selection-TriggerSearchItem-disabled`]: disabled,
 
-         });
 
-         return (
 
-             <span className={spanCls}>
 
-                 {renderText ? renderText : placeholder}
 
-             </span>
 
-         );
 
-     };
 
-     /**
 
-      * Single selection and the search box content rendered when the search box is on trigger
 
-      */
 
-     renderSingleTriggerSearch = () => {
 
-         const { inputValue } = this.state;
 
-         return (
 
-             <>
 
-                 {!inputValue && this.renderSingleTriggerSearchItem()}
 
-                 {this.renderInput()}
 
-             </>
 
-         );
 
-     };
 
-     renderSelectContent = () => {
 
-         const {
 
-             multiple,
 
-             placeholder,
 
-             maxTagCount,
 
-             searchPosition,
 
-             filterTreeNode,
 
-             showRestTagsPopover, 
 
-             restTagsPopoverProps 
 
-         } = this.props;
 
-         const isTriggerPositionSearch = filterTreeNode && searchPosition === strings.SEARCH_POSITION_TRIGGER;
 
-         // searchPosition = trigger
 
-         if (isTriggerPositionSearch) {
 
-             return multiple ? this.renderTagInput() : this.renderSingleTriggerSearch();
 
-         }
 
-         // searchPosition = dropdown and single seleciton
 
-         if (!multiple || !this.hasValue()) {
 
-             const renderText = this.foundation.getRenderTextInSingle();
 
-             const spanCls = cls({
 
-                 [`${prefixcls}-selection-placeholder`]: !renderText,
 
-             });
 
-             return <span className={spanCls}>{renderText ? renderText : placeholder}</span>;
 
-         }
 
-         // searchPosition = dropdown and multiple seleciton
 
-         const tagList = this.renderTagList();
 
-         // mode=custom to return tagList directly
 
-         return (
 
-             <TagGroup<'custom'>
 
-                 maxTagCount={maxTagCount}
 
-                 tagList={tagList}
 
-                 size="large"
 
-                 mode="custom"
 
-                 showPopover={showRestTagsPopover}
 
-                 popoverProps={restTagsPopoverProps}
 
-             />
 
-         );
 
-     };
 
-     handleClear = (e: React.MouseEvent) => {
 
-         e && e.stopPropagation();
 
-         this.foundation.handleClear(e);
 
-     };
 
-     /* istanbul ignore next */
 
-     handleClearEnterPress = (e: React.KeyboardEvent<HTMLDivElement>) => {
 
-         e && e.stopPropagation();
 
-         this.foundation.handleClearEnterPress(e);
 
-     };
 
-     handleMouseOver = (e: React.MouseEvent) => {
 
-         this.foundation.toggleHoverState(true);
 
-     };
 
-     handleMouseLeave = (e: React.MouseEvent) => {
 
-         this.foundation.toggleHoverState(false);
 
-     };
 
-     search = (value: string) => {
 
-         const { isOpen } = this.state;
 
-         if (!isOpen) {
 
-             this.foundation.open();
 
-         }
 
-         this.foundation.handleInputChange(value);
 
-     };
 
-     close = () => {
 
-         this.foundation.close(null);
 
-     };
 
-     renderArrow = () => {
 
-         const showClearBtn = this.showClearBtn();
 
-         const { arrowIcon } = this.props;
 
-         if (showClearBtn) {
 
-             return null;
 
-         }
 
-         return arrowIcon ? (
 
-             <div className={cls(`${prefixcls}-arrow`)} x-semi-prop="arrowIcon">
 
-                 {arrowIcon}
 
-             </div>
 
-         ) : null;
 
-     };
 
-     renderClearBtn = () => {
 
-         const showClearBtn = this.showClearBtn();
 
-         const { clearIcon } = this.props;
 
-         const clearCls = cls(`${prefixcls}-clearbtn`);
 
-         if (showClearBtn) {
 
-             return (
 
-                 <div
 
-                     role='button'
 
-                     tabIndex={0}
 
-                     aria-label="Clear TreeSelect value"
 
-                     className={clearCls}
 
-                     onClick={this.handleClear}
 
-                     onKeyPress={this.handleClearEnterPress}
 
-                 >
 
-                     { clearIcon ? clearIcon : <IconClear />}
 
-                 </div>
 
-             );
 
-         }
 
-         return null;
 
-     };
 
-     renderSelection = () => {
 
-         const {
 
-             disabled,
 
-             multiple,
 
-             filterTreeNode,
 
-             validateStatus,
 
-             prefix,
 
-             suffix,
 
-             style,
 
-             size,
 
-             insetLabel,
 
-             className,
 
-             placeholder,
 
-             showClear,
 
-             leafOnly,
 
-             searchPosition,
 
-             triggerRender,
 
-         } = this.props;
 
-         const { inputValue, selectedKeys, checkedKeys, keyEntities, isFocus } = this.state;
 
-         const filterable = Boolean(filterTreeNode);
 
-         const useCustomTrigger = typeof triggerRender === 'function';
 
-         const mouseEvent = showClear ?
 
-             {
 
-                 onMouseEnter: (e: React.MouseEvent) => this.handleMouseOver(e),
 
-                 onMouseLeave: (e: React.MouseEvent) => this.handleMouseLeave(e),
 
-             } :
 
-             {};
 
-         const isTriggerPositionSearch = searchPosition === strings.SEARCH_POSITION_TRIGGER && filterable;
 
-         const isEmptyTriggerSearch = isTriggerPositionSearch && isEmpty(checkedKeys);
 
-         const isValueTriggerSearch = isTriggerPositionSearch && !isEmpty(checkedKeys);
 
-         const classNames = useCustomTrigger ?
 
-             cls(className) :
 
-             cls(
 
-                 prefixcls,
 
-                 {
 
-                     [`${prefixcls}-focus`]: isFocus,
 
-                     [`${prefixcls}-disabled`]: disabled,
 
-                     [`${prefixcls}-single`]: !multiple,
 
-                     [`${prefixcls}-multiple`]: multiple,
 
-                     [`${prefixcls}-multiple-tagInput-empty`]: multiple && isEmptyTriggerSearch,
 
-                     [`${prefixcls}-multiple-tagInput-notEmpty`]: multiple && isValueTriggerSearch,
 
-                     [`${prefixcls}-filterable`]: filterable,
 
-                     [`${prefixcls}-error`]: validateStatus === 'error',
 
-                     [`${prefixcls}-warning`]: validateStatus === 'warning',
 
-                     [`${prefixcls}-small`]: size === 'small',
 
-                     [`${prefixcls}-large`]: size === 'large',
 
-                     [`${prefixcls}-with-prefix`]: prefix || insetLabel,
 
-                     [`${prefixcls}-with-suffix`]: suffix,
 
-                     [`${prefixcls}-with-suffix`]: suffix,
 
-                 },
 
-                 className
 
-             );
 
-         const triggerRenderKeys = multiple ? normalizeKeyList([...checkedKeys], keyEntities, leafOnly, true) : selectedKeys;
 
-         const inner = useCustomTrigger ? (
 
-             <Trigger
 
-                 inputValue={inputValue}
 
-                 // eslint-disable-next-line @typescript-eslint/no-shadow
 
-                 value={triggerRenderKeys.map((key: string) => get(keyEntities, [key, 'data']))}
 
-                 disabled={disabled}
 
-                 placeholder={placeholder}
 
-                 onClear={this.handleClear}
 
-                 componentName={'TreeSelect'}
 
-                 triggerRender={triggerRender}
 
-                 componentProps={{ ...this.props }}
 
-                 onSearch={this.search}
 
-                 onRemove={this.removeTag}
 
-             />
 
-         ) : (
 
-             [
 
-                 <Fragment key={'prefix'}>{prefix || insetLabel ? this.renderPrefix() : null}</Fragment>,
 
-                 <Fragment key={'selection'}>
 
-                     <div className={`${prefixcls}-selection`}>{this.renderSelectContent()}</div>
 
-                 </Fragment>,
 
-                 <Fragment key={'suffix'}>{suffix ? this.renderSuffix() : null}</Fragment>,
 
-                 <Fragment key={'clearBtn'}>
 
-                     {
 
-                         (showClear || (isTriggerPositionSearch && inputValue)) ?
 
-                             this.renderClearBtn() :
 
-                             null
 
-                     }
 
-                 </Fragment>,
 
-                 <Fragment key={'arrow'}>{this.renderArrow()}</Fragment>,
 
-             ]
 
-         );
 
-         const tabIndex = disabled ? null : 0;
 
-         /**
 
-          * Reasons for disabling the a11y eslint rule:
 
-          * The following attributes(aria-controls,aria-expanded) will be automatically added by Tooltip, no need to declare here
 
-          */
 
-         return (
 
-             <div
 
-                 // eslint-disable-next-line jsx-a11y/role-has-required-aria-props
 
-                 role='combobox'
 
-                 aria-disabled={disabled}
 
-                 aria-haspopup="tree"
 
-                 tabIndex={tabIndex}
 
-                 className={classNames}
 
-                 style={style}
 
-                 ref={this.triggerRef}
 
-                 onClick={this.handleClick}
 
-                 onKeyPress={this.handleSelectionEnterPress}
 
-                 aria-invalid={this.props['aria-invalid']}
 
-                 aria-errormessage={this.props['aria-errormessage']}
 
-                 aria-label={this.props['aria-label']}
 
-                 aria-labelledby={this.props['aria-labelledby']}
 
-                 aria-describedby={this.props['aria-describedby']}
 
-                 aria-required={this.props['aria-required']}
 
-                 {...mouseEvent}
 
-             >
 
-                 {inner}
 
-             </div>
 
-         );
 
-     };
 
-     // eslint-disable-next-line @typescript-eslint/no-shadow
 
-     renderTagItem = (key: string, idx: number) => {
 
-         const { keyEntities, disabledKeys } = this.state;
 
-         const {
 
-             size,
 
-             leafOnly,
 
-             disabled,
 
-             disableStrictly,
 
-             renderSelectedItem: propRenderSelectedItem,
 
-             treeNodeLabelProp
 
-         } = this.props;
 
-         const keyList = normalizeKeyList([key], keyEntities, leafOnly, true);
 
-         const nodes = keyList.map(i => (keyEntities[key] && keyEntities[key].data.key === key) ? keyEntities[key].data : this.getDataForKeyNotInKeyEntities(key));
 
-         const value = getValueOrKey(nodes);
 
-         const tagCls = cls(`${prefixcls}-selection-tag`, {
 
-             [`${prefixcls}-selection-tag-disabled`]: disabled,
 
-         });
 
-         const nodeHaveData = !isEmpty(nodes) && !isEmpty(nodes[0]);
 
-         const isDisableStrictlyNode = disableStrictly && nodeHaveData && disabledKeys.has(nodes[0].key);
 
-         const closable = nodeHaveData && !nodes[0].disabled && !disabled && !isDisableStrictlyNode;
 
-         const onClose = (tagChildren: React.ReactNode, e: React.MouseEvent) => {
 
-             // When value has not changed, prevent clicking tag closeBtn to close tag
 
-             e.preventDefault();
 
-             this.removeTag(key);
 
-         };
 
-         const tagProps: Partial<TagProps> & React.Attributes = {
 
-             size: size === 'small' ? 'small' : 'large',
 
-             key: `tag-${value}-${idx}`,
 
-             color: 'white',
 
-             className: tagCls,
 
-             closable,
 
-             onClose,
 
-         };
 
-         const item = nodes[0];
 
-         const renderSelectedItem = isFunction(propRenderSelectedItem) ? propRenderSelectedItem :
 
-             (selectedItem: TreeNodeData) => ({
 
-                 isRenderInTag: true,
 
-                 content: get(selectedItem, treeNodeLabelProp, null)
 
-             });
 
-         if (isFunction(renderSelectedItem)) {
 
-             const { content, isRenderInTag } = item && treeNodeLabelProp in item ?
 
-                 (renderSelectedItem as RenderSelectedItemInMultiple)(item, { index: idx, onClose }) :
 
-                 null;
 
-             if (isRenderInTag) {
 
-                 return <Tag {...tagProps}>{content}</Tag>;
 
-             } else {
 
-                 return content;
 
-             }
 
-         }
 
-         return (
 
-             <Tag {...tagProps}>
 
-                 {value}
 
-             </Tag>
 
-         );
 
-     };
 
-     renderTagInput = () => {
 
-         const {
 
-             leafOnly,
 
-             disabled,
 
-             size,
 
-             searchAutoFocus,
 
-             placeholder,
 
-             maxTagCount,
 
-             checkRelation,
 
-             showRestTagsPopover, 
 
-             restTagsPopoverProps,
 
-             searchPosition,
 
-             filterTreeNode,
 
-             preventScroll
 
-         } = this.props;
 
-         const {
 
-             keyEntities,
 
-             checkedKeys,
 
-             inputValue,
 
-             realCheckedKeys,
 
-         } = this.state;
 
-         let keyList = [];
 
-         if (checkRelation === 'related') {
 
-             keyList = normalizeKeyList(checkedKeys, keyEntities, leafOnly, true);
 
-         } else if (checkRelation === 'unRelated') {
 
-             keyList = [...realCheckedKeys];
 
-         }
 
-         // auto focus search input divide into two parts
 
-         // 1. filterTreeNode && searchPosition === strings.SEARCH_POSITION_TRIGGER
 
-         //    Implemented by passing autofocus to the underlying input's autofocus
 
-         // 2. filterTreeNode && searchPosition === strings.SEARCH_POSITION_DROPDOWN
 
-         //    Due to the off-screen rendering in the tooltip implementation mechanism, if it is implemented through the 
 
-         //    autofocus of the input, when the option panel is opened, the page will scroll to top, so it is necessary 
 
-         //    to call the focus method through ref in the onVisibleChange callback of the Popover to achieve focus
 
-         const autoFocus = (filterTreeNode && searchPosition === strings.SEARCH_POSITION_TRIGGER) ? searchAutoFocus : undefined;
 
-         return (
 
-             <TagInput
 
-                 maxTagCount={maxTagCount}
 
-                 disabled={disabled}
 
-                 onInputChange={v => this.search(v)}
 
-                 ref={this.tagInputRef}
 
-                 placeholder={placeholder}
 
-                 value={keyList}
 
-                 inputValue={inputValue}
 
-                 size={size}
 
-                 showRestTagsPopover={showRestTagsPopover}
 
-                 restTagsPopoverProps={restTagsPopoverProps}
 
-                 // eslint-disable-next-line jsx-a11y/no-autofocus
 
-                 autoFocus={autoFocus}
 
-                 renderTagItem={(itemKey, index) => this.renderTagItem(itemKey, index)}
 
-                 onRemove={itemKey => this.removeTag(itemKey)}
 
-                 expandRestTagsOnClick={false}
 
-                 preventScroll={preventScroll}
 
-             />
 
-         );
 
-     };
 
-     // render Tree
 
-     renderInput = () => {
 
-         const {
 
-             searchPlaceholder,
 
-             searchRender,
 
-             showSearchClear,
 
-             searchPosition,
 
-             searchAutoFocus,
 
-             multiple,
 
-             disabled,
 
-         } = this.props;
 
-         const isDropdownPositionSearch = searchPosition === strings.SEARCH_POSITION_DROPDOWN;
 
-         const inputcls = cls({
 
-             [`${prefixTree}-input`]: isDropdownPositionSearch,
 
-             [`${prefixcls}-inputTrigger`]: !isDropdownPositionSearch
 
-         });
 
-         const { inputValue } = this.state;
 
-         const baseInputProps = {
 
-             value: inputValue,
 
-             className: inputcls,
 
-             onChange: (value: string) => this.search(value),
 
-         };
 
-         const inputDropdownProps = {
 
-             showClear: showSearchClear,
 
-             prefix: <IconSearch />,
 
-         };
 
-         const inputTriggerProps = {
 
-             autofocus: searchAutoFocus,
 
-             onFocus: (e: React.FocusEvent) => this.foundation.handleInputTriggerFocus(),
 
-             onBlur: (e: React.FocusEvent) => this.foundation.handleInputTriggerBlur(),
 
-             disabled,
 
-         };
 
-         const realInputProps = isDropdownPositionSearch ? inputDropdownProps : inputTriggerProps;
 
-         const wrapperCls = cls({
 
-             [`${prefixTree}-search-wrapper`]: isDropdownPositionSearch,
 
-             [`${prefixcls}-triggerSingleSearch-wrapper`]: !isDropdownPositionSearch && !multiple,
 
-         });
 
-         const useCusSearch = typeof searchRender === 'function' || typeof searchRender === 'boolean';
 
-         if (useCusSearch && !searchRender) {
 
-             return null;
 
-         }
 
-         return (
 
-             <div className={wrapperCls}>
 
-                 <LocaleConsumer componentName="TreeSelect">
 
-                     {(locale: Locale['TreeSelect']) => {
 
-                         const placeholder = isDropdownPositionSearch ?
 
-                             searchPlaceholder || locale.searchPlaceholder :
 
-                             '';
 
-                         if (useCusSearch) {
 
-                             return (searchRender as any)({ ...realInputProps, ...baseInputProps, placeholder });
 
-                         }
 
-                         return (
 
-                             <Input
 
-                                 aria-label='Filter TreeSelect item'
 
-                                 ref={this.inputRef as any}
 
-                                 placeholder={placeholder}
 
-                                 {...baseInputProps}
 
-                                 {...realInputProps}
 
-                             />
 
-                         );
 
-                     }}
 
-                 </LocaleConsumer>
 
-             </div>
 
-         );
 
-     };
 
-     renderEmpty = () => {
 
-         const { emptyContent } = this.props;
 
-         if (emptyContent) {
 
-             return <TreeNode empty emptyContent={this.props.emptyContent} />;
 
-         } else {
 
-             return (
 
-                 <LocaleConsumer componentName="Tree">
 
-                     {(locale: Locale['Tree']) => <TreeNode empty emptyContent={locale.emptyText} />}
 
-                 </LocaleConsumer>
 
-             );
 
-         }
 
-     };
 
-     onNodeLoad = (data: TreeNodeData) => new Promise(resolve => this.foundation.setLoadKeys(data, resolve));
 
-     onNodeSelect = (e: React.MouseEvent | React.KeyboardEvent, treeNode: TreeNodeProps) => {
 
-         this.foundation.handleNodeSelect(e, treeNode);
 
-     };
 
-     onNodeCheck = (e: React.MouseEvent | React.KeyboardEvent, treeNode: TreeNodeProps) => {
 
-         this.foundation.handleNodeSelect(e, treeNode);
 
-     };
 
-     onNodeExpand = (e: React.MouseEvent | React.KeyboardEvent, treeNode: TreeNodeProps) => {
 
-         this.foundation.handleNodeExpand(e, treeNode);
 
-     };
 
-     getTreeNodeRequiredProps = () => {
 
-         const { expandedKeys, selectedKeys, checkedKeys, halfCheckedKeys, keyEntities, filteredKeys } = this.state;
 
-         return {
 
-             expandedKeys: expandedKeys || new Set(),
 
-             selectedKeys: selectedKeys || [],
 
-             checkedKeys: checkedKeys || new Set(),
 
-             halfCheckedKeys: halfCheckedKeys || new Set(),
 
-             filteredKeys: filteredKeys || new Set(),
 
-             keyEntities,
 
-         };
 
-     };
 
-     getTreeNodeKey = (treeNode: TreeNodeData) => {
 
-         const { data } = treeNode;
 
-         // eslint-disable-next-line @typescript-eslint/no-shadow
 
-         const { key }: { key: string } = data;
 
-         return key;
 
-     };
 
-     /* Event handler function after popover is closed */
 
-     handlePopoverClose = isVisible => {
 
-         const { filterTreeNode, searchAutoFocus, searchPosition } = this.props;
 
-         if (isVisible === false && Boolean(filterTreeNode)) {
 
-             this.foundation.clearInput();
 
-         }
 
-         if (filterTreeNode && searchPosition === strings.SEARCH_POSITION_DROPDOWN && isVisible && searchAutoFocus) {
 
-             this.foundation.focusInput(true);
 
-         } 
 
-     }
 
-     renderTreeNode = (treeNode: FlattenNode, ind: number, style: React.CSSProperties) => {
 
-         const { data } = treeNode;
 
-         // eslint-disable-next-line @typescript-eslint/no-shadow
 
-         const { key }: { key: string } = data;
 
-         const treeNodeProps = this.foundation.getTreeNodeProps(key);
 
-         if (!treeNodeProps) {
 
-             return null;
 
-         }
 
-         return <TreeNode {...treeNodeProps} {...data} key={key} data={data} style={style} />;
 
-     };
 
-     itemKey = (index: number, data: Record<string, any>) => {
 
-         const { visibleOptions } = data;
 
-         // Find the item at the specified index.
 
-         const item = visibleOptions[index];
 
-         // Return a value that uniquely identifies this item.
 
-         return item.key;
 
-     };
 
-     renderNodeList = () => {
 
-         const { flattenNodes, motionKeys, motionType, filteredKeys } = this.state;
 
-         const { direction } = this.context;
 
-         const { virtualize, motionExpand } = this.props;
 
-         const isExpandControlled = 'expandedKeys' in this.props;
 
-         if (!virtualize || isEmpty(virtualize)) {
 
-             return (
 
-                 <NodeList
 
-                     flattenNodes={flattenNodes}
 
-                     flattenList={this._flattenNodes}
 
-                     motionKeys={motionExpand ? motionKeys : new Set([])}
 
-                     motionType={motionType}
 
-                     // When motionKeys is empty, but filteredKeys is not empty (that is, the search hits), this situation should be distinguished from ordinary motionKeys
 
-                     searchTargetIsDeep={
 
-                         isExpandControlled &&
 
-                         motionExpand &&
 
-                         isEmpty(motionKeys) &&
 
-                         !isEmpty(filteredKeys)
 
-                     }
 
-                     onMotionEnd={this.onMotionEnd}
 
-                     renderTreeNode={this.renderTreeNode}
 
-                 />
 
-             );
 
-         }
 
-         const data = {
 
-             visibleOptions: flattenNodes,
 
-             renderOption: this.renderTreeNode
 
-         };
 
-         return (
 
-             <AutoSizer defaultHeight={virtualize.height} defaultWidth={virtualize.width}>
 
-                 {({ height, width }) => (
 
-                     <VirtualList
 
-                         itemCount={flattenNodes.length}
 
-                         itemSize={virtualize.itemSize}
 
-                         height={height}
 
-                         width={width}
 
-                         // @ts-ignore avoid strict check of itemKey
 
-                         itemKey={this.itemKey}
 
-                         itemData={data}
 
-                         className={`${prefixTree}-virtual-list`}
 
-                         style={{ direction }}
 
-                     >
 
-                         {VirtualRow}
 
-                     </VirtualList>
 
-                 )}
 
-             </AutoSizer>
 
-         );
 
-     };
 
-     renderTree = () => {
 
-         const { keyEntities, motionKeys, motionType, inputValue, filteredKeys, flattenNodes, checkedKeys, realCheckedKeys } = this.state;
 
-         const {
 
-             loadData,
 
-             filterTreeNode,
 
-             disabled,
 
-             multiple,
 
-             showFilteredOnly,
 
-             motionExpand,
 
-             outerBottomSlot,
 
-             outerTopSlot,
 
-             expandAction,
 
-             labelEllipsis,
 
-             virtualize,
 
-             optionListStyle,
 
-             searchPosition,
 
-             renderLabel,
 
-             renderFullLabel,
 
-             checkRelation,
 
-         } = this.props;
 
-         const wrapperCls = cls(`${prefixTree}-wrapper`);
 
-         const listCls = cls(`${prefixTree}-option-list`, {
 
-             [`${prefixTree}-option-list-block`]: true,
 
-         });
 
-         const searchNoRes = Boolean(inputValue) && !filteredKeys.size;
 
-         const noData = isEmpty(flattenNodes) || (showFilteredOnly && searchNoRes);
 
-         const isDropdownPositionSearch = searchPosition === strings.SEARCH_POSITION_DROPDOWN;
 
-         return (
 
-             <TreeContext.Provider
 
-                 value={{
 
-                     loadData,
 
-                     treeDisabled: disabled,
 
-                     motion: motionExpand,
 
-                     motionKeys,
 
-                     motionType,
 
-                     expandAction,
 
-                     filterTreeNode,
 
-                     keyEntities,
 
-                     onNodeClick: this.onNodeClick,
 
-                     onNodeDoubleClick: this.onNodeDoubleClick,
 
-                     // tree node will call this function when treeNode is right clicked
 
-                     onNodeRightClick: noop,
 
-                     onNodeExpand: this.onNodeExpand,
 
-                     onNodeSelect: this.onNodeSelect,
 
-                     onNodeCheck: this.onNodeCheck,
 
-                     renderTreeNode: this.renderTreeNode,
 
-                     multiple,
 
-                     showFilteredOnly,
 
-                     isSearching: Boolean(inputValue),
 
-                     renderLabel,
 
-                     renderFullLabel,
 
-                     labelEllipsis: typeof labelEllipsis === 'undefined' ? virtualize : labelEllipsis,
 
-                 }}
 
-             >
 
-                 <div className={wrapperCls}>
 
-                     {outerTopSlot}
 
-                     {
 
-                         !outerTopSlot &&
 
-                         filterTreeNode &&
 
-                         isDropdownPositionSearch &&
 
-                         this.renderInput()
 
-                     }
 
-                     <div className={listCls} role="tree" aria-multiselectable={multiple ? true : false} style={optionListStyle}>
 
-                         { noData ? this.renderEmpty() : (multiple ? 
 
-                             (<CheckboxGroup value={Array.from(checkRelation === 'related' ? checkedKeys : realCheckedKeys)}>
 
-                                 {this.renderNodeList()}
 
-                             </CheckboxGroup>) : 
 
-                             this.renderNodeList()
 
-                         )}
 
-                     </div>
 
-                     {outerBottomSlot}
 
-                 </div>
 
-             </TreeContext.Provider>
 
-         );
 
-     };
 
-     render() {
 
-         const content = this.renderContent();
 
-         const {
 
-             motion,
 
-             zIndex,
 
-             mouseLeaveDelay,
 
-             mouseEnterDelay,
 
-             autoAdjustOverflow,
 
-             stopPropagation,
 
-             getPopupContainer,
 
-             dropdownMargin,
 
-             position,
 
-         } = this.props;
 
-         const { isOpen, rePosKey } = this.state;
 
-         const selection = this.renderSelection();
 
-         const pos = position ? position : 'bottomLeft';
 
-         return (
 
-             <Popover
 
-                 stopPropagation={stopPropagation}
 
-                 getPopupContainer={getPopupContainer}
 
-                 zIndex={zIndex}
 
-                 motion={motion}
 
-                 margin={dropdownMargin}
 
-                 ref={this.optionsRef}
 
-                 content={content}
 
-                 visible={isOpen}
 
-                 trigger="custom"
 
-                 rePosKey={rePosKey}
 
-                 position={pos}
 
-                 autoAdjustOverflow={autoAdjustOverflow}
 
-                 mouseLeaveDelay={mouseLeaveDelay}
 
-                 mouseEnterDelay={mouseEnterDelay}
 
-                 onVisibleChange={this.handlePopoverClose}
 
-             >
 
-                 {selection}
 
-             </Popover>
 
-         );
 
-     }
 
- }
 
- export default TreeSelect;
 
 
  |