"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Tabs = exports.Tab = void 0;
var _web = require("@react-spring/web");
var _ahooks = require("ahooks");
var _classnames = _interopRequireDefault(require("classnames"));
var _react = _interopRequireWildcard(require("react"));
var _bound = require("../../utils/bound");
var _nativeProps = require("../../utils/native-props");
var _shouldRender = require("../../utils/should-render");
var _traverseReactNode = require("../../utils/traverse-react-node");
var _useIsomorphicUpdateLayoutEffect = require("../../utils/use-isomorphic-update-layout-effect");
var _useMutationEffect = require("../../utils/use-mutation-effect");
var _usePropsValue = require("../../utils/use-props-value");
var _useResizeEffect = require("../../utils/use-resize-effect");
var _withDefaultProps = require("../../utils/with-default-props");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const classPrefix = `adm-tabs`;
const Tab = () => {
  return null;
};
exports.Tab = Tab;
const defaultProps = {
  activeLineMode: 'auto',
  stretch: true,
  direction: 'ltr'
};
const Tabs = p => {
  var _a;
  const props = (0, _withDefaultProps.mergeProps)(defaultProps, p);
  const tabListContainerRef = (0, _react.useRef)(null);
  const activeLineRef = (0, _react.useRef)(null);
  const tabRefs = (0, _react.useRef)({});
  const keyToIndexRecord = {};
  let firstActiveKey = null;
  const panes = [];
  const isRTL = props.direction === 'rtl';
  (0, _traverseReactNode.traverseReactNode)(props.children, (child, index) => {
    if (!(0, _react.isValidElement)(child)) return;
    const key = child.key;
    if (typeof key !== 'string') return;
    if (index === 0) {
      firstActiveKey = key;
    }
    const length = panes.push(child);
    keyToIndexRecord[key] = length - 1;
  });
  const [activeKey, setActiveKey] = (0, _usePropsValue.usePropsValue)({
    value: props.activeKey,
    defaultValue: (_a = props.defaultActiveKey) !== null && _a !== void 0 ? _a : firstActiveKey,
    onChange: v => {
      var _a;
      if (v === null) return;
      (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, v);
    }
  });
  /** Save the keyboard click to make sure focus only trigger when by keyboard */
  const manuallyActiveRef = (0, _react.useRef)(null);
  const [{
    x,
    width
  }, inkApi] = (0, _web.useSpring)(() => ({
    x: 0,
    width: 0,
    config: {
      tension: 300,
      clamp: true
    }
  }));
  const [{
    scrollLeft
  }, scrollApi] = (0, _web.useSpring)(() => ({
    scrollLeft: 0,
    config: {
      tension: 300,
      clamp: true
    }
  }));
  const [{
    leftMaskOpacity,
    rightMaskOpacity
  }, maskApi] = (0, _web.useSpring)(() => ({
    leftMaskOpacity: 0,
    rightMaskOpacity: 0,
    config: {
      clamp: true
    }
  }));
  function animate(immediate = false, fromMutation = false) {
    const container = tabListContainerRef.current;
    if (!container) return;
    const activeIndex = keyToIndexRecord[activeKey];
    if (activeIndex === undefined) {
      inkApi.start({
        x: 0,
        width: 0,
        immediate: true
      });
      return;
    }
    const activeLine = activeLineRef.current;
    if (!activeLine) return;
    const activeTabWrapper = container.children.item(activeIndex + 1);
    const activeTab = activeTabWrapper.children.item(0);
    const activeTabLeft = activeTab.offsetLeft;
    const activeTabWidth = activeTab.offsetWidth;
    const activeTabWrapperLeft = activeTabWrapper.offsetLeft;
    const activeTabWrapperWidth = activeTabWrapper.offsetWidth;
    const containerWidth = container.offsetWidth;
    const containerScrollWidth = container.scrollWidth;
    const containerScrollLeft = container.scrollLeft;
    const activeLineWidth = activeLine.offsetWidth;
    let x = 0;
    let width = 0;
    if (props.activeLineMode === 'auto') {
      x = activeTabLeft;
      width = activeTabWidth;
    } else if (props.activeLineMode === 'full') {
      x = activeTabWrapperLeft;
      width = activeTabWrapperWidth;
    } else {
      x = activeTabLeft + (activeTabWidth - activeLineWidth) / 2;
    }
    if (isRTL) {
      /**
       * In RTL mode, x equals the container width minus the x-coordinate of the current tab minus the width of the current tab.
       * https://github.com/Fog3211/reproduce-codesandbox/blob/f0a3396a114cc00e88a51a67d3be60a746519b30/assets/images/antd_mobile_tabs_rtl_x.jpg?raw=true
       */
      const w = ['auto', 'full'].includes(props.activeLineMode) ? width : activeLineWidth;
      x = -(containerWidth - x - w);
    }
    inkApi.start({
      x,
      width,
      immediate
    });
    const maxScrollDistance = containerScrollWidth - containerWidth;
    if (maxScrollDistance <= 0) return;
    let nextScrollLeft = 0;
    if (isRTL) {
      /**
       * 位移距离等于：activeTab的中心坐标距离容器中心坐标的距离，然后RTL取负数
       * containerWidth / 2 - (activeTabLeft + (activeTabWidth - activeLineWidth) / 2) - activeLineWidth / 2,
       */
      nextScrollLeft = -(0, _bound.bound)(containerWidth / 2 - activeTabLeft + activeTabWidth / 2 - activeLineWidth, 0, maxScrollDistance);
    } else {
      nextScrollLeft = (0, _bound.bound)(activeTabLeft - (containerWidth - activeTabWidth) / 2, 0, maxScrollDistance);
    }
    if (!fromMutation || props.autoScroll !== false) {
      scrollApi.start({
        scrollLeft: nextScrollLeft,
        from: {
          scrollLeft: containerScrollLeft
        },
        immediate
      });
    }
  }
  (0, _ahooks.useIsomorphicLayoutEffect)(() => {
    animate(!x.isAnimating);
  }, []);
  (0, _useIsomorphicUpdateLayoutEffect.useIsomorphicUpdateLayoutEffect)(() => {
    animate();
  }, [activeKey, isRTL, props.activeLineMode]);
  (0, _useResizeEffect.useResizeEffect)(() => {
    animate(!x.isAnimating);
  }, tabListContainerRef);
  (0, _useMutationEffect.useMutationEffect)(() => {
    animate(!x.isAnimating, true);
  }, tabListContainerRef, {
    subtree: true,
    childList: true,
    characterData: true
  });
  const {
    run: updateMask
  } = (0, _ahooks.useThrottleFn)(immediate => {
    const container = tabListContainerRef.current;
    if (!container) return;
    const scrollLeft = container.scrollLeft;
    let showLeftMask = false;
    let showRightMask = false;
    if (isRTL) {
      /**
       * RTL模式下，只要滑动过，scrollLeft就再也回不到0（chrome是0.5）
       * 所以要加round才能终止触发条件
       * round(443.5) + 375 < 819
       */
      showLeftMask = Math.round(-scrollLeft) + container.offsetWidth < container.scrollWidth;
      showRightMask = scrollLeft < 0;
    } else {
      showLeftMask = scrollLeft > 0;
      showRightMask = scrollLeft + container.offsetWidth < container.scrollWidth;
    }
    maskApi.start({
      leftMaskOpacity: showLeftMask ? 1 : 0,
      rightMaskOpacity: showRightMask ? 1 : 0,
      immediate
    });
  }, {
    wait: 100,
    trailing: true,
    leading: true
  });
  (0, _ahooks.useIsomorphicLayoutEffect)(() => {
    updateMask(true);
  }, []);
  const handleKeyDown = e => {
    const keys = Object.keys(keyToIndexRecord);
    const currentIndex = keyToIndexRecord[activeKey];
    const isNext = isRTL ? e.key === 'ArrowLeft' : e.key === 'ArrowRight';
    const isPrev = isRTL ? e.key === 'ArrowRight' : e.key === 'ArrowLeft';
    const offsetDirection = isNext ? 1 : -1;
    const findNextEnabledTab = (startIndex, direction) => {
      const length = keys.length;
      for (let i = 0; i < length; i++) {
        const index = (startIndex + direction * (i + 1) + length) % length;
        const key = keys[index];
        const pane = panes.find(p => p.key === key);
        if (!(pane === null || pane === void 0 ? void 0 : pane.props.disabled)) return key;
      }
      return keys[startIndex];
    };
    const currentKey = findNextEnabledTab(currentIndex, offsetDirection);
    if (isNext || isPrev) {
      e.preventDefault();
      manuallyActiveRef.current = currentKey;
      setActiveKey(currentKey);
    }
  };
  (0, _react.useEffect)(() => {
    var _a;
    if (activeKey && tabRefs.current[activeKey] && manuallyActiveRef.current === activeKey) {
      (_a = tabRefs.current[activeKey]) === null || _a === void 0 ? void 0 : _a.focus();
      manuallyActiveRef.current = null;
    }
  }, [activeKey]);
  return (0, _nativeProps.withNativeProps)(props, _react.default.createElement("div", {
    className: classPrefix,
    style: {
      direction: props.direction
    }
  }, _react.default.createElement("div", {
    className: `${classPrefix}-header`
  }, _react.default.createElement(_web.animated.div, {
    className: (0, _classnames.default)(`${classPrefix}-header-mask`, `${classPrefix}-header-mask-left`),
    style: {
      opacity: leftMaskOpacity
    }
  }), _react.default.createElement(_web.animated.div, {
    className: (0, _classnames.default)(`${classPrefix}-header-mask`, `${classPrefix}-header-mask-right`),
    style: {
      opacity: rightMaskOpacity
    }
  }), _react.default.createElement(_web.animated.div, {
    className: `${classPrefix}-tab-list`,
    ref: tabListContainerRef,
    scrollLeft: scrollLeft,
    onScroll: updateMask,
    onKeyDown: handleKeyDown,
    role: 'tablist'
  }, _react.default.createElement(_web.animated.div, {
    ref: activeLineRef,
    className: `${classPrefix}-tab-line`,
    style: {
      width: props.activeLineMode === 'fixed' ? 'var(--fixed-active-line-width, 30px)' : width,
      x
    }
  }), panes.map(pane => (0, _nativeProps.withNativeProps)(pane.props, _react.default.createElement("div", {
    key: pane.key,
    className: (0, _classnames.default)(`${classPrefix}-tab-wrapper`, {
      [`${classPrefix}-tab-wrapper-stretch`]: props.stretch
    })
  }, _react.default.createElement("div", {
    role: 'tab',
    "aria-selected": pane.key === activeKey,
    tabIndex: pane.key === activeKey ? 0 : -1,
    ref: el => tabRefs.current[pane.key] = el,
    onClick: () => {
      const {
        key
      } = pane;
      if (pane.props.disabled) return;
      if (key === undefined || key === null) {
        return;
      }
      setActiveKey(key.toString());
    },
    className: (0, _classnames.default)(`${classPrefix}-tab`, {
      [`${classPrefix}-tab-active`]: pane.key === activeKey,
      [`${classPrefix}-tab-disabled`]: pane.props.disabled
    })
  }, pane.props.title)))))), panes.map(pane => {
    if (pane.props.children === undefined) {
      return null;
    }
    const active = pane.key === activeKey;
    return _react.default.createElement(_shouldRender.ShouldRender, {
      key: pane.key,
      active: active,
      forceRender: pane.props.forceRender,
      destroyOnClose: pane.props.destroyOnClose
    }, _react.default.createElement("div", {
      className: `${classPrefix}-content`,
      style: {
        display: active ? 'block' : 'none'
      }
    }, pane.props.children));
  })));
};
exports.Tabs = Tabs;