"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const Vue = require("vue");
const utils = require("./utils.js");
const index_esm = require("../../../@vant/use/dist/index.esm.js");
const useId = require("../composables/use-id.js");
const useRoute = require("../composables/use-route.js");
const useRefs = require("../composables/use-refs.js");
const useExpose = require("../composables/use-expose.js");
const onPopupReopen = require("../composables/on-popup-reopen.js");
const useVisibilityChange = require("../composables/use-visibility-change.js");
const index = require("../sticky/index.js");
const TabsContent = require("./TabsContent.js");
const constant = require("../utils/constant.js");
const dom = require("../utils/dom.js");
const props = require("../utils/props.js");
const create = require("../utils/create.js");
const format = require("../utils/format.js");
const basic = require("../utils/basic.js");
const interceptor = require("../utils/interceptor.js");
const [name, bem] = create.createNamespace("tabs");
const tabsProps = {
  type: props.makeStringProp("line"),
  color: String,
  border: Boolean,
  sticky: Boolean,
  shrink: Boolean,
  active: props.makeNumericProp(0),
  duration: props.makeNumericProp(0.3),
  animated: Boolean,
  ellipsis: props.truthProp,
  swipeable: Boolean,
  scrollspy: Boolean,
  offsetTop: props.makeNumericProp(0),
  background: String,
  lazyRender: props.truthProp,
  showHeader: props.truthProp,
  lineWidth: props.numericProp,
  lineHeight: props.numericProp,
  beforeChange: Function,
  swipeThreshold: props.makeNumericProp(5),
  titleActiveColor: String,
  titleInactiveColor: String
};
const TABS_KEY = Symbol(name);
var stdin_default = Vue.defineComponent({
  name,
  props: tabsProps,
  emits: ["change", "scroll", "rendered", "clickTab", "update:active"],
  setup(props2, {
    emit,
    slots
  }) {
    let tabHeight;
    let lockScroll;
    let stickyFixed;
    let cancelScrollLeftToRaf;
    let cancelScrollTopToRaf;
    const root = Vue.ref();
    const navRef = Vue.ref();
    const wrapRef = Vue.ref();
    const contentRef = Vue.ref();
    const id = useId.useId();
    const scroller = index_esm.useScrollParent(root);
    const [titleRefs, setTitleRefs] = useRefs.useRefs();
    const {
      children,
      linkChildren
    } = index_esm.useChildren(TABS_KEY);
    const state = Vue.reactive({
      inited: false,
      position: "",
      lineStyle: {},
      currentIndex: -1
    });
    const scrollable = Vue.computed(() => children.length > +props2.swipeThreshold || !props2.ellipsis || props2.shrink);
    const navStyle = Vue.computed(() => ({
      borderColor: props2.color,
      background: props2.background
    }));
    const getTabName = (tab, index2) => {
      var _a;
      return (_a = tab.name) != null ? _a : index2;
    };
    const currentName = Vue.computed(() => {
      const activeTab = children[state.currentIndex];
      if (activeTab) {
        return getTabName(activeTab, state.currentIndex);
      }
    });
    const offsetTopPx = Vue.computed(() => format.unitToPx(props2.offsetTop));
    const scrollOffset = Vue.computed(() => {
      if (props2.sticky) {
        return offsetTopPx.value + tabHeight;
      }
      return 0;
    });
    const scrollIntoView = (immediate) => {
      const nav = navRef.value;
      const titles = titleRefs.value;
      if (!scrollable.value || !nav || !titles || !titles[state.currentIndex]) {
        return;
      }
      const title = titles[state.currentIndex].$el;
      const to = title.offsetLeft - (nav.offsetWidth - title.offsetWidth) / 2;
      if (cancelScrollLeftToRaf) cancelScrollLeftToRaf();
      cancelScrollLeftToRaf = utils.scrollLeftTo(nav, to, immediate ? 0 : +props2.duration);
    };
    const setLine = () => {
      const shouldAnimate = state.inited;
      Vue.nextTick(() => {
        const titles = titleRefs.value;
        if (!titles || !titles[state.currentIndex] || props2.type !== "line" || dom.isHidden(root.value)) {
          return;
        }
        const title = titles[state.currentIndex].$el;
        const {
          lineWidth,
          lineHeight
        } = props2;
        const left = title.offsetLeft + title.offsetWidth / 2;
        const lineStyle = {
          width: format.addUnit(lineWidth),
          backgroundColor: props2.color,
          transform: `translateX(${left}px) translateX(-50%)`
        };
        if (shouldAnimate) {
          lineStyle.transitionDuration = `${props2.duration}s`;
        }
        if (basic.isDef(lineHeight)) {
          const height = format.addUnit(lineHeight);
          lineStyle.height = height;
          lineStyle.borderRadius = height;
        }
        state.lineStyle = lineStyle;
      });
    };
    const findAvailableTab = (index2) => {
      const diff = index2 < state.currentIndex ? -1 : 1;
      while (index2 >= 0 && index2 < children.length) {
        if (!children[index2].disabled) {
          return index2;
        }
        index2 += diff;
      }
    };
    const setCurrentIndex = (currentIndex, skipScrollIntoView) => {
      const newIndex = findAvailableTab(currentIndex);
      if (!basic.isDef(newIndex)) {
        return;
      }
      const newTab = children[newIndex];
      const newName = getTabName(newTab, newIndex);
      const shouldEmitChange = state.currentIndex !== null;
      if (state.currentIndex !== newIndex) {
        state.currentIndex = newIndex;
        if (!skipScrollIntoView) {
          scrollIntoView();
        }
        setLine();
      }
      if (newName !== props2.active) {
        emit("update:active", newName);
        if (shouldEmitChange) {
          emit("change", newName, newTab.title);
        }
      }
      if (stickyFixed && !props2.scrollspy) {
        dom.setRootScrollTop(Math.ceil(dom.getElementTop(root.value) - offsetTopPx.value));
      }
    };
    const setCurrentIndexByName = (name2, skipScrollIntoView) => {
      const index2 = children.findIndex((tab, index22) => getTabName(tab, index22) === name2);
      setCurrentIndex(index2 === -1 ? 0 : index2, skipScrollIntoView);
    };
    const scrollToCurrentContent = (immediate = false) => {
      if (props2.scrollspy) {
        const target = children[state.currentIndex].$el;
        if (target && scroller.value) {
          const to = dom.getElementTop(target, scroller.value) - scrollOffset.value;
          lockScroll = true;
          if (cancelScrollTopToRaf) cancelScrollTopToRaf();
          cancelScrollTopToRaf = utils.scrollTopTo(scroller.value, to, immediate ? 0 : +props2.duration, () => {
            lockScroll = false;
          });
        }
      }
    };
    const onClickTab = (item, index2, event) => {
      const {
        title,
        disabled
      } = children[index2];
      const name2 = getTabName(children[index2], index2);
      if (!disabled) {
        interceptor.callInterceptor(props2.beforeChange, {
          args: [name2],
          done: () => {
            setCurrentIndex(index2);
            scrollToCurrentContent();
          }
        });
        useRoute.route(item);
      }
      emit("clickTab", {
        name: name2,
        title,
        event,
        disabled
      });
    };
    const onStickyScroll = (params) => {
      stickyFixed = params.isFixed;
      emit("scroll", params);
    };
    const scrollTo = (name2) => {
      Vue.nextTick(() => {
        setCurrentIndexByName(name2);
        scrollToCurrentContent(true);
      });
    };
    const getCurrentIndexOnScroll = () => {
      for (let index2 = 0; index2 < children.length; index2++) {
        const {
          top
        } = index_esm.useRect(children[index2].$el);
        if (top > scrollOffset.value) {
          return index2 === 0 ? 0 : index2 - 1;
        }
      }
      return children.length - 1;
    };
    const onScroll = () => {
      if (props2.scrollspy && !lockScroll) {
        const index2 = getCurrentIndexOnScroll();
        setCurrentIndex(index2);
      }
    };
    const renderLine = () => {
      if (props2.type === "line" && children.length) {
        return Vue.createVNode("div", {
          "class": bem("line"),
          "style": state.lineStyle
        }, null);
      }
    };
    const renderHeader = () => {
      var _a, _b, _c;
      const {
        type,
        border,
        sticky
      } = props2;
      const Header = [Vue.createVNode("div", {
        "ref": sticky ? void 0 : wrapRef,
        "class": [bem("wrap"), {
          [constant.BORDER_TOP_BOTTOM]: type === "line" && border
        }]
      }, [Vue.createVNode("div", {
        "ref": navRef,
        "role": "tablist",
        "class": bem("nav", [type, {
          shrink: props2.shrink,
          complete: scrollable.value
        }]),
        "style": navStyle.value,
        "aria-orientation": "horizontal"
      }, [(_a = slots["nav-left"]) == null ? void 0 : _a.call(slots), children.map((item) => item.renderTitle(onClickTab)), renderLine(), (_b = slots["nav-right"]) == null ? void 0 : _b.call(slots)])]), (_c = slots["nav-bottom"]) == null ? void 0 : _c.call(slots)];
      if (sticky) {
        return Vue.createVNode("div", {
          "ref": wrapRef
        }, [Header]);
      }
      return Header;
    };
    const resize = () => {
      setLine();
      Vue.nextTick(() => {
        var _a, _b;
        scrollIntoView(true);
        (_b = (_a = contentRef.value) == null ? void 0 : _a.swipeRef.value) == null ? void 0 : _b.resize();
      });
    };
    Vue.watch(() => [props2.color, props2.duration, props2.lineWidth, props2.lineHeight], setLine);
    Vue.watch(dom.windowWidth, resize);
    Vue.watch(() => props2.active, (value) => {
      if (value !== currentName.value) {
        setCurrentIndexByName(value);
      }
    });
    Vue.watch(() => children.length, () => {
      if (state.inited) {
        setCurrentIndexByName(props2.active);
        setLine();
        Vue.nextTick(() => {
          scrollIntoView(true);
        });
      }
    });
    const init = () => {
      setCurrentIndexByName(props2.active, true);
      Vue.nextTick(() => {
        state.inited = true;
        if (wrapRef.value) {
          tabHeight = index_esm.useRect(wrapRef.value).height;
        }
        scrollIntoView(true);
      });
    };
    const onRendered = (name2, title) => emit("rendered", name2, title);
    useExpose.useExpose({
      resize,
      scrollTo
    });
    Vue.onActivated(setLine);
    onPopupReopen.onPopupReopen(setLine);
    index_esm.onMountedOrActivated(init);
    useVisibilityChange.useVisibilityChange(root, setLine);
    index_esm.useEventListener("scroll", onScroll, {
      target: scroller,
      passive: true
    });
    linkChildren({
      id,
      props: props2,
      setLine,
      scrollable,
      onRendered,
      currentName,
      setTitleRefs,
      scrollIntoView
    });
    return () => Vue.createVNode("div", {
      "ref": root,
      "class": bem([props2.type])
    }, [props2.showHeader ? props2.sticky ? Vue.createVNode(index.Sticky, {
      "container": root.value,
      "offsetTop": offsetTopPx.value,
      "onScroll": onStickyScroll
    }, {
      default: () => [renderHeader()]
    }) : renderHeader() : null, Vue.createVNode(TabsContent.default, {
      "ref": contentRef,
      "count": children.length,
      "inited": state.inited,
      "animated": props2.animated,
      "duration": props2.duration,
      "swipeable": props2.swipeable,
      "lazyRender": props2.lazyRender,
      "currentIndex": state.currentIndex,
      "onChange": setCurrentIndex
    }, {
      default: () => {
        var _a;
        return [(_a = slots.default) == null ? void 0 : _a.call(slots)];
      }
    })]);
  }
});
exports.TABS_KEY = TABS_KEY;
exports.default = stdin_default;
exports.tabsProps = tabsProps;
