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

'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var Vue = require('vue');
var utils_dom = require('../../utils/dom.js');
var utils_renderNode = require('../../utils/render-node.js');
var components_configProvider_configReceiver = require('../config-provider/config-receiver.js');
var utils_mixins = require('../../utils/mixins.js');
var components_affix_index = require('../affix/index.js');
var components_anchor_utils = require('./utils.js');
var components_anchor_props = require('./props.js');
require('raf');
require('lodash/isString');
require('../../chunks/log.js');
require('../../chunks/_commonjsHelpers-2e6815bd.js');
require('../../utils/easing.js');
require('lodash');
require('lodash/mergeWith');
require('../config-provider/context.js');
require('../../chunks/zh_CN.js');
require('../../utils/with-install.js');
require('../../config.js');
require('../affix/affix.js');
require('lodash/isFunction');
require('../affix/props.js');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var Vue__default = /*#__PURE__*/_interopDefaultLegacy(Vue);

const classPrefixMixins = components_configProvider_configReceiver.getClassPrefixMixins("anchor");
var _Anchor = utils_mixins["default"](Vue__default["default"], classPrefixMixins).extend({
  name: "LAnchor",
  components: {
    LAffix: components_affix_index.Affix
  },
  props: {
    ...components_anchor_props.AnchorProps
  },
  provide() {
    return {
      tAnchor: this
    };
  },
  data() {
    return {
      links: [],
      active: "",
      activeLineStyle: false
    };
  },
  watch: {
    attach() {
      if (this.scrollContainer) utils_dom.off(this.scrollContainer, "scroll", this.handleScroll);
      this.getScrollContainer();
    },
    size: {
      async handler() {
        await Vue__default["default"].nextTick();
        this.updateActiveLine();
      },
      immediate: true
    }
  },
  methods: {
    getScrollContainer() {
      const {
        container
      } = this;
      this.scrollContainer = utils_dom.getScrollContainer(container);
      utils_dom.on(this.scrollContainer, "scroll", this.handleScroll);
      this.handleScroll();
    },
    getAnchorTarget(link) {
      const matcher = link.match(components_anchor_utils.ANCHOR_SHARP_REGEXP);
      if (!matcher) return;
      const anchor = document.getElementById(matcher[1]);
      if (!anchor) return;
      return anchor;
    },
    registerLink(link) {
      const {
        links
      } = this;
      if (!components_anchor_utils.ANCHOR_SHARP_REGEXP.test(link) || links.includes(link)) return;
      links.push(link);
    },
    unregisterLink(link) {
      this.links = this.links.filter(each => each !== link);
    },
    async setCurrentActiveLink(link) {
      const {
        active
      } = this;
      if (active === link) return;
      this.active = link;
      this.emitChange(link, active);
      await Vue__default["default"].nextTick();
      this.updateActiveLine();
    },
    updateActiveLine() {
      const ele = this.$el.querySelector(`.${this.commonStatusClassName.active}>a`);
      if (!ele) {
        this.activeLineStyle = false;
        return;
      }
      const {
        offsetTop: top,
        offsetHeight: height
      } = ele;
      this.activeLineStyle = {
        top: `${top}px`,
        height: `${height}px`,
        opacity: 1
      };
    },
    emitChange(currentLink, prevLink) {
      this.$emit("change", currentLink, prevLink);
      if (this.onChange) this.onChange(currentLink, prevLink);
    },
    handleLinkClick(link) {
      this.$emit("click", link);
      if (this.onClick) this.onClick(link);
    },
    async handleScrollTo(link) {
      const anchor = this.getAnchorTarget(link);
      this.setCurrentActiveLink(link);
      if (!anchor) return;
      this.handleScrollLock = true;
      const {
        scrollContainer,
        targetOffset
      } = this;
      const scrollTop = utils_dom.getScroll(scrollContainer);
      const offsetTop = components_anchor_utils.getOffsetTop(anchor, scrollContainer);
      const top = scrollTop + offsetTop - targetOffset;
      await utils_dom.scrollTo(top, {
        container: scrollContainer
      });
      this.handleScrollLock = false;
    },
    handleScroll() {
      if (this.handleScrollLock) return;
      const {
        links,
        bounds,
        targetOffset
      } = this;
      const filters = [];
      let active = "";
      links.forEach(link => {
        const anchor = this.getAnchorTarget(link);
        if (!anchor) return;
        const top = components_anchor_utils.getOffsetTop(anchor, this.scrollContainer);
        if (top < bounds + targetOffset) {
          filters.push({
            link,
            top
          });
        }
      });
      if (filters.length) {
        const latest = filters.reduce((prev, cur) => prev.top > cur.top ? prev : cur);
        active = latest.link;
      }
      this.setCurrentActiveLink(active);
    },
    renderCursor() {
      const h = this.$createElement;
      const titleContent = utils_renderNode.renderLNodeJSX(this, "cursor");
      return titleContent || h("div", {
        "class": `${this.componentName}__line-cursor`
      });
    }
  },
  async mounted() {
    const {
      active
    } = this;
    this.getScrollContainer();
    if (active) {
      await Vue__default["default"].nextTick();
      this.handleScrollTo(active);
    }
  },
  destroyed() {
    if (!this.scrollContainer) return;
    utils_dom.off(this.scrollContainer, "scroll", this.handleScroll);
  },
  render() {
    const h = arguments[0];
    const {
      $scopedSlots: {
        default: children
      },
      size,
      affixProps,
      activeLineStyle
    } = this;
    const className = [this.componentName, this.commonSizeClassName[size]];
    const content = h("div", {
      "class": className
    }, [h("div", {
      "class": `${this.componentName}__line`
    }, [h("div", {
      "class": `${this.componentName}__line-cursor-wrapper`,
      "style": activeLineStyle
    }, [this.renderCursor()])]), children && children(null)]);
    if (affixProps) return h("l-affix", {
      "props": {
        ...affixProps
      }
    }, [content]);
    return content;
  }
});

exports["default"] = _Anchor;
//# sourceMappingURL=anchor.js.map
