import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import { createVNode as _createVNode } from "vue"; import { defineComponent, nextTick, onBeforeUnmount, onMounted, onUpdated, reactive, ref, computed } from 'vue'; import classNames from '../_util/classNames'; import addEventListener from '../vc-util/Dom/addEventListener'; import Affix from '../affix'; import scrollTo from '../_util/scrollTo'; import getScroll from '../_util/getScroll'; import useConfigInject from '../_util/hooks/useConfigInject'; import useProvideAnchor from './context'; function getDefaultContainer() { return window; } function getOffsetTop(element, container) { if (!element.getClientRects().length) { return 0; } var rect = element.getBoundingClientRect(); if (rect.width || rect.height) { if (container === window) { container = element.ownerDocument.documentElement; return rect.top - container.clientTop; } return rect.top - container.getBoundingClientRect().top; } return rect.top; } var sharpMatcherRegx = /#([\S ]+)$/; export var anchorProps = function anchorProps() { return { prefixCls: String, offsetTop: Number, bounds: Number, affix: { type: Boolean, default: true }, showInkInFixed: { type: Boolean, default: false }, getContainer: Function, wrapperClass: String, wrapperStyle: { type: Object, default: undefined }, getCurrentAnchor: Function, targetOffset: Number, onChange: Function, onClick: Function }; }; export default defineComponent({ compatConfig: { MODE: 3 }, name: 'AAnchor', inheritAttrs: false, props: anchorProps(), setup: function setup(props, _ref) { var emit = _ref.emit, attrs = _ref.attrs, slots = _ref.slots, expose = _ref.expose; var _useConfigInject = useConfigInject('anchor', props), prefixCls = _useConfigInject.prefixCls, getTargetContainer = _useConfigInject.getTargetContainer, direction = _useConfigInject.direction; var inkNodeRef = ref(); var anchorRef = ref(); var state = reactive({ links: [], scrollContainer: null, scrollEvent: null, animating: false }); var activeLink = ref(null); var getContainer = computed(function () { var getContainer = props.getContainer; return getContainer || getTargetContainer.value || getDefaultContainer; }); // func... var getCurrentAnchor = function getCurrentAnchor() { var offsetTop = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var bounds = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5; var linkSections = []; var container = getContainer.value(); state.links.forEach(function (link) { var sharpLinkMatch = sharpMatcherRegx.exec(link.toString()); if (!sharpLinkMatch) { return; } var target = document.getElementById(sharpLinkMatch[1]); if (target) { var top = getOffsetTop(target, container); if (top < offsetTop + bounds) { linkSections.push({ link: link, top: top }); } } }); if (linkSections.length) { var maxSection = linkSections.reduce(function (prev, curr) { return curr.top > prev.top ? curr : prev; }); return maxSection.link; } return ''; }; var setCurrentActiveLink = function setCurrentActiveLink(link) { var getCurrentAnchor = props.getCurrentAnchor; if (activeLink.value === link) { return; } activeLink.value = typeof getCurrentAnchor === 'function' ? getCurrentAnchor() : link; emit('change', link); }; var handleScrollTo = function handleScrollTo(link) { var offsetTop = props.offsetTop, targetOffset = props.targetOffset; setCurrentActiveLink(link); var container = getContainer.value(); var scrollTop = getScroll(container, true); var sharpLinkMatch = sharpMatcherRegx.exec(link); if (!sharpLinkMatch) { return; } var targetElement = document.getElementById(sharpLinkMatch[1]); if (!targetElement) { return; } var eleOffsetTop = getOffsetTop(targetElement, container); var y = scrollTop + eleOffsetTop; y -= targetOffset !== undefined ? targetOffset : offsetTop || 0; state.animating = true; scrollTo(y, { callback: function callback() { state.animating = false; }, getContainer: getContainer.value }); }; expose({ scrollTo: handleScrollTo }); var handleScroll = function handleScroll() { if (state.animating) { return; } var offsetTop = props.offsetTop, bounds = props.bounds, targetOffset = props.targetOffset; var currentActiveLink = getCurrentAnchor(targetOffset !== undefined ? targetOffset : offsetTop || 0, bounds); setCurrentActiveLink(currentActiveLink); }; var updateInk = function updateInk() { var linkNode = anchorRef.value.getElementsByClassName("".concat(prefixCls.value, "-link-title-active"))[0]; if (linkNode) { inkNodeRef.value.style.top = "".concat(linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5, "px"); } }; useProvideAnchor({ registerLink: function registerLink(link) { if (!state.links.includes(link)) { state.links.push(link); } }, unregisterLink: function unregisterLink(link) { var index = state.links.indexOf(link); if (index !== -1) { state.links.splice(index, 1); } }, activeLink: activeLink, scrollTo: handleScrollTo, handleClick: function handleClick(e, info) { emit('click', e, info); } }); onMounted(function () { nextTick(function () { var container = getContainer.value(); state.scrollContainer = container; state.scrollEvent = addEventListener(state.scrollContainer, 'scroll', handleScroll); handleScroll(); }); }); onBeforeUnmount(function () { if (state.scrollEvent) { state.scrollEvent.remove(); } }); onUpdated(function () { if (state.scrollEvent) { var currentContainer = getContainer.value(); if (state.scrollContainer !== currentContainer) { state.scrollContainer = currentContainer; state.scrollEvent.remove(); state.scrollEvent = addEventListener(state.scrollContainer, 'scroll', handleScroll); handleScroll(); } } updateInk(); }); return function () { var _slots$default; var offsetTop = props.offsetTop, affix = props.affix, showInkInFixed = props.showInkInFixed; var pre = prefixCls.value; var inkClass = classNames("".concat(pre, "-ink-ball"), { visible: activeLink.value }); var wrapperClass = classNames(props.wrapperClass, "".concat(pre, "-wrapper"), _defineProperty({}, "".concat(pre, "-rtl"), direction.value === 'rtl')); var anchorClass = classNames(pre, _defineProperty({}, "".concat(pre, "-fixed"), !affix && !showInkInFixed)); var wrapperStyle = _objectSpread({ maxHeight: offsetTop ? "calc(100vh - ".concat(offsetTop, "px)") : '100vh' }, props.wrapperStyle); var anchorContent = _createVNode("div", { "class": wrapperClass, "style": wrapperStyle, "ref": anchorRef }, [_createVNode("div", { "class": anchorClass }, [_createVNode("div", { "class": "".concat(pre, "-ink") }, [_createVNode("span", { "class": inkClass, "ref": inkNodeRef }, null)]), (_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)])]); return !affix ? anchorContent : _createVNode(Affix, _objectSpread(_objectSpread({}, attrs), {}, { "offsetTop": offsetTop, "target": getContainer.value }), { default: function _default() { return [anchorContent]; } }); }; } });