"use strict";

exports.__esModule = true;
exports.default = void 0;

var _react = _interopRequireWildcard(require("react"));

var _clsx = _interopRequireDefault(require("clsx"));

var _useRefs2 = _interopRequireDefault(require("../hooks/use-refs"));

var _useRect = require("../hooks/use-rect");

var _useTouch = _interopRequireDefault(require("../hooks/use-touch"));

var _useScrollParent = _interopRequireDefault(require("../hooks/use-scroll-parent"));

var _useEventListener = _interopRequireDefault(require("../hooks/use-event-listener"));

var _IndexBarContext = _interopRequireDefault(require("./IndexBarContext"));

var _PopupContext = _interopRequireDefault(require("../popup/PopupContext"));

var _utils = require("../utils");

var _hooks = require("../hooks");

var _renderToContainer = require("../utils/dom/renderToContainer");

var _useSsrCompat2 = _interopRequireDefault(require("../hooks/use-ssr-compat"));

var _IndexAnchor = require("./IndexAnchor");

var _ConfigProviderContext = _interopRequireDefault(require("../config-provider/ConfigProviderContext"));

var _constant = require("../utils/constant");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

/* eslint-disable @typescript-eslint/no-explicit-any */
var IndexBar = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
  var popupContext = (0, _react.useContext)(_PopupContext.default);

  var _useContext = (0, _react.useContext)(_ConfigProviderContext.default),
      prefixCls = _useContext.prefixCls,
      createNamespace = _useContext.createNamespace;

  var _createNamespace = createNamespace('index-bar', prefixCls),
      bem = _createNamespace[0];

  var children = props.children,
      sticky = props.sticky,
      zIndex = props.zIndex,
      highlightColor = props.highlightColor;

  var _useState = (0, _react.useState)(null),
      activeAnchor = _useState[0],
      setActiveAnchor = _useState[1];

  var root = (0, _react.useRef)(null);
  var sidebar = (0, _react.useRef)(null);
  var touchActiveIndex = (0, _react.useRef)(null);
  var touch = (0, _useTouch.default)();
  var scrollParent = (0, _useScrollParent.default)(root);

  var _useRefs = (0, _useRefs2.default)(),
      refs = _useRefs[0],
      setRefs = _useRefs[1];

  var _useSsrCompat = (0, _useSsrCompat2.default)(),
      ssrCompatRender = _useSsrCompat[0];

  var sidebarStyle = (0, _react.useMemo)(function () {
    if ((0, _utils.isDef)(zIndex)) {
      return {
        zIndex: +zIndex + 1
      };
    }

    return {};
  }, [zIndex]);
  var highlightStyle = (0, _react.useMemo)(function () {
    if (highlightColor) {
      return {
        color: highlightColor
      };
    }

    return {};
  }, [highlightColor]);

  var getScrollerRect = function getScrollerRect() {
    if (scrollParent.getBoundingClientRect) {
      return (0, _useRect.getRect)(scrollParent);
    }

    return {
      top: 0,
      left: 0
    };
  };

  var getActiveAnchor = function getActiveAnchor(scrollTop, rects) {
    for (var i = rects.length - 1; i >= 0; i -= 1) {
      var prevHeight = i > 0 ? rects[i - 1].height : 0;
      var reachTop = props.sticky ? prevHeight + props.stickyOffsetTop : 0;

      if (scrollTop + reachTop >= rects[i].top) {
        return i;
      }
    }

    return -1;
  };

  var onScroll = function onScroll() {
    if ((0, _utils.isHidden)(root.current) || !scrollParent) {
      return;
    }

    var indexList = props.indexList;
    var scrollTop = (0, _utils.getScrollTop)(scrollParent);
    var scrollParentRect = getScrollerRect();
    var rects = Object.values(refs).map(function (anchor) {
      return anchor.getRect(scrollParent, scrollParentRect);
    });
    var active = getActiveAnchor(scrollTop, rects);
    setActiveAnchor(indexList[active]);

    if (sticky) {
      Object.values(refs).forEach(function (item, index) {
        var updateState = item.updateState;

        if (index === active || index === active - 1) {
          var rect = item.root.current.getBoundingClientRect();
          updateState({
            left: rect.left,
            width: rect.width
          });
        } else {
          updateState({
            left: null,
            width: null
          });
        }

        if (index === active) {
          updateState({
            active: true,
            top: Math.max(props.stickyOffsetTop, rects[index].top - scrollTop) + scrollParentRect.top
          });
        } else if (index === active - 1) {
          var activeItemTop = rects[active].top - scrollTop;
          updateState({
            active: activeItemTop > 0,
            top: activeItemTop + scrollParentRect.top - rects[index].height
          });
        } else {
          updateState({
            active: false
          });
        }
      });
    }
  };

  var init = function init() {
    return setTimeout(onScroll, 0);
  };

  var renderIndexes = function renderIndexes() {
    return props.indexList.map(function (index) {
      var active = index === activeAnchor;
      return /*#__PURE__*/_react.default.createElement("span", {
        key: index,
        className: (0, _clsx.default)(bem('index', {
          active: active
        })),
        style: active ? highlightStyle : null,
        "data-index": index
      }, index);
    });
  };

  var onTouchStart = function onTouchStart(event) {
    touch.start(event);
  };

  var scrollTo = function scrollTo(index) {
    if (!index) {
      return;
    }

    if (refs[index]) {
      refs[index].root.current.scrollIntoView();

      if (props.sticky && props.stickyOffsetTop) {
        if (popupContext.visible) {
          (0, _utils.setScrollTop)(scrollParent, (0, _utils.getScrollTop)(scrollParent) - props.stickyOffsetTop);
        } else {
          (0, _utils.setRootScrollTop)((0, _utils.getRootScrollTop)() - props.stickyOffsetTop);
        }
      }

      if (props.onSelect && typeof props.onSelect === 'function') {
        props.onSelect(activeAnchor);
      }
    }
  };

  var scrollToElement = function scrollToElement(element) {
    var index = element.dataset.index;
    scrollTo(index);
  };

  var onClickSidebar = function onClickSidebar(event) {
    scrollToElement(event.target);
  };

  var onTouchMove = function onTouchMove(event) {
    touch.move(event);
    (0, _utils.preventDefault)(event);

    if (touch.isVertical()) {
      var _event$touches$ = event.touches[0],
          clientX = _event$touches$.clientX,
          clientY = _event$touches$.clientY;
      var target = document.elementFromPoint(clientX, clientY);

      if (target) {
        var index = target.dataset.index;
        /* istanbul ignore else */

        if (touchActiveIndex.current !== index) {
          touchActiveIndex.current = index;
          scrollToElement(target);
        }
      }
    }
  };

  (0, _useEventListener.default)('scroll', onScroll, {
    target: scrollParent,
    depends: [scrollParent]
  });
  (0, _useEventListener.default)('touchmove', onTouchMove, {
    target: sidebar.current,
    depends: [touch.deltaY]
  });
  (0, _react.useEffect)(function () {
    if (props.onChange && typeof props.onChange === 'function') {
      props.onChange(activeAnchor);
    }
  }, [activeAnchor]);
  (0, _hooks.useMount)(init);

  var handleMapChildren = function handleMapChildren($children) {
    return _react.default.Children.toArray($children).filter(Boolean).map(function (child) {
      var _child$type, _child$props;

      if (((_child$type = child.type) == null ? void 0 : _child$type[_constant.COMPONENT_TYPE_KEY]) === _IndexAnchor.INDEX_ANCHORE_KEY) {
        return /*#__PURE__*/_react.default.cloneElement(child, {
          ref: setRefs(child.props.index)
        });
      }

      if ((_child$props = child.props) != null && _child$props.children) {
        var deepMap = handleMapChildren(child.props.children);
        return deepMap.length ? deepMap : child;
      }

      return child;
    });
  };

  (0, _react.useImperativeHandle)(ref, function () {
    return {
      scrollTo: scrollTo
    };
  });
  var memoChildren = (0, _react.useMemo)(function () {
    return handleMapChildren(children);
  }, [children]);
  return /*#__PURE__*/_react.default.createElement(_IndexBarContext.default.Provider, {
    value: {
      zIndex: zIndex,
      highlightColor: highlightColor,
      sticky: sticky
    }
  }, /*#__PURE__*/_react.default.createElement("div", {
    ref: root,
    className: (0, _clsx.default)(bem(), props.className),
    style: props.style
  }, ssrCompatRender(function () {
    return (0, _renderToContainer.renderToContainer)(props.teleport, /*#__PURE__*/_react.default.createElement("div", {
      ref: sidebar,
      className: (0, _clsx.default)(bem('sidebar')),
      style: sidebarStyle,
      onClick: onClickSidebar,
      onTouchStart: onTouchStart
    }, renderIndexes()));
  }), memoChildren));
});

function genAlphabet() {
  var indexList = [];
  var charCodeOfA = 'A'.charCodeAt(0);

  for (var i = 0; i < 26; i += 1) {
    indexList.push(String.fromCharCode(charCodeOfA + i));
  }

  return indexList;
}

IndexBar.defaultProps = {
  sticky: true,
  stickyOffsetTop: 0,
  indexList: genAlphabet()
};
var _default = IndexBar;
exports.default = _default;