yantd
Version:
React component library
228 lines (227 loc) • 9.79 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import * as React from 'react';
import classNames from 'classnames';
import addEventListener from 'rc-util/lib/Dom/addEventListener';
import { ConfigContext } from '../config-provider';
import scrollTo from '../_util/scrollTo';
import getScroll from '../_util/getScroll';
import AnchorContext 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+)$/;
var Anchor = /** @class */ (function (_super) {
__extends(Anchor, _super);
function Anchor() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = {
activeLink: null,
};
_this.wrapperRef = React.createRef();
_this.links = [];
// Context
_this.registerLink = function (link) {
if (!_this.links.includes(link)) {
_this.links.push(link);
}
};
_this.unregisterLink = function (link) {
var index = _this.links.indexOf(link);
if (index !== -1) {
_this.links.splice(index, 1);
}
};
_this.getContainer = function () {
var getTargetContainer = _this.context.getTargetContainer;
var getContainer = _this.props.getContainer;
var getFunc = getContainer || getTargetContainer || getDefaultContainer;
return getFunc();
};
_this.handleScrollTo = function (link) {
var _a = _this.props, offsetTop = _a.offsetTop, targetOffset = _a.targetOffset;
_this.setCurrentActiveLink(link);
var container = _this.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 () {
_this.animating = false;
},
getContainer: _this.getContainer,
});
};
_this.saveInkNode = function (node) {
_this.inkNode = node;
};
_this.setCurrentActiveLink = function (link) {
var activeLink = _this.state.activeLink;
var onChange = _this.props.onChange;
if (activeLink !== link) {
_this.setState({
activeLink: link,
});
onChange === null || onChange === void 0 ? void 0 : onChange(link);
}
};
_this.handleScroll = function () {
if (_this.animating) {
return;
}
var _a = _this.props, offsetTop = _a.offsetTop, bounds = _a.bounds, targetOffset = _a.targetOffset;
var currentActiveLink = _this.getCurrentAnchor(targetOffset !== undefined ? targetOffset : offsetTop || 0, bounds);
_this.setCurrentActiveLink(currentActiveLink);
};
_this.updateInk = function () {
var _a = _this, prefixCls = _a.prefixCls, wrapperRef = _a.wrapperRef;
var anchorNode = wrapperRef.current;
var linkNode = anchorNode === null || anchorNode === void 0 ? void 0 : anchorNode.getElementsByClassName(prefixCls + "-link-title-active")[0];
if (linkNode) {
_this.inkNode.style.top = linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5 + "px";
}
};
_this.render = function () {
var _a;
var _b = _this.context, getPrefixCls = _b.getPrefixCls, direction = _b.direction;
var _c = _this.props, customizePrefixCls = _c.prefixCls, _d = _c.className, className = _d === void 0 ? '' : _d, style = _c.style, offsetTop = _c.offsetTop, affix = _c.affix, showInkInFixed = _c.showInkInFixed, children = _c.children;
var activeLink = _this.state.activeLink;
var prefixCls = getPrefixCls('anchor', customizePrefixCls);
// To support old version react.
// Have to add prefixCls on the instance.
// https://github.com/facebook/react/issues/12397
_this.prefixCls = prefixCls;
var inkClass = classNames(prefixCls + "-ink-ball", {
visible: activeLink,
});
var wrapperClass = classNames(prefixCls + "-wrapper", (_a = {},
_a[prefixCls + "-rtl"] = direction === 'rtl',
_a), className);
var anchorClass = classNames(prefixCls, {
fixed: !affix && !showInkInFixed,
});
var wrapperStyle = __assign({ maxHeight: offsetTop ? "calc(100vh - " + offsetTop + "px)" : '100vh' }, style);
var anchorContent = (React.createElement("div", { ref: _this.wrapperRef, className: wrapperClass, style: wrapperStyle },
React.createElement("div", { className: anchorClass },
React.createElement("div", { className: prefixCls + "-ink" },
React.createElement("span", { className: inkClass, ref: _this.saveInkNode })),
children)));
return (React.createElement(AnchorContext.Provider, { value: {
registerLink: _this.registerLink,
unregisterLink: _this.unregisterLink,
activeLink: _this.state.activeLink,
scrollTo: _this.handleScrollTo,
onClick: _this.props.onClick,
} }, anchorContent));
};
return _this;
}
Anchor.prototype.componentDidMount = function () {
this.scrollContainer = this.getContainer();
this.scrollEvent = addEventListener(this.scrollContainer, 'scroll', this.handleScroll);
this.handleScroll();
};
Anchor.prototype.componentDidUpdate = function () {
if (this.scrollEvent) {
var currentContainer = this.getContainer();
if (this.scrollContainer !== currentContainer) {
this.scrollContainer = currentContainer;
this.scrollEvent.remove();
this.scrollEvent = addEventListener(this.scrollContainer, 'scroll', this.handleScroll);
this.handleScroll();
}
}
this.updateInk();
};
Anchor.prototype.componentWillUnmount = function () {
if (this.scrollEvent) {
this.scrollEvent.remove();
}
};
Anchor.prototype.getCurrentAnchor = function (offsetTop, bounds) {
if (offsetTop === void 0) { offsetTop = 0; }
if (bounds === void 0) { bounds = 5; }
var getCurrentAnchor = this.props.getCurrentAnchor;
if (typeof getCurrentAnchor === 'function') {
return getCurrentAnchor();
}
var linkSections = [];
var container = this.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_1 = getOffsetTop(target, container);
if (top_1 < offsetTop + bounds) {
linkSections.push({
link: link,
top: top_1,
});
}
}
});
if (linkSections.length) {
var maxSection = linkSections.reduce(function (prev, curr) { return (curr.top > prev.top ? curr : prev); });
return maxSection.link;
}
return '';
};
Anchor.defaultProps = {
affix: true,
showInkInFixed: false,
};
Anchor.contextType = ConfigContext;
return Anchor;
}(React.Component));
export default Anchor;