import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
import _extends from "@babel/runtime/helpers/esm/extends";
import _isFunction from "lodash/isFunction";
import _isNil from "lodash/isNil";
import _isUndefined from "lodash/isUndefined";
import _omit from "lodash/omit";
import _pick from "lodash/pick";
import React, { useState, useRef, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import { List, AutoSizer } from '../Picker/VirtualizedList';
import TreeNode from './TreeNode';
import { createChainedFunction, useClassNames, useCustom, useControlled, TREE_NODE_DROP_POSITION, KEY_VALUES, mergeRefs, shallowEqual } from '../utils';
import { getExpandWhenSearching, hasVisibleChildren, getDragNodeKeys, calDropNodePosition, createUpdateTreeDataFunction, useTreeDrag, useFlattenTreeData, getTreeActiveNode, getDefaultExpandItemValues, useTreeNodeRefs, useTreeSearch, focusPreviousItem, getFocusableItems, focusNextItem, getActiveItem, toggleExpand, useGetTreeNodeChildren, focusToActiveTreeNode, leftArrowHandler, focusTreeNode, rightArrowHandler, isSearching } from '../utils/treeUtils';
import { PickerToggle, PickerOverlay, SearchBar, PickerToggleTrigger, createConcatChildrenFunction, usePickerClassName, onMenuKeyDown as _onMenuKeyDown, usePublicMethods, listPickerPropTypes, listPickerDefaultProps, pickTriggerPropKeys, omitTriggerPropKeys, useToggleKeyDownEvent } from '../Picker';
// default value for virtualized
export var maxTreeHeight = 320;

var defaultProps = _extends({}, listPickerDefaultProps, {
  classPrefix: 'picker',
  as: 'div',
  height: 360,
  appearance: 'default',
  searchable: true,
  cleanable: true,
  menuAutoWidth: true,
  placement: 'bottomStart'
});

var TreePicker = /*#__PURE__*/React.forwardRef(function (props, ref) {
  var Component = props.as,
      data = props.data,
      style = props.style,
      controlledValue = props.value,
      inline = props.inline,
      overrideLocale = props.locale,
      height = props.height,
      className = props.className,
      disabled = props.disabled,
      placement = props.placement,
      cleanable = props.cleanable,
      menuStyle = props.menuStyle,
      searchable = props.searchable,
      virtualized = props.virtualized,
      classPrefix = props.classPrefix,
      defaultValue = props.defaultValue,
      placeholder = props.placeholder,
      searchKeyword = props.searchKeyword,
      menuClassName = props.menuClassName,
      menuAutoWidth = props.menuAutoWidth,
      searchBy = props.searchBy,
      toggleAs = props.toggleAs,
      labelKey = props.labelKey,
      valueKey = props.valueKey,
      childrenKey = props.childrenKey,
      draggable = props.draggable,
      defaultExpandAll = props.defaultExpandAll,
      disabledItemValues = props.disabledItemValues,
      controlledExpandItemValues = props.expandItemValues,
      defaultExpandItemValues = props.defaultExpandItemValues,
      id = props.id,
      getChildren = props.getChildren,
      renderTreeIcon = props.renderTreeIcon,
      renderTreeNode = props.renderTreeNode,
      onExited = props.onExited,
      onClean = props.onClean,
      onOpen = props.onOpen,
      onSearch = props.onSearch,
      onSelect = props.onSelect,
      onChange = props.onChange,
      onEntered = props.onEntered,
      onClose = props.onClose,
      onDragEnd = props.onDragEnd,
      onDragStart = props.onDragStart,
      onDragEnter = props.onDragEnter,
      onDragLeave = props.onDragLeave,
      onDragOver = props.onDragOver,
      onDrop = props.onDrop,
      onExpand = props.onExpand,
      renderExtraFooter = props.renderExtraFooter,
      renderMenu = props.renderMenu,
      renderValue = props.renderValue,
      renderDragNode = props.renderDragNode,
      rest = _objectWithoutPropertiesLoose(props, ["as", "data", "style", "value", "inline", "locale", "height", "className", "disabled", "placement", "cleanable", "menuStyle", "searchable", "virtualized", "classPrefix", "defaultValue", "placeholder", "searchKeyword", "menuClassName", "menuAutoWidth", "searchBy", "toggleAs", "labelKey", "valueKey", "childrenKey", "draggable", "defaultExpandAll", "disabledItemValues", "expandItemValues", "defaultExpandItemValues", "id", "getChildren", "renderTreeIcon", "renderTreeNode", "onExited", "onClean", "onOpen", "onSearch", "onSelect", "onChange", "onEntered", "onClose", "onDragEnd", "onDragStart", "onDragEnter", "onDragLeave", "onDragOver", "onDrop", "onExpand", "renderExtraFooter", "renderMenu", "renderValue", "renderDragNode"]);

  var triggerRef = useRef();
  var targetRef = useRef();
  var listRef = useRef();
  var overlayRef = useRef();
  var searchInputRef = useRef();
  var treeViewRef = useRef();

  var _useCustom = useCustom('Picker', overrideLocale),
      rtl = _useCustom.rtl,
      locale = _useCustom.locale;

  var _useControlled = useControlled(controlledValue, defaultValue),
      value = _useControlled[0],
      setValue = _useControlled[1],
      isControlled = _useControlled[2];

  var _useGetTreeNodeChildr = useGetTreeNodeChildren(data, valueKey, childrenKey),
      treeData = _useGetTreeNodeChildr.data,
      setTreeData = _useGetTreeNodeChildr.setData,
      loadingNodeValues = _useGetTreeNodeChildr.loadingNodeValues,
      loadChildren = _useGetTreeNodeChildr.loadChildren;

  var _useControlled2 = useControlled(controlledExpandItemValues, getDefaultExpandItemValues(treeData, {
    defaultExpandAll: defaultExpandAll,
    valueKey: valueKey,
    childrenKey: childrenKey,
    defaultExpandItemValues: defaultExpandItemValues
  })),
      expandItemValues = _useControlled2[0],
      setExpandItemValues = _useControlled2[1];

  var _useState = useState(false),
      active = _useState[0],
      setActive = _useState[1];

  var _useState2 = useState(null),
      focusItemValue = _useState2[0],
      setFocusItemValue = _useState2[1];

  var _useFlattenTreeData = useFlattenTreeData({
    data: treeData,
    labelKey: labelKey,
    valueKey: valueKey,
    childrenKey: childrenKey,
    callback: function callback() {
      // after flattenData, always trigger re-render
      forceUpdate();
    }
  }),
      flattenNodes = _useFlattenTreeData.flattenNodes,
      forceUpdate = _useFlattenTreeData.forceUpdate,
      formatVirtualizedTreeData = _useFlattenTreeData.formatVirtualizedTreeData;

  var _useClassNames = useClassNames(classPrefix),
      prefix = _useClassNames.prefix,
      merge = _useClassNames.merge;

  var _useClassNames2 = useClassNames('tree'),
      treePrefix = _useClassNames2.prefix,
      withTreeClassPrefix = _useClassNames2.withClassPrefix;

  var _useTreeSearch = useTreeSearch({
    labelKey: labelKey,
    childrenKey: childrenKey,
    searchKeyword: searchKeyword,
    data: treeData,
    searchBy: searchBy,
    callback: function callback(searchKeyword, _filterData, event) {
      onSearch === null || onSearch === void 0 ? void 0 : onSearch(searchKeyword, event);
    }
  }),
      filteredData = _useTreeSearch.filteredData,
      searchKeywordState = _useTreeSearch.searchKeywordState,
      setSearchKeyword = _useTreeSearch.setSearchKeyword,
      handleSearch = _useTreeSearch.handleSearch,
      setFilteredData = _useTreeSearch.setFilteredData;

  var _useTreeDrag = useTreeDrag(),
      dragNodeKeys = _useTreeDrag.dragNodeKeys,
      dragOverNodeKey = _useTreeDrag.dragOverNodeKey,
      dragNode = _useTreeDrag.dragNode,
      dropNodePosition = _useTreeDrag.dropNodePosition,
      setDragNodeKeys = _useTreeDrag.setDragNodeKeys,
      setDragOverNodeKey = _useTreeDrag.setDragOverNodeKey,
      setDragNode = _useTreeDrag.setDragNode,
      setDropNodePosition = _useTreeDrag.setDropNodePosition;

  var _useTreeNodeRefs = useTreeNodeRefs(),
      treeNodesRefs = _useTreeNodeRefs.treeNodesRefs,
      saveTreeNodeRef = _useTreeNodeRefs.saveTreeNodeRef;

  var activeNode = getTreeActiveNode(flattenNodes, value, valueKey);
  var getFormattedNodes = useCallback(function (render) {
    var formattedNodes = [];

    if (virtualized) {
      formattedNodes = formatVirtualizedTreeData(flattenNodes, filteredData, expandItemValues, {
        searchKeyword: searchKeywordState
      }).filter(function (n) {
        return n.visible;
      });
    } else {
      formattedNodes = filteredData.map(function (dataItem, index) {
        return render === null || render === void 0 ? void 0 : render(dataItem, index, 1);
      });
    }

    return formattedNodes;
  }, [searchKeywordState, expandItemValues, filteredData, flattenNodes, formatVirtualizedTreeData, virtualized]);
  var focusActiveNode = useCallback(function () {
    focusToActiveTreeNode({
      list: listRef.current,
      valueKey: valueKey,
      selector: "." + treePrefix('node-active'),
      activeNode: activeNode,
      virtualized: virtualized,
      container: treeViewRef.current,
      formattedNodes: getFormattedNodes()
    });
  }, [treePrefix, activeNode, getFormattedNodes, valueKey, virtualized]);
  useEffect(function () {
    setFilteredData(data, searchKeywordState);
    setTreeData(data);
  }, [data, searchKeywordState, setFilteredData, setTreeData]);
  useEffect(function () {
    setFilteredData(treeData, searchKeywordState);
  }, [treeData, searchKeywordState, setFilteredData]);
  useEffect(function () {
    if (Array.isArray(controlledExpandItemValues)) {
      setExpandItemValues(controlledExpandItemValues);
    }
  }, [controlledExpandItemValues, setExpandItemValues]);
  useEffect(function () {
    setSearchKeyword(searchKeyword !== null && searchKeyword !== void 0 ? searchKeyword : '');
  }, [searchKeyword, setSearchKeyword]);
  var getDropData = useCallback(function (nodeData) {
    var options = {
      valueKey: valueKey,
      childrenKey: childrenKey
    };
    return {
      /** draggingNode */
      dragNode: dragNode,

      /** dropNode */
      dropNode: nodeData,

      /** dragAndDrop Position type */
      dropNodePosition: dropNodePosition,
      createUpdateDataFunction: createUpdateTreeDataFunction({
        dragNode: dragNode,
        dropNode: nodeData,
        dropNodePosition: dropNodePosition
      }, options)
    };
  }, [dragNode, valueKey, childrenKey, dropNodePosition]);

  var getTreeNodeProps = function getTreeNodeProps(node, layer, index) {
    var draggingNode = dragNode !== null && dragNode !== void 0 ? dragNode : {};
    return {
      as: Component,
      rtl: rtl,
      value: node[valueKey],
      label: node[labelKey],
      index: index,
      layer: layer,
      loading: loadingNodeValues.some(function (item) {
        return shallowEqual(item, node[valueKey]);
      }),
      expand: node.expand,
      active: shallowEqual(node[valueKey], value),
      focus: shallowEqual(node[valueKey], focusItemValue),
      visible: node.visible,
      draggable: draggable,
      dragging: shallowEqual(node[valueKey], draggingNode[valueKey]),
      children: node[childrenKey],
      nodeData: node,
      disabled: disabledItemValues.some(function (disabledItem) {
        return shallowEqual(disabledItem, node[valueKey]);
      }),
      dragOver: shallowEqual(node[valueKey], dragOverNodeKey) && dropNodePosition === TREE_NODE_DROP_POSITION.DRAG_OVER,
      dragOverTop: shallowEqual(node[valueKey], dragOverNodeKey) && dropNodePosition === TREE_NODE_DROP_POSITION.DRAG_OVER_TOP,
      dragOverBottom: shallowEqual(node[valueKey], dragOverNodeKey) && dropNodePosition === TREE_NODE_DROP_POSITION.DRAG_OVER_BOTTOM,
      onSelect: handleSelect,
      onDragStart: handleDragStart,
      onDragEnter: handleDragEnter,
      onDragOver: handleDragOver,
      onDragLeave: handleDragLeave,
      onDragEnd: handleDragEnd,
      onDrop: handleDrop,
      onExpand: handleExpand,
      onRenderTreeNode: renderTreeNode,
      onRenderTreeIcon: renderTreeIcon
    };
  };

  var handleSelect = useCallback(function (nodeData, event) {
    var _targetRef$current, _triggerRef$current, _triggerRef$current$c;

    if (!nodeData) {
      return;
    }

    var nodeValue = nodeData[valueKey];

    if (!isControlled) {
      setValue(nodeValue);
    }

    setFocusItemValue(nodeData[valueKey]);
    onChange === null || onChange === void 0 ? void 0 : onChange(nodeValue, event);
    onSelect === null || onSelect === void 0 ? void 0 : onSelect(nodeData, nodeValue, event);
    (_targetRef$current = targetRef.current) === null || _targetRef$current === void 0 ? void 0 : _targetRef$current.focus();
    (_triggerRef$current = triggerRef.current) === null || _triggerRef$current === void 0 ? void 0 : (_triggerRef$current$c = _triggerRef$current.close) === null || _triggerRef$current$c === void 0 ? void 0 : _triggerRef$current$c.call(_triggerRef$current);
  }, [valueKey, isControlled, onChange, onSelect, setValue]);
  var handleExpand = useCallback(function (node) {
    var nextExpandItemValues = toggleExpand({
      node: node,
      isExpand: !node.expand,
      expandItemValues: expandItemValues,
      valueKey: valueKey
    });
    setExpandItemValues(nextExpandItemValues);
    onExpand === null || onExpand === void 0 ? void 0 : onExpand(nextExpandItemValues, node, createConcatChildrenFunction(node, node[valueKey], {
      valueKey: valueKey,
      childrenKey: childrenKey
    }));

    if (_isFunction(getChildren) && !node.expand && Array.isArray(node[childrenKey]) && node[childrenKey].length === 0) {
      loadChildren(node, getChildren);
    }
  }, [valueKey, childrenKey, expandItemValues, getChildren, onExpand, setExpandItemValues, loadChildren]);
  var handleDragStart = useCallback(function (nodeData, event) {
    if (draggable) {
      setDragNodeKeys(getDragNodeKeys(nodeData, childrenKey, valueKey));
      setDragNode(flattenNodes[nodeData.refKey]);
      onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(nodeData, event);
    }
  }, [draggable, childrenKey, flattenNodes, onDragStart, setDragNodeKeys, setDragNode, valueKey]);
  var handleDragEnter = useCallback(function (nodeData, event) {
    if (dragNodeKeys.some(function (d) {
      return shallowEqual(d, nodeData[valueKey]);
    })) {
      return;
    }

    if (dragNode) {
      setDragOverNodeKey(nodeData[valueKey]);
      setDropNodePosition(calDropNodePosition(event, treeNodesRefs[nodeData.refKey]));
    }

    onDragEnter === null || onDragEnter === void 0 ? void 0 : onDragEnter(nodeData, event);
  }, [dragNode, treeNodesRefs, dragNodeKeys, onDragEnter, setDragOverNodeKey, setDropNodePosition, valueKey]);
  var handleDragOver = useCallback(function (nodeData, event) {
    if (dragNodeKeys.some(function (d) {
      return shallowEqual(d, nodeData[valueKey]);
    })) {
      return;
    }

    if (dragNode && shallowEqual(nodeData[valueKey], dragOverNodeKey)) {
      var lastDropNodePosition = calDropNodePosition(event, treeNodesRefs[nodeData.refKey]);
      if (lastDropNodePosition === dropNodePosition) return;
      setDropNodePosition(lastDropNodePosition);
    }

    onDragOver === null || onDragOver === void 0 ? void 0 : onDragOver(nodeData, event);
  }, [dragNode, dragNodeKeys, dragOverNodeKey, dropNodePosition, onDragOver, setDropNodePosition, treeNodesRefs, valueKey]);
  var handleDragLeave = useCallback(function (nodeData, event) {
    onDragLeave === null || onDragLeave === void 0 ? void 0 : onDragLeave(nodeData, event);
  }, [onDragLeave]);
  var handleDragEnd = useCallback(function (nodeData, event) {
    setDragNode(null);
    setDragNodeKeys([]);
    setDragOverNodeKey(null);
    onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(nodeData, event);
  }, [setDragNode, setDragNodeKeys, setDragOverNodeKey, onDragEnd]);
  var handleDrop = useCallback(function (nodeData, event) {
    if (dragNodeKeys.some(function (d) {
      return shallowEqual(d, nodeData[valueKey]);
    })) {
      console.error('Cannot drag a node to itself and its children');
    } else {
      var dropData = getDropData(nodeData);
      onDrop === null || onDrop === void 0 ? void 0 : onDrop(dropData, event);
    }

    setDragNode(null);
    setDragNodeKeys([]);
    setDragOverNodeKey(null);
  }, [dragNodeKeys, setDragNode, setDragOverNodeKey, setDragNodeKeys, onDrop, getDropData, valueKey]);
  var handleOpen = useCallback(function () {
    var _triggerRef$current2, _triggerRef$current2$;

    (_triggerRef$current2 = triggerRef.current) === null || _triggerRef$current2 === void 0 ? void 0 : (_triggerRef$current2$ = _triggerRef$current2.open) === null || _triggerRef$current2$ === void 0 ? void 0 : _triggerRef$current2$.call(_triggerRef$current2);
    focusActiveNode();
    onOpen === null || onOpen === void 0 ? void 0 : onOpen();
    setActive(true);
  }, [focusActiveNode, onOpen]);
  var handleClose = useCallback(function () {
    var _triggerRef$current3, _triggerRef$current3$, _targetRef$current2;

    (_triggerRef$current3 = triggerRef.current) === null || _triggerRef$current3 === void 0 ? void 0 : (_triggerRef$current3$ = _triggerRef$current3.close) === null || _triggerRef$current3$ === void 0 ? void 0 : _triggerRef$current3$.call(_triggerRef$current3);
    setSearchKeyword('');
    onClose === null || onClose === void 0 ? void 0 : onClose();
    setActive(false);
    setFocusItemValue(activeNode === null || activeNode === void 0 ? void 0 : activeNode[valueKey]);
    /**
     * when using keyboard toggle picker, should refocus on PickerToggle Component after close picker menu
     */

    (_targetRef$current2 = targetRef.current) === null || _targetRef$current2 === void 0 ? void 0 : _targetRef$current2.focus();
  }, [activeNode, onClose, setSearchKeyword, valueKey]);
  usePublicMethods(ref, {
    triggerRef: triggerRef,
    overlayRef: overlayRef,
    targetRef: targetRef
  });
  var handleFocusItem = useCallback(function (key) {
    var focusableItems = getFocusableItems(filteredData, {
      disabledItemValues: disabledItemValues,
      valueKey: valueKey,
      childrenKey: childrenKey,
      expandItemValues: expandItemValues
    }, isSearching(searchKeywordState));
    var selector = "." + treePrefix('node-label');
    var focusProps = {
      focusItemValue: focusItemValue,
      focusableItems: focusableItems,
      treeNodesRefs: treeNodesRefs,
      selector: selector,
      valueKey: valueKey,
      callback: function callback(nextFocusItemValue) {
        setFocusItemValue(nextFocusItemValue);
      }
    };

    if (key === KEY_VALUES.DOWN) {
      focusNextItem(focusProps);
      return;
    }

    if (key === KEY_VALUES.UP) {
      focusPreviousItem(focusProps);
    }
  }, [searchKeywordState, expandItemValues, filteredData, focusItemValue, treeNodesRefs, treePrefix, valueKey, childrenKey, disabledItemValues]);
  var handleLeftArrow = useCallback(function () {
    var focusItem = getActiveItem(focusItemValue, flattenNodes, valueKey);
    leftArrowHandler({
      focusItem: focusItem,
      expand: expandItemValues.includes(focusItem === null || focusItem === void 0 ? void 0 : focusItem[valueKey]),
      onExpand: handleExpand,
      onFocusItem: function onFocusItem() {
        var _focusItem$parent, _focusItem$parent2;

        setFocusItemValue(focusItem === null || focusItem === void 0 ? void 0 : (_focusItem$parent = focusItem.parent) === null || _focusItem$parent === void 0 ? void 0 : _focusItem$parent[valueKey]);
        focusTreeNode(focusItem === null || focusItem === void 0 ? void 0 : (_focusItem$parent2 = focusItem.parent) === null || _focusItem$parent2 === void 0 ? void 0 : _focusItem$parent2.refKey, treeNodesRefs, "." + treePrefix('node-label'));
      }
    });
  }, [expandItemValues, flattenNodes, focusItemValue, handleExpand, treeNodesRefs, treePrefix, valueKey]);
  var handleRightArrow = useCallback(function () {
    var focusItem = getActiveItem(focusItemValue, flattenNodes, valueKey);
    rightArrowHandler({
      focusItem: focusItem,
      expand: expandItemValues.includes(focusItem === null || focusItem === void 0 ? void 0 : focusItem[valueKey]),
      childrenKey: childrenKey,
      onExpand: handleExpand,
      onFocusItem: function onFocusItem() {
        handleFocusItem(KEY_VALUES.DOWN);
      }
    });
  }, [focusItemValue, flattenNodes, valueKey, expandItemValues, childrenKey, handleExpand, handleFocusItem]);
  var selectActiveItem = useCallback(function (event) {
    var activeItem = getActiveItem(focusItemValue, flattenNodes, valueKey);
    handleSelect(activeItem, event);
  }, [flattenNodes, valueKey, focusItemValue, handleSelect]);
  var handleClean = useCallback(function (event) {
    var target = event.target; // exclude searchBar

    if (target.matches('div[role="searchbox"] > input')) {
      return;
    }

    setValue(null);
    onChange === null || onChange === void 0 ? void 0 : onChange(null, event);
  }, [onChange, setValue]);
  var onPickerKeydown = useToggleKeyDownEvent(_extends({
    toggle: !activeNode || !active,
    triggerRef: triggerRef,
    targetRef: targetRef,
    overlayRef: overlayRef,
    searchInputRef: searchInputRef,
    active: active,
    onExit: handleClean,
    onClose: handleClose,
    onMenuKeyDown: function onMenuKeyDown(event) {
      _onMenuKeyDown(event, {
        down: function down() {
          return handleFocusItem(KEY_VALUES.DOWN);
        },
        up: function up() {
          return handleFocusItem(KEY_VALUES.UP);
        },
        left: rtl ? handleRightArrow : handleLeftArrow,
        right: rtl ? handleLeftArrow : handleRightArrow,
        enter: selectActiveItem,
        del: handleClean
      });
    }
  }, rest));
  var handleTreeKeyDown = useCallback(function (event) {
    if (!treeViewRef.current) {
      return;
    }

    _onMenuKeyDown(event, {
      down: function down() {
        return handleFocusItem(KEY_VALUES.DOWN);
      },
      up: function up() {
        return handleFocusItem(KEY_VALUES.UP);
      },
      left: rtl ? handleRightArrow : handleLeftArrow,
      right: rtl ? handleLeftArrow : handleRightArrow,
      enter: selectActiveItem
    });
  }, [handleFocusItem, handleLeftArrow, handleRightArrow, rtl, selectActiveItem]);

  var renderNode = function renderNode(node, index, layer) {
    if (!node.visible) {
      return null;
    }

    var children = node[childrenKey];
    var expand = getExpandWhenSearching(searchKeywordState, expandItemValues.includes(node[valueKey]));
    var visibleChildren = _isUndefined(searchKeywordState) || searchKeywordState.length === 0 ? !!children : hasVisibleChildren(node, childrenKey);

    var nodeProps = _extends({}, getTreeNodeProps(_extends({}, node, {
      expand: expand
    }), layer, index), {
      hasChildren: visibleChildren
    });

    if (nodeProps.hasChildren) {
      var _merge;

      layer += 1;
      var openClass = treePrefix('open');
      var childrenClass = merge(treePrefix('node-children'), (_merge = {}, _merge[openClass] = expand && visibleChildren, _merge));
      var nodes = children || [];
      return /*#__PURE__*/React.createElement("div", {
        className: childrenClass,
        key: node[valueKey]
      }, /*#__PURE__*/React.createElement(TreeNode, _extends({}, nodeProps, {
        ref: function ref(_ref) {
          return saveTreeNodeRef(node.refKey, _ref);
        }
      })), /*#__PURE__*/React.createElement("div", {
        className: treePrefix('children')
      }, nodes.map(function (child, i) {
        return renderNode(child, i, layer);
      })));
    }

    return /*#__PURE__*/React.createElement(TreeNode, _extends({
      ref: function ref(_ref2) {
        return saveTreeNodeRef(node.refKey, _ref2);
      },
      key: node[valueKey]
    }, nodeProps));
  };

  var renderVirtualListNode = function renderVirtualListNode(nodes) {
    return function (_ref3) {
      var key = _ref3.key,
          index = _ref3.index,
          style = _ref3.style;
      var node = nodes[index];
      var layer = node.layer,
          visible = node.visible;
      var expand = getExpandWhenSearching(searchKeywordState, expandItemValues.includes(node[valueKey]));

      if (!node.visible) {
        return null;
      }

      var nodeProps = _extends({}, getTreeNodeProps(_extends({}, node, {
        expand: expand
      }), layer), {
        style: style,
        hasChildren: node.hasChildren
      });

      return visible && /*#__PURE__*/React.createElement(TreeNode, _extends({
        ref: function ref(_ref4) {
          return saveTreeNodeRef(node.refKey, _ref4);
        },
        key: key
      }, nodeProps));
    };
  };

  var renderDefaultDragNode = function renderDefaultDragNode() {
    if (draggable) {
      var dragNodeContent = dragNode === null || dragNode === void 0 ? void 0 : dragNode[labelKey];

      if (_isFunction(renderDragNode)) {
        dragNodeContent = renderDragNode(dragNode);
      }

      return /*#__PURE__*/React.createElement("span", {
        id: "drag-node",
        className: treePrefix('drag-node-mover')
      }, dragNodeContent);
    }

    return null;
  };

  var renderTree = function renderTree() {
    var _withTreeClassPrefix;

    var classes = withTreeClassPrefix((_withTreeClassPrefix = {}, _withTreeClassPrefix[className !== null && className !== void 0 ? className : ''] = inline, _withTreeClassPrefix.virtualized = virtualized, _withTreeClassPrefix));
    var formattedNodes = getFormattedNodes(renderNode);
    var styles = inline ? _extends({
      height: height
    }, style) : {};
    return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
      role: "tree",
      id: id ? id + "-listbox" : undefined,
      ref: treeViewRef,
      className: classes,
      style: styles,
      onKeyDown: inline ? handleTreeKeyDown : undefined
    }, /*#__PURE__*/React.createElement("div", {
      className: treePrefix('nodes')
    }, virtualized ? /*#__PURE__*/React.createElement(AutoSizer, {
      defaultHeight: inline ? height : maxTreeHeight,
      style: {
        width: 'auto',
        height: 'auto'
      }
    }, function (_ref5) {
      var height = _ref5.height,
          width = _ref5.width;
      return /*#__PURE__*/React.createElement(List, {
        ref: listRef,
        width: width,
        height: height,
        rowHeight: 36,
        rowCount: formattedNodes.length,
        rowRenderer: renderVirtualListNode(formattedNodes),
        scrollToAlignment: "center"
      });
    }) : formattedNodes)), renderDefaultDragNode());
  };

  var renderDropdownMenu = function renderDropdownMenu(positionProps, speakerRef) {
    var left = positionProps.left,
        top = positionProps.top,
        className = positionProps.className;
    var classes = merge(className, menuClassName, prefix('tree-menu'));

    var mergedMenuStyle = _extends({}, menuStyle, {
      left: left,
      top: top
    });

    var styles = virtualized ? _extends({
      height: height
    }, mergedMenuStyle) : _extends({}, mergedMenuStyle);
    return /*#__PURE__*/React.createElement(PickerOverlay, {
      autoWidth: menuAutoWidth,
      className: classes,
      style: styles,
      ref: mergeRefs(overlayRef, speakerRef),
      onKeyDown: onPickerKeydown,
      target: triggerRef
    }, searchable ? /*#__PURE__*/React.createElement(SearchBar, {
      placeholder: locale.searchPlaceholder,
      onChange: handleSearch,
      value: searchKeywordState,
      inputRef: searchInputRef
    }) : null, renderMenu ? renderMenu(renderTree()) : renderTree(), renderExtraFooter === null || renderExtraFooter === void 0 ? void 0 : renderExtraFooter());
  };
  /**
   * 1.Have a value and the value is valid.
   * 2.Regardless of whether the value is valid, as long as renderValue is set, it is judged to have a value.
   */


  var hasValidValue = !_isNil(activeNode) || !_isNil(value) && _isFunction(renderValue);

  var selectedElement = placeholder;

  if (hasValidValue) {
    var node = activeNode !== null && activeNode !== void 0 ? activeNode : {};
    selectedElement = node[labelKey];

    if (_isFunction(renderValue)) {
      selectedElement = renderValue(value, node, selectedElement);

      if (_isNil(selectedElement)) {
        hasValidValue = false;
      }
    }
  }

  var _usePickerClassName = usePickerClassName(_extends({}, props, {
    hasValue: hasValidValue,
    name: 'tree'
  })),
      classes = _usePickerClassName[0],
      usedClassNamePropKeys = _usePickerClassName[1];

  if (inline) {
    return renderTree();
  }

  return /*#__PURE__*/React.createElement(PickerToggleTrigger, {
    pickerProps: _pick(props, pickTriggerPropKeys),
    ref: triggerRef,
    placement: placement,
    onEnter: handleOpen,
    onEntered: onEntered,
    onExited: createChainedFunction(handleClose, onExited),
    speaker: renderDropdownMenu
  }, /*#__PURE__*/React.createElement(Component, {
    className: classes,
    style: style
  }, /*#__PURE__*/React.createElement(PickerToggle, _extends({}, _omit(rest, [].concat(omitTriggerPropKeys, usedClassNamePropKeys, ['cascade'])), {
    id: id,
    ref: targetRef,
    onKeyDown: onPickerKeydown,
    onClean: createChainedFunction(handleClean, onClean),
    cleanable: cleanable && !disabled,
    as: toggleAs,
    disabled: disabled,
    hasValue: hasValidValue,
    active: active,
    placement: placement,
    inputValue: value
  }), selectedElement || locale.placeholder)));
});
TreePicker.displayName = 'TreePicker';
TreePicker.defaultProps = defaultProps;
TreePicker.propTypes = _extends({}, listPickerPropTypes, {
  locale: PropTypes.any,
  appearance: PropTypes.oneOf(['default', 'subtle']),
  height: PropTypes.number,
  inline: PropTypes.bool,
  draggable: PropTypes.bool,
  virtualized: PropTypes.bool,
  searchable: PropTypes.bool,
  menuAutoWidth: PropTypes.bool,
  searchKeyword: PropTypes.string,
  defaultExpandAll: PropTypes.bool,
  expandItemValues: PropTypes.array,
  defaultExpandItemValues: PropTypes.array,
  onSearch: PropTypes.func,
  onExpand: PropTypes.func,
  onSelect: PropTypes.func,
  renderMenu: PropTypes.func,
  renderTreeNode: PropTypes.func,
  renderTreeIcon: PropTypes.func,
  renderExtraFooter: PropTypes.func,
  renderDragNode: PropTypes.func,
  searchBy: PropTypes.func
});
export default TreePicker;