UNPKG

@fpxfd/next

Version:

A configurable component library for web built on React.

394 lines (330 loc) 15.2 kB
'use strict'; exports.__esModule = true; var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _class, _temp2; var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _reactLifecyclesCompat = require('react-lifecycles-compat'); var _affix = require('../affix'); var _affix2 = _interopRequireDefault(_affix); var _configProvider = require('../config-provider'); var _configProvider2 = _interopRequireDefault(_configProvider); var _util = require('../util'); var _anchorLink = require('./anchor-link'); var _anchorLink2 = _interopRequireDefault(_anchorLink); var _context = require('./context'); var _context2 = _interopRequireDefault(_context); var _getScroll = require('./getScroll'); var _getScroll2 = _interopRequireDefault(_getScroll); var _scrollTo = require('./scrollTo'); var _scrollTo2 = _interopRequireDefault(_scrollTo); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 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 scrollTimeout = void 0; /** * Anchor */ var Anchor = (_temp2 = _class = function (_Component) { (0, _inherits3.default)(Anchor, _Component); function Anchor() { var _temp, _this, _ret; (0, _classCallCheck3.default)(this, Anchor); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, _Component.call.apply(_Component, [this].concat(args))), _this), _this.state = { activeLink: null, isOpen: _this.props.open }, _this.wrapperRef = _react2.default.createRef(), _this.links = [], _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 getContainer = _this.props.getContainer; var getFunc = getContainer || getDefaultContainer; return getFunc(); }, _this.handleScrollTo = function (link) { var _this$props = _this.props, offsetTop = _this$props.offsetTop, targetOffset = _this$props.targetOffset; _this.setCurrentActiveLink(link); var container = _this.getContainer(); var scrollTop = (0, _getScroll2.default)(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; (0, _scrollTo2.default)(y, { callback: function callback() { _this.animating = false; }, getContainer: _this.getContainer }); }, _this.setCurrentActiveLink = function (link) { var activeLink = _this.state.activeLink; var _this$props2 = _this.props, onChange = _this$props2.onChange, getCurrentAnchor = _this$props2.getCurrentAnchor; if (activeLink === link) { return; } _this.setState({ isOpen: !_this.props.allowFold, activeLink: typeof getCurrentAnchor === 'function' ? getCurrentAnchor(link) : link }); onChange && onChange(link); }, _this.handleScroll = function () { if (_this.animating) { return; } var _this$props3 = _this.props, offsetTop = _this$props3.offsetTop, bounds = _this$props3.bounds, targetOffset = _this$props3.targetOffset, allowFold = _this$props3.allowFold; var currentActiveLink = _this.getCurrentAnchor(targetOffset !== undefined ? targetOffset : offsetTop || 0, bounds); _this.setCurrentActiveLink(currentActiveLink); if (allowFold) { clearTimeout(scrollTimeout); scrollTimeout = setTimeout(function () { // 滚动停止后,展开anchor _this.setState({ isOpen: true }); clearTimeout(scrollTimeout); }, 300); } }, _this.handlerOpen = function () { _this.setState({ isOpen: !_this.state.isOpen }); }, _this.getMemoizedContextValue = function (link, onClickFn) { return { registerLink: _this.registerLink, unregisterLink: _this.unregisterLink, scrollTo: _this.handleScrollTo, activeLink: link, onClick: onClickFn }; }, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret); } // scroll scope's container Anchor.prototype.componentDidMount = function componentDidMount() { this.scrollContainer = this.getContainer(); _util.events.on(this.scrollContainer, 'scroll', this.handleScroll); if (this.links) { this.setState({ activeLink: this.links[0] }); } }; Anchor.prototype.componentDidUpdate = function componentDidUpdate() { _util.events.off(this.scrollContainer, 'scroll', this.handleScroll); _util.events.on(this.scrollContainer, 'scroll', this.handleScroll); }; Anchor.prototype.componentWillUnmount = function componentWillUnmount() { _util.events.off(this.scrollContainer, 'scroll', this.handleScroll); }; Anchor.prototype.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 = 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 = 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 ''; }; Anchor.prototype.render = function render() { var _classNames, _classNames2, _this2 = this; var direction = this.context.direction; var _props = this.props, prefix = _props.prefix, _props$className = _props.className, className = _props$className === undefined ? '' : _props$className, style = _props.style, offsetTop = _props.offsetTop, affix = _props.affix, dataSource = _props.dataSource, allowFold = _props.allowFold, onClick = _props.onClick; var _state = this.state, activeLink = _state.activeLink, isOpen = _state.isOpen; var wrapperClass = (0, _classnames2.default)((allowFold ? prefix + '-wrapper ' + prefix + '-wrapper-allowFold' : prefix + '-wrapper') + ' ', (_classNames = {}, _classNames[prefix + '-rtl'] = direction === 'rtl', _classNames), className); var anchorClass = (0, _classnames2.default)(prefix, (_classNames2 = {}, _classNames2[prefix + '-fixed'] = !affix, _classNames2)); var wrapperStyle = (0, _extends3.default)({ maxHeight: offsetTop ? 'calc(100vh - ' + offsetTop + 'px)' : '100vh' }, style); var anchorContent = _react2.default.createElement( 'div', { ref: this.wrapperRef, className: wrapperClass, style: wrapperStyle }, _react2.default.createElement( 'div', { className: '' + (allowFold ? anchorClass + ' ' + anchorClass + '-allowFold' : anchorClass) }, dataSource && dataSource.map(function (item, index) { var props = { href: item.href, title: item.title, allowFold: allowFold, isOpen: isOpen }; if (item.children) { return _react2.default.createElement( 'div', { key: item.href + '-' + index }, isOpen ? _react2.default.createElement(_anchorLink2.default, (0, _extends3.default)({}, props, { isParent: true, style: { marginBottom: 0, borderLeftColor: '#DADFE8', color: '#151F28' } })) : null, item.children.map(function (g) { var props = { href: g.href, title: g.title, allowFold: allowFold, isOpen: isOpen, isSub: true }; return _react2.default.createElement(_anchorLink2.default, (0, _extends3.default)({}, props, { key: g.href })); }) ); } else { return _react2.default.createElement(_anchorLink2.default, (0, _extends3.default)({}, props, { key: item.href })); } }) ), allowFold ? _react2.default.createElement( 'div', { className: prefix + '-fold', onClick: function onClick() { return _this2.handlerOpen(); } }, _react2.default.createElement( 'span', null, isOpen ? _react2.default.createElement( 'svg', { viewBox: '0 0 1024 1024', version: '1.1', xmlns: 'http://www.w3.org/2000/svg', 'p-id': '8015' }, _react2.default.createElement('path', { d: 'M448 672c-6.4 0-19.2 0-25.6-6.4-12.8-12.8-12.8-32 0-44.8L531.2 512 422.4 409.6c-12.8-12.8-12.8-32 0-44.8s32-12.8 44.8 0l128 128c12.8 12.8 12.8 32 0 44.8l-128 128C467.2 672 454.4 672 448 672z', 'p-id': '8016' }) ) : _react2.default.createElement( 'svg', { viewBox: '0 0 1024 1024', version: '1.1', xmlns: 'http://www.w3.org/2000/svg', 'p-id': '8747' }, _react2.default.createElement('path', { d: 'M576 672c-6.4 0-19.2 0-25.6-6.4l-128-128c-12.8-12.8-12.8-32 0-44.8l128-128c12.8-12.8 32-12.8 44.8 0s12.8 32 0 44.8L492.8 512l102.4 102.4c12.8 12.8 12.8 32 0 44.8C595.2 672 582.4 672 576 672z', 'p-id': '8748' }) ) ) ) : null ); var contextValue = this.getMemoizedContextValue(activeLink, onClick); return _react2.default.createElement( _context2.default.Provider, { value: contextValue }, !affix ? anchorContent : _react2.default.createElement( _affix2.default, { useAbsolute: true, offsetTop: offsetTop, target: this.getContainer }, anchorContent ) ); }; return Anchor; }(_react.Component), _class.propTypes = { prefix: _propTypes2.default.string, className: _propTypes2.default.string, style: _propTypes2.default.any, dataSource: _propTypes2.default.array, allowFold: _propTypes2.default.bool, open: _propTypes2.default.bool, children: _propTypes2.default.any, offsetTop: _propTypes2.default.number, bounds: _propTypes2.default.number, affix: _propTypes2.default.bool, getContainer: _propTypes2.default.func, /** Return customize highlight anchor */ getCurrentAnchor: _propTypes2.default.func, onClick: function onClick(e, link) { return _propTypes2.default.void; }, /** Scroll to target offset value, if none, it's offsetTop prop value or 0. */ targetOffset: _propTypes2.default.number, /** Listening event when scrolling change active link */ onChange: function onChange(currentActiveLink) { return _propTypes2.default.void; } }, _class.defaultProps = { prefix: 'next-anchor', affix: true, allowFold: false, open: false }, _temp2); Anchor.displayName = 'Anchor'; exports.default = _configProvider2.default.config((0, _reactLifecyclesCompat.polyfill)(Anchor)); module.exports = exports['default'];