ant-design-vue
Version:
An enterprise-class UI design language and Vue-based implementation
307 lines (261 loc) • 9.89 kB
JavaScript
import { createVNode as _createVNode } from "vue";
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import { defineComponent, inject, nextTick, provide } from 'vue';
import PropTypes from '../_util/vue-types';
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 { findDOMNode } from '../_util/props-util';
import BaseMixin from '../_util/BaseMixin';
import { defaultConfigProvider } from '../config-provider';
function getDefaultContainer() {
return window;
}
function getOffsetTop(element, container) {
if (!element) {
return 0;
}
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 = /#([^#]+)$/;
var AnchorProps = {
prefixCls: PropTypes.string,
offsetTop: PropTypes.number,
bounds: PropTypes.number,
affix: PropTypes.looseBool.def(true),
showInkInFixed: PropTypes.looseBool.def(false),
getContainer: PropTypes.func.def(getDefaultContainer),
wrapperClass: PropTypes.string,
wrapperStyle: PropTypes.style,
getCurrentAnchor: PropTypes.func,
targetOffset: PropTypes.number,
onChange: PropTypes.func,
onClick: PropTypes.func
};
export default defineComponent({
name: 'AAnchor',
mixins: [BaseMixin],
inheritAttrs: false,
props: AnchorProps,
emits: ['change', 'click'],
setup: function setup() {
return {
configProvider: inject('configProvider', defaultConfigProvider)
};
},
data: function data() {
// this.links = [];
// this.sPrefixCls = '';
return {
activeLink: null,
links: [],
sPrefixCls: '',
scrollContainer: null,
scrollEvent: null,
animating: false
};
},
created: function created() {
var _this = this;
provide('antAnchor', {
registerLink: function registerLink(link) {
if (!_this.links.includes(link)) {
_this.links.push(link);
}
},
unregisterLink: function unregisterLink(link) {
var index = _this.links.indexOf(link);
if (index !== -1) {
_this.links.splice(index, 1);
}
},
$data: this.$data,
scrollTo: this.handleScrollTo
});
provide('antAnchorContext', this);
},
mounted: function mounted() {
var _this2 = this;
nextTick(function () {
var getContainer = _this2.getContainer;
_this2.scrollContainer = getContainer();
_this2.scrollEvent = addEventListener(_this2.scrollContainer, 'scroll', _this2.handleScroll);
_this2.handleScroll();
});
},
updated: function updated() {
var _this3 = this;
nextTick(function () {
if (_this3.scrollEvent) {
var getContainer = _this3.getContainer;
var currentContainer = getContainer();
if (_this3.scrollContainer !== currentContainer) {
_this3.scrollContainer = currentContainer;
_this3.scrollEvent.remove();
_this3.scrollEvent = addEventListener(_this3.scrollContainer, 'scroll', _this3.handleScroll);
_this3.handleScroll();
}
}
_this3.updateInk();
});
},
beforeUnmount: function beforeUnmount() {
if (this.scrollEvent) {
this.scrollEvent.remove();
}
},
methods: {
getCurrentActiveLink: function getCurrentActiveLink() {
var offsetTop = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var bounds = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5;
var getCurrentAnchor = this.getCurrentAnchor;
if (typeof getCurrentAnchor === 'function') {
return getCurrentAnchor();
}
var activeLink = '';
if (typeof document === 'undefined') {
return activeLink;
}
var linkSections = [];
var getContainer = this.getContainer;
var container = getContainer();
this.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 '';
},
handleScrollTo: function handleScrollTo(link) {
var _this4 = this;
var offsetTop = this.offsetTop,
getContainer = this.getContainer,
targetOffset = this.targetOffset;
this.setCurrentActiveLink(link);
var container = getContainer();
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;
this.animating = true;
scrollTo(y, {
callback: function callback() {
_this4.animating = false;
},
getContainer: getContainer
});
},
setCurrentActiveLink: function setCurrentActiveLink(link) {
var activeLink = this.activeLink;
if (activeLink !== link) {
this.setState({
activeLink: link
});
this.$emit('change', link);
}
},
handleScroll: function handleScroll() {
if (this.animating) {
return;
}
var offsetTop = this.offsetTop,
bounds = this.bounds,
targetOffset = this.targetOffset;
var currentActiveLink = this.getCurrentActiveLink(targetOffset !== undefined ? targetOffset : offsetTop || 0, bounds);
this.setCurrentActiveLink(currentActiveLink);
},
updateInk: function updateInk() {
if (typeof document === 'undefined') {
return;
}
var sPrefixCls = this.sPrefixCls;
var linkNode = findDOMNode(this).getElementsByClassName("".concat(sPrefixCls, "-link-title-active"))[0];
if (linkNode) {
this.$refs.inkNode.style.top = "".concat(linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5, "px");
}
}
},
render: function render() {
var _a;
var customizePrefixCls = this.prefixCls,
offsetTop = this.offsetTop,
affix = this.affix,
showInkInFixed = this.showInkInFixed,
activeLink = this.activeLink,
$slots = this.$slots,
getContainer = this.getContainer;
var getPrefixCls = this.configProvider.getPrefixCls;
var prefixCls = getPrefixCls('anchor', customizePrefixCls);
this.sPrefixCls = prefixCls;
var inkClass = classNames("".concat(prefixCls, "-ink-ball"), {
visible: activeLink
});
var wrapperClass = classNames(this.wrapperClass, "".concat(prefixCls, "-wrapper"));
var anchorClass = classNames(prefixCls, {
fixed: !affix && !showInkInFixed
});
var wrapperStyle = _extends({
maxHeight: offsetTop ? "calc(100vh - ".concat(offsetTop, "px)") : '100vh'
}, this.wrapperStyle);
var anchorContent = _createVNode("div", {
"class": wrapperClass,
"style": wrapperStyle
}, [_createVNode("div", {
"class": anchorClass
}, [_createVNode("div", {
"class": "".concat(prefixCls, "-ink")
}, [_createVNode("span", {
"class": inkClass,
"ref": "inkNode"
}, null)]), (_a = $slots.default) === null || _a === void 0 ? void 0 : _a.call($slots)])]);
return !affix ? anchorContent : _createVNode(Affix, _objectSpread(_objectSpread({}, this.$attrs), {}, {
"offsetTop": offsetTop,
"target": getContainer
}), {
default: function _default() {
return [anchorContent];
}
});
}
});