/**
 * ldesign v0.2.14
 * (c) 2022/11/2 16:16 built by swimly
 * @license MIT
 */

import debounce from 'lodash/debounce';
import { ChevronLeftIcon, ChevronRightIcon, AddIcon } from '@ldesign/icons-vue';
import { emitEvent } from '../../utils/event.js';
import { firstUpperCase } from '../../utils/helper.js';
import { renderLNodeJSX } from '../../utils/render-node.js';
import { getClassPrefixMixins, getGlobalIconMixins } from '../config-provider/config-receiver.js';
import mixins from '../../utils/mixins.js';
import _TabPanel from './tab-panel.js';
import LTabNavItem from './tab-nav-item.js';
import { TabsProps } from './props.js';
import 'lodash/camelCase';
import 'vue';
import 'lodash';
import 'lodash/mergeWith';
import '../config-provider/context.js';
import '../../_chunks/dep-def4c2ce.js';
import '../../hooks/use-destroy-onclose.js';
import '../../utils/ripple.js';
import '../../_chunks/dep-cf772670.js';
import '../../config.js';

const classPrefixMixins = getClassPrefixMixins("tab__nav");
const getDomWidth = dom => (dom === null || dom === void 0 ? void 0 : dom.offsetWidth) || 0;
const getActiveTabEl = (navs, value) => {
  for (let i = 0; i < navs.length; i++) {
    var _navs$i$componentInst;
    if (navs[i].componentOptions.propsData.value === value) return (_navs$i$componentInst = navs[i].componentInstance) === null || _navs$i$componentInst === void 0 ? void 0 : _navs$i$componentInst.$el;
  }
  return null;
};
const getLeftCoverWidth = o => {
  const leftOperationsZoneWidth = getDomWidth(o.leftZone);
  const leftIconWidth = getDomWidth(o.leftIcon);
  if (o.totalWidthBeforeActiveTab === 0) {
    return leftOperationsZoneWidth - leftIconWidth;
  }
  return leftOperationsZoneWidth;
};
const getRightCoverWidth = o => {
  const rightOperationsZoneWidth = getDomWidth(o.rightZone);
  const rightIconWidth = getDomWidth(o.rightIcon);
  const wrapWidth = getDomWidth(o.wrap);
  if (Math.abs(o.totalWidthBeforeActiveTab + o.activeTabWidth - wrapWidth) < 1) {
    return rightOperationsZoneWidth - rightIconWidth;
  }
  return rightOperationsZoneWidth;
};
var LTabNav = mixins(classPrefixMixins, getGlobalIconMixins()).extend({
  name: "LTabNav",
  components: {
    LTabNavItem,
    LTabPanel: _TabPanel
  },
  props: {
    theme: TabsProps.theme,
    panels: {
      type: Array,
      default: () => []
    },
    value: TabsProps.value,
    placement: TabsProps.placement,
    size: TabsProps.size,
    disabled: TabsProps.disabled,
    addable: TabsProps.addable
  },
  data() {
    return {
      scrollLeft: 0,
      canToLeft: false,
      canToRight: false,
      navBarStyle: {}
    };
  },
  computed: {
    navs() {
      const h = this.$createElement;
      return this.panels.map((panel, index) => h("l-tab-nav-item", {
        "ref": `tabItem${index}`,
        "key": panel.value,
        "attrs": {
          "index": index,
          "theme": this.theme,
          "size": this.size,
          "placement": this.placement,
          "label": renderLNodeJSX(panel, "label", `\u9009\u9879\u5361${index + 1}`),
          "active": panel.value === this.value,
          "disabled": this.disabled || panel.disabled,
          "removable": panel.removable,
          "value": panel.value
        },
        "on": {
          "click": e => this.tabClick(e, panel),
          "remove": this.removeBtnClick
        }
      }));
    },
    wrapTransformStyle() {
      if (["left", "right"].includes(this.placement.toLowerCase())) return {};
      return {
        transform: `translate(${-this.scrollLeft}px, 0)`
      };
    },
    dataCanUpdateNavBarStyle() {
      return [this.scrollLeft, this.placement, this.theme, this.navs, this.value];
    },
    dataCanUpdateArrow() {
      return [this.scrollLeft, this.placement, this.navs];
    },
    iconBaseClass() {
      return {
        [`${this.classPrefix}-tabs__btn`]: true,
        [this.commonSizeClassName.medium]: this.size === "medium",
        [this.commonSizeClassName.large]: this.size === "large"
      };
    },
    leftIconClass() {
      return {
        [`${this.classPrefix}-tabs__btn--left`]: true,
        ...this.iconBaseClass
      };
    },
    rightIconClass() {
      return {
        [`${this.classPrefix}-tabs__btn--right`]: true,
        ...this.iconBaseClass
      };
    },
    addIconClass() {
      return {
        [`${this.classPrefix}-tabs__add-btn`]: true,
        ...this.iconBaseClass
      };
    },
    navContainerClass() {
      return {
        [`${this.classPrefix}-tabs__nav-container`]: true,
        [`${this.classPrefix}-tabs__nav--card`]: this.theme === "card",
        [`${this.classPrefix}-is-${this.placement}`]: true,
        [`${this.classPrefix}-is-addable`]: this.theme === "card" && this.addable
      };
    },
    navScrollContainerClass() {
      return {
        [`${this.classPrefix}-tabs__nav-scroll`]: true,
        [`${this.classPrefix}-is-scrollable`]: this.canToLeft || this.canToRight
      };
    },
    navsWrapClass() {
      return [`${this.classPrefix}-tabs__nav-wrap`, `${this.classPrefix}-is-smooth`, {
        [`${this.classPrefix}-is-vertical`]: this.placement === "left" || this.placement === "right"
      }];
    },
    navBarClass() {
      return [`${this.classPrefix}-tabs__bar`, `${this.classPrefix}-is-${this.placement}`];
    },
    navsContainerStyle() {
      return this.addable ? {
        "min-height": "48px"
      } : null;
    }
  },
  watch: {
    dataCanUpdateArrow() {
      this.$nextTick(() => {
        this.calculateCanShowArrow();
      });
    },
    dataCanUpdateNavBarStyle() {
      this.$nextTick(() => {
        this.calculateNavBarStyle();
      });
    },
    value() {
      this.$nextTick(() => {
        this.moveActiveTabIntoView();
      });
    },
    navs() {
      this.$nextTick(() => {
        this.fixScrollLeft();
      });
    }
  },
  methods: {
    calculateCanShowArrow() {
      this.calculateCanToLeft();
      this.calculateCanToRight();
    },
    calculateCanToLeft() {
      if (["left", "right"].includes(this.placement.toLowerCase())) this.canToLeft = false;
      const container = this.$refs.navsContainer;
      const wrap = this.$refs.navsWrap;
      if (!wrap || !container) this.canToLeft = false;
      const leftOperationsZoneWidth = getDomWidth(this.$refs.leftOperationsZone);
      const leftIconWidth = getDomWidth(this.$refs.leftIcon);
      this.canToLeft = this.scrollLeft + Math.round(leftOperationsZoneWidth - leftIconWidth) > 0;
    },
    calculateCanToRight() {
      if (["left", "right"].includes(this.placement.toLowerCase())) this.canToRight = false;
      const container = this.$refs.navsContainer;
      const wrap = this.$refs.navsWrap;
      if (!wrap || !container) this.canToRight = false;
      const rightOperationsZoneWidth = getDomWidth(this.$refs.rightOperationsZone);
      const rightIconWidth = getDomWidth(this.$refs.rightIcon);
      this.canToRight = this.scrollLeft + getDomWidth(container) - (rightOperationsZoneWidth - rightIconWidth) - getDomWidth(wrap) < -1;
    },
    calculateNavBarStyle() {
      const getNavBarStyle = () => {
        var _this$navs$i$componen4, _this$navs$i$componen5;
        if (this.theme === "card") return {};
        const getPropName = () => {
          if (["left", "right"].includes(this.placement.toLowerCase())) return ["height", "top"];
          return ["width", "left"];
        };
        let offset = 0;
        const [sizePropName, offsetPropName] = getPropName();
        let i = 0;
        for (; i < this.navs.length; i++) {
          var _this$navs$i$componen, _this$navs$i$componen2, _this$navs$i$componen3;
          if (((_this$navs$i$componen = this.navs[i].componentInstance) === null || _this$navs$i$componen === void 0 ? void 0 : _this$navs$i$componen.value) === this.value) break;
          offset += ((_this$navs$i$componen2 = this.navs[i].componentInstance) === null || _this$navs$i$componen2 === void 0 ? void 0 : (_this$navs$i$componen3 = _this$navs$i$componen2.$el) === null || _this$navs$i$componen3 === void 0 ? void 0 : _this$navs$i$componen3[`client${firstUpperCase(sizePropName)}`]) || 0;
        }
        if (!this.navs[i]) return {};
        return {
          [offsetPropName]: `${offset}px`,
          [sizePropName]: `${((_this$navs$i$componen4 = this.navs[i].componentInstance) === null || _this$navs$i$componen4 === void 0 ? void 0 : (_this$navs$i$componen5 = _this$navs$i$componen4.$el) === null || _this$navs$i$componen5 === void 0 ? void 0 : _this$navs$i$componen5[`client${firstUpperCase(sizePropName)}`]) || 0}px`
        };
      };
      this.navBarStyle = getNavBarStyle();
    },
    watchDomChange() {
      const onResize = debounce(() => {
        this.resetScrollPosition();
      }, 300);
      window.addEventListener("resize", onResize);
      this.$once("beforeDestroy", () => {
        window.removeEventListener("resize", onResize);
      });
      if (!this.$refs.navsContainer) return;
      if (!window.ResizeObserver) return;
      const resizeObserver = new window.ResizeObserver(onResize);
      resizeObserver.observe(this.$refs.navsContainer);
      this.$once("beforeDestroy", () => {
        resizeObserver.disconnect();
      });
    },
    resetScrollPosition() {
      this.fixScrollLeft();
      this.calculateCanShowArrow();
    },
    handleScrollToLeft() {
      const container = this.$refs.navsContainer;
      if (!container) return;
      const leftOperationsZoneWidth = getDomWidth(this.$refs.leftOperationsZone);
      const leftIconWidth = getDomWidth(this.$refs.leftIcon);
      const containerWidth = getDomWidth(container);
      this.scrollLeft = Math.max(-(leftOperationsZoneWidth - leftIconWidth), this.scrollLeft - containerWidth);
    },
    handleScrollToRight() {
      const container = this.$refs.navsContainer;
      const wrap = this.$refs.navsWrap;
      const rightOperationsZoneWidth = getDomWidth(this.$refs.rightOperationsZone);
      const rightIconWidth = getDomWidth(this.$refs.rightIcon);
      const containerWidth = getDomWidth(container);
      const wrapWidth = getDomWidth(wrap);
      this.scrollLeft = Math.min(this.scrollLeft + containerWidth, wrapWidth - containerWidth + rightOperationsZoneWidth - rightIconWidth);
    },
    shouldMoveToLeftSide(activeTabEl) {
      const totalWidthBeforeActiveTab = activeTabEl.offsetLeft;
      const container = this.$refs.navsContainer;
      if (!container) return;
      const leftCoverWidth = getLeftCoverWidth({
        leftZone: this.$refs.leftOperationsZone,
        leftIcon: this.$refs.leftIcon,
        totalWidthBeforeActiveTab
      });
      const isCurrentTabHiddenInLeftZone = () => this.scrollLeft + leftCoverWidth > totalWidthBeforeActiveTab;
      if (isCurrentTabHiddenInLeftZone()) {
        this.scrollLeft = totalWidthBeforeActiveTab - leftCoverWidth;
        return true;
      }
      return false;
    },
    shouldMoveToRightSide(activeTabEl) {
      const totalWidthBeforeActiveTab = activeTabEl.offsetLeft;
      const activeTabWidth = activeTabEl.offsetWidth;
      const container = this.$refs.navsContainer;
      const wrap = this.$refs.navsWrap;
      if (!container || !wrap) return;
      const containerWidth = getDomWidth(container);
      const rightCoverWidth = getRightCoverWidth({
        rightZone: this.$refs.rightOperationsZone,
        rightIcon: this.$refs.rightIcon,
        wrap,
        totalWidthBeforeActiveTab,
        activeTabWidth
      });
      const isCurrentTabHiddenInRightZone = () => this.scrollLeft + containerWidth - rightCoverWidth < totalWidthBeforeActiveTab + activeTabWidth;
      if (isCurrentTabHiddenInRightZone()) {
        this.scrollLeft = totalWidthBeforeActiveTab + activeTabWidth - containerWidth + rightCoverWidth;
        return true;
      }
      return false;
    },
    moveActiveTabIntoView() {
      let {
        needCheckUpdate
      } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
        needCheckUpdate: true
      };
      if (["left", "right"].includes(this.placement)) return false;
      const activeTabEl = getActiveTabEl(this.navs, this.value);
      if (!activeTabEl) {
        if (needCheckUpdate) {
          this.$once("hook:updated", () => {
            this.moveActiveTabIntoView({
              needCheckUpdate: false
            });
          });
        }
        return false;
      }
      return this.shouldMoveToLeftSide(activeTabEl) || this.shouldMoveToRightSide(activeTabEl);
    },
    fixIfLastItemNotTouchRightSide(containerWidth, wrapWidth) {
      const rightOperationsZoneWidth = getDomWidth(this.$refs.rightOperationsZone);
      if (this.scrollLeft + containerWidth - rightOperationsZoneWidth > wrapWidth) {
        this.scrollLeft = wrapWidth + rightOperationsZoneWidth - containerWidth;
        return true;
      }
      return false;
    },
    fixIfItemTotalWidthIsLessThenContainerWidth(containerWidth, wrapWidth) {
      if (wrapWidth <= containerWidth) {
        this.scrollLeft = 0;
        return true;
      }
      return false;
    },
    fixScrollLeft() {
      if (["left", "right"].includes(this.placement.toLowerCase())) return;
      const container = this.$refs.navsContainer;
      const wrap = this.$refs.navsWrap;
      if (!wrap || !container) return false;
      const containerWidth = getDomWidth(container);
      const wrapWidth = getDomWidth(wrap);
      return this.fixIfItemTotalWidthIsLessThenContainerWidth(containerWidth, wrapWidth) || this.fixIfLastItemNotTouchRightSide(containerWidth, wrapWidth);
    },
    handleAddTab(e) {
      emitEvent(this, "add", {
        e
      });
    },
    tabClick(event, nav) {
      const {
        value,
        disabled
      } = nav;
      if (disabled || this.value === value) return false;
      emitEvent(this, "change", value);
    },
    removeBtnClick(_ref) {
      let {
        e,
        value,
        index
      } = _ref;
      emitEvent(this, "remove", {
        e,
        value,
        index
      });
    },
    renderArrows() {
      const h = this.$createElement;
      const {
        ChevronLeftIcon: ChevronLeftIcon$1,
        ChevronRightIcon: ChevronRightIcon$1,
        AddIcon: AddIcon$1
      } = this.useGlobalIcon({
        ChevronLeftIcon: ChevronLeftIcon,
        ChevronRightIcon: ChevronRightIcon,
        AddIcon: AddIcon
      });
      return [h("div", {
        "ref": "leftOperationsZone",
        "class": [`${this.classPrefix}-tabs__operations`, `${this.classPrefix}-tabs__operations--left`]
      }, [h("transition", {
        "attrs": {
          "name": "fade",
          "mode": "out-in",
          "appear": true
        }
      }, [this.canToLeft ? h("div", {
        "ref": "leftIcon",
        "class": this.leftIconClass,
        "on": {
          "click": this.handleScrollToLeft
        }
      }, [h(ChevronLeftIcon$1)]) : null])]), h("div", {
        "ref": "rightOperationsZone",
        "class": [`${this.classPrefix}-tabs__operations`, `${this.classPrefix}-tabs__operations--right`]
      }, [h("transition", {
        "attrs": {
          "name": "fade",
          "mode": "out-in",
          "appear": true
        }
      }, [this.canToRight ? h("div", {
        "ref": "rightIcon",
        "class": this.rightIconClass,
        "on": {
          "click": this.handleScrollToRight
        }
      }, [h(ChevronRightIcon$1)]) : null]), this.addable ? h("div", {
        "class": this.addIconClass,
        "on": {
          "click": this.handleAddTab
        }
      }, [h(AddIcon$1)]) : null])];
    },
    renderNavs() {
      const h = this.$createElement;
      return h("div", {
        "class": this.navContainerClass
      }, [h("div", {
        "class": this.navScrollContainerClass
      }, [h("div", {
        "ref": "navsWrap",
        "class": this.navsWrapClass,
        "style": this.wrapTransformStyle
      }, [this.renderNavBar(), this.navs])])]);
    },
    renderNavBar() {
      const h = this.$createElement;
      if (this.theme === "card") return null;
      return h("div", {
        "class": this.navBarClass,
        "style": this.navBarStyle
      });
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.watchDomChange();
      this.calculateNavBarStyle();
      this.calculateCanShowArrow();
    });
  },
  render() {
    const h = arguments[0];
    return h("div", {
      "ref": "navsContainer",
      "class": [`${this.classPrefix}-tabs__nav`],
      "style": this.navsContainerStyle
    }, [this.renderArrows(), this.renderNavs()]);
  }
});

export { LTabNav as default };
//# sourceMappingURL=tab-nav.js.map
