text: "use strict";
  
  var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
  
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  
  exports.__esModule = true;
  exports.useTree = useTree;
  
  var _uniq2 = _interopRequireDefault(require("lodash/uniq"));
  
  var _invoke2 = _interopRequireDefault(require("lodash/invoke"));
  
  var _without2 = _interopRequireDefault(require("lodash/without"));
  
  var React = _interopRequireWildcard(require("react"));
  
  var _reactBindings = require("@fluentui/react-bindings");
  
  var _flattenTree = require("./flattenTree");
  
  /**
   * This hook returns a stable `getItemById()` function that will lookup in latest `flatTree`.
   * This is used to have stable callbacks that can be passed to React's Context.
   */
  function useGetItemById(flatTree) {
    // An exception is thrown there to ensure that a proper callback will assigned to ref
    var callbackRef = React.useRef(function () {
      throw new Error('Callback is not assigned yet');
    }); // We are assigning a callback during render as it can be used during render and in event handlers. In dev mode we
    // are freezing objects to prevent their mutations
  
    callbackRef.current = function (itemId) {
      return process.env.NODE_ENV === 'production' ? flatTree[itemId] : Object.freeze(flatTree[itemId]);
    };
  
    return React.useCallback(function () {
      return callbackRef.current.apply(callbackRef, arguments);
    }, []);
  }
  
  function useStableProps(props) {
    var stableProps = React.useRef(props);
    React.useEffect(function () {
      stableProps.current = props;
    });
    return stableProps;
  }
  
  function useTree(options) {
    // We need this because we want to handle `expanded` prop on `items`, should be deprecated and removed
    var deprecated_initialActiveItemIds = React.useMemo(function () {
      return deprecated_getInitialActiveItemIds(options.items);
    }, // eslint-disable-next-line react-hooks/exhaustive-deps
    [] // initialValue only needs to be computed on mount
    );
  
    var _useAutoControlled = (0, _reactBindings.useAutoControlled)({
      defaultValue: options.defaultActiveItemIds,
      value: options.activeItemIds,
      initialValue: deprecated_initialActiveItemIds // will become []
  
    }),
        activeItemIds = _useAutoControlled[0],
        setActiveItemIdsState = _useAutoControlled[1]; // selectedItemIds is only valid for leaf nodes.
    // For non-leaf nodes, their 'selected' states are defered from all their descendents
  
  
    var _useAutoControlled2 = (0, _reactBindings.useAutoControlled)({
      defaultValue: options.defaultSelectedItemIds,
      value: options.selectedItemIds,
      initialValue: []
    }),
        selectedItemIds = _useAutoControlled2[0],
        setSelectedItemIdsState = _useAutoControlled2[1]; // We want to set `visibleItemIds` to simplify rendering later
  
  
    var _React$useMemo = React.useMemo(function () {
      return (0, _flattenTree.flattenTree)(options.items, activeItemIds, selectedItemIds);
    }, [activeItemIds, options.items, selectedItemIds]),
        flatTree = _React$useMemo.flatTree,
        visibleItemIds = _React$useMemo.visibleItemIds;
  
    var getItemById = useGetItemById(flatTree);
    var stableProps = useStableProps(options);
    var toggleItemActive = React.useCallback(function (e, idToToggle) {
      var item = getItemById(idToToggle);
  
      if (!item || !item.hasSubtree) {
        // leaf node does not have the concept of active/inactive
        return;
      }
  
      setActiveItemIdsState(function (activeItemIds) {
        var nextActiveItemIds;
        var isActiveId = activeItemIds.indexOf(idToToggle) !== -1;
  
        if (isActiveId) {
          nextActiveItemIds = (0, _without2.default)(activeItemIds, idToToggle);
        } else {
          nextActiveItemIds = [].concat(activeItemIds, [idToToggle]);
  
          if (options.exclusive) {
            var _getItemById, _getItemById2, _getItemById2$childre;
  
            // remove active siblings, if any, from activeItemIds
            var parent = (_getItemById = getItemById(idToToggle)) == null ? void 0 : _getItemById.parent;
            var activeSibling = (_getItemById2 = getItemById(parent)) == null ? void 0 : (_getItemById2$childre = _getItemById2.childrenIds) == null ? void 0 : _getItemById2$childre.find(function (id) {
              return id !== idToToggle && nextActiveItemIds.indexOf(id) >= 0;
            });
  
            if (activeSibling != null) {
              nextActiveItemIds = (0, _without2.default)(nextActiveItemIds, activeSibling);
            }
          }
        }
  
        (0, _invoke2.default)(stableProps.current, 'onActiveItemIdsChange', e, Object.assign({}, stableProps.current, {
          activeItemIds: nextActiveItemIds
        }));
        return nextActiveItemIds;
      });
    }, [getItemById, options.exclusive, setActiveItemIdsState, stableProps]);
    var expandSiblings = React.useCallback(function (e, focusedItemId) {
      if (options.exclusive) {
        return;
      }
  
      var focusedItem = getItemById(focusedItemId);
  
      if (!focusedItem) {
        return;
      }
  
      var parentItem = getItemById(focusedItem == null ? void 0 : focusedItem.parent);
      var siblingsIds = parentItem == null ? void 0 : parentItem.childrenIds;
  
      if (!siblingsIds) {
        return;
      }
  
      setActiveItemIdsState(function (activeItemIds) {
        var nextActiveItemIds = (0, _uniq2.default)(activeItemIds.concat(siblingsIds));
        (0, _invoke2.default)(stableProps.current, 'onActiveItemIdsChange', e, Object.assign({}, stableProps.current, {
          activeItemIds: nextActiveItemIds
        }));
        return nextActiveItemIds;
      });
    }, [getItemById, options.exclusive, setActiveItemIdsState, stableProps]);
    var toggleItemSelect = React.useCallback(function (e, idToToggle) {
      var item = getItemById(idToToggle);
  
      if (!item) {
        return;
      }
  
      var leafs = getLeafNodes(getItemById, idToToggle);
      setSelectedItemIdsState(function (selectedItemIds) {
        var nextSelectedItemIds = item.selected === true ? _without2.default.apply(void 0, [selectedItemIds].concat(leafs)) // remove all leaves from selected
        : (0, _uniq2.default)(selectedItemIds.concat(leafs)); // add all leaves to selected
  
        (0, _invoke2.default)(stableProps.current, 'onSelectedItemIdsChange', e, Object.assign({}, stableProps.current, {
          selectedItemIds: nextSelectedItemIds
        }));
        return nextSelectedItemIds;
      });
    }, [getItemById, setSelectedItemIdsState, stableProps]); // Maintains stable collection of refs to avoid unnecessary React context updates
  
    var nodes = React.useRef({});
    var registerItemRef = React.useCallback(function (id, node) {
      nodes.current[id] = node;
    }, []);
    var getItemRef = React.useCallback(function (id) {
      return nodes.current[id];
    }, []); // can be used for keyboard navigation ===
  
    var focusItemById = React.useCallback(function (id) {
      var itemRef = getItemRef(id);
  
      if (itemRef instanceof HTMLElement) {
        var _getItemById3;
  
        if ((_getItemById3 = getItemById(id)) != null && _getItemById3.hasSubtree) {
          itemRef.focus();
        } else {
          var _itemRef$firstElement;
  
          // when node is leaf, need to focus on the inner treeTitle
          (_itemRef$firstElement = itemRef.firstElementChild) == null ? void 0 : _itemRef$firstElement.focus();
        }
      }
    }, [getItemById, getItemRef]);
    var searchByFirstChar = React.useCallback(function (startIndex, endIndex, char) {
      for (var i = startIndex; i < endIndex; ++i) {
        var _getItemRef, _getItemRef$textConte, _getItemRef$textConte2, _getItemRef$textConte3;
  
        // get first charater of tree node using the same way aria does (https://www.w3.org/TR/wai-aria-practices-1.1/examples/treeview/treeview-2/js/treeitemLinks.js)
        var itemFirstChar = (_getItemRef = getItemRef(visibleItemIds[i])) == null ? void 0 : (_getItemRef$textConte = _getItemRef.textContent) == null ? void 0 : (_getItemRef$textConte2 = _getItemRef$textConte.trim()) == null ? void 0 : (_getItemRef$textConte3 = _getItemRef$textConte2.charAt(0)) == null ? void 0 : _getItemRef$textConte3.toLowerCase();
  
        if (itemFirstChar === char.toLowerCase()) {
          return i;
        }
      }
  
      return -1;
    }, [getItemRef, visibleItemIds]);
    var getToFocusIDByFirstCharacter = React.useCallback(function (e, idToStartSearch) {
      // Get start index for search
      var starIndex = visibleItemIds.indexOf(idToStartSearch) + 1;
  
      if (starIndex === visibleItemIds.length) {
        starIndex = 0;
      } // Check following nodes in tree
  
  
      var toFocusIndex = searchByFirstChar(starIndex, visibleItemIds.length, e.key); // If not found in following nodes, check from beginning
  
      if (toFocusIndex === -1) {
        toFocusIndex = searchByFirstChar(0, starIndex - 1, e.key);
      }
  
      if (toFocusIndex === -1) {
        return idToStartSearch;
      }
  
      return visibleItemIds[toFocusIndex];
    }, [searchByFirstChar, visibleItemIds]);
    return {
      flatTree: flatTree,
      getItemById: getItemById,
      activeItemIds: activeItemIds,
      visibleItemIds: visibleItemIds,
      registerItemRef: registerItemRef,
      getItemRef: getItemRef,
      toggleItemActive: toggleItemActive,
      focusItemById: focusItemById,
      expandSiblings: expandSiblings,
      toggleItemSelect: toggleItemSelect,
      getToFocusIDByFirstCharacter: getToFocusIDByFirstCharacter
    };
  }
  
  function deprecated_getInitialActiveItemIds(items) {
    if (!items) {
      return [];
    }
  
    var result = [];
    items.forEach(function (item) {
      if (item.expanded) {
        result.push(item.id);
      }
  
      if (item.items) {
        result = result.concat(deprecated_getInitialActiveItemIds(item.items));
      }
    });
    return result;
  }
  
  function getLeafNodes(getItemById, rootId) {
    var leafs = [];
  
    var traverseDown = function traverseDown(id) {
      var _getItemById4;
  
      if ((_getItemById4 = getItemById(id)) != null && _getItemById4.childrenIds) {
        var _getItemById5;
  
        (_getItemById5 = getItemById(id)) == null ? void 0 : _getItemById5.childrenIds.forEach(function (child) {
          traverseDown(child);
        });
      } else {
        leafs.push(id);
      }
    };
  
    traverseDown(rootId);
    return leafs;
  }
  //# sourceMappingURL=useTree.js.map
  