choerodon-ui
Version:
An enterprise-class UI design language and React-based implementation
320 lines (270 loc) • 9.36 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _objectSpread from "@babel/runtime/helpers/objectSpread2";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
import _inherits from "@babel/runtime/helpers/inherits";
import _createSuper from "@babel/runtime/helpers/createSuper";
import React, { Component } from 'react';
import { findDOMNode } from 'react-dom';
import classNames from 'classnames';
import addEventListener from '../_util/addEventListener';
import Affix from '../affix';
import scrollTo from '../_util/scrollTo';
import getScroll from '../_util/getScroll';
import ConfigContext from '../config-provider/ConfigContext';
import { AnchorContextProvider } from './AnchorContext';
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 && element.ownerDocument) {
container = element.ownerDocument.documentElement;
return rect.top - container.clientTop;
}
return rect.top - container.getBoundingClientRect().top;
}
return rect.top;
}
var sharpMatcherRegx = /#([^#]+)$/;
var Anchor = /*#__PURE__*/function (_Component) {
_inherits(Anchor, _Component);
var _super = _createSuper(Anchor);
function Anchor() {
var _this;
_classCallCheck(this, Anchor);
_this = _super.apply(this, arguments);
_this.state = {
activeLink: null
};
_this.links = [];
_this.handleScrollTo = function (link) {
var _this$props = _this.props,
offsetTop = _this$props.offsetTop,
getContainer = _this$props.getContainer,
targetOffset = _this$props.targetOffset;
_this.setState({
activeLink: 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() {
_this.animating = false;
},
getContainer: getContainer
});
};
_this.saveInkNode = function (node) {
_this.inkNode = node;
};
_this.handleScroll = function () {
if (_this.animating) {
return;
}
var activeLink = _this.state.activeLink;
var _this$props2 = _this.props,
offsetTop = _this$props2.offsetTop,
bounds = _this$props2.bounds,
targetOffset = _this$props2.targetOffset;
var currentActiveLink = _this.getCurrentAnchor(targetOffset !== undefined ? targetOffset : offsetTop || 0, bounds);
if (activeLink !== currentActiveLink) {
_this.setState({
activeLink: currentActiveLink
});
}
};
_this.updateInk = function () {
if (typeof document === 'undefined') {
return;
}
var prefixCls = _this.getPrefixCls();
var linkNode = findDOMNode(_assertThisInitialized(_this)).getElementsByClassName("".concat(prefixCls, "-link-title-active"))[0];
if (linkNode && linkNode.offsetParent) {
_this.inkNode.style.top = "".concat(linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5, "px");
}
};
return _this;
}
_createClass(Anchor, [{
key: "getContextValue",
value: function getContextValue() {
var _this2 = this;
var onClick = this.props.onClick;
var activeLink = this.state.activeLink;
var c7nAnchor = {
registerLink: function registerLink(link) {
if (!_this2.links.includes(link)) {
_this2.links.push(link);
}
},
unregisterLink: function unregisterLink(link) {
var index = _this2.links.indexOf(link);
if (index !== -1) {
_this2.links.splice(index, 1);
}
},
activeLink: activeLink,
scrollTo: this.handleScrollTo,
onClick: onClick
};
return {
c7nAnchor: c7nAnchor
};
}
}, {
key: "componentDidMount",
value: function componentDidMount() {
var getContainer = this.props.getContainer;
this.scrollContainer = getContainer();
this.scrollEvent = addEventListener(this.scrollContainer, 'scroll', this.handleScroll);
this.handleScroll();
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate() {
if (this.scrollEvent) {
var getContainer = this.props.getContainer;
var currentContainer = getContainer();
if (this.scrollContainer !== currentContainer) {
this.scrollContainer = currentContainer;
this.scrollEvent.remove();
this.scrollEvent = addEventListener(this.scrollContainer, 'scroll', this.handleScroll);
this.handleScroll();
}
}
this.updateInk();
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
if (this.scrollEvent) {
this.scrollEvent.remove();
}
}
}, {
key: "getCurrentAnchor",
value: 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 getCurrentAnchor = this.props.getCurrentAnchor;
if (typeof getCurrentAnchor === 'function') {
return getCurrentAnchor();
}
var activeLink = '';
if (typeof document === 'undefined') {
return activeLink;
}
var linkSections = [];
var getContainer = this.props.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 '';
}
}, {
key: "getPrefixCls",
value: function getPrefixCls() {
var prefixCls = this.props.prefixCls;
var getPrefixCls = this.context.getPrefixCls;
return getPrefixCls('anchor', prefixCls);
}
}, {
key: "render",
value: function render() {
var _this$props3 = this.props,
_this$props3$classNam = _this$props3.className,
className = _this$props3$classNam === void 0 ? '' : _this$props3$classNam,
style = _this$props3.style,
offsetTop = _this$props3.offsetTop,
affix = _this$props3.affix,
showInkInFixed = _this$props3.showInkInFixed,
children = _this$props3.children,
getContainer = _this$props3.getContainer;
var activeLink = this.state.activeLink;
var getPrefixCls = this.context.getPrefixCls;
var prefixCls = this.getPrefixCls();
var inkClass = classNames("".concat(prefixCls, "-ink-ball"), {
visible: activeLink
});
var wrapperClass = classNames(className, "".concat(prefixCls, "-wrapper"));
var anchorClass = classNames(prefixCls, {
fixed: !affix && !showInkInFixed
});
var wrapperStyle = _objectSpread({
maxHeight: offsetTop ? "calc(100vh - ".concat(offsetTop, "px)") : '100vh'
}, style);
var anchorContent = /*#__PURE__*/React.createElement("div", {
className: wrapperClass,
style: wrapperStyle
}, /*#__PURE__*/React.createElement("div", {
className: anchorClass
}, /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls, "-ink")
}, /*#__PURE__*/React.createElement("span", {
className: inkClass,
ref: this.saveInkNode
})), /*#__PURE__*/React.createElement(AnchorContextProvider, _extends({}, this.getContextValue(), {
getPrefixCls: getPrefixCls
}), children)));
return !affix ? anchorContent : /*#__PURE__*/React.createElement(Affix, {
offsetTop: offsetTop,
target: getContainer
}, anchorContent);
}
}], [{
key: "contextType",
get: function get() {
return ConfigContext;
}
}]);
return Anchor;
}(Component);
export { Anchor as default };
Anchor.displayName = 'Anchor';
Anchor.defaultProps = {
affix: true,
showInkInFixed: false,
getContainer: getDefaultContainer
};
//# sourceMappingURL=Anchor.js.map