UNPKG

@6thquake/react-material

Version:

React components that implement Google's Material Design.

511 lines (429 loc) 14.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.scrollToAnchor = exports.styles = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf3 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _withStyles = _interopRequireDefault(require("../styles/withStyles")); var _classnames = _interopRequireDefault(require("classnames")); var _colorManipulator = require("../styles/colorManipulator"); var _throttle = require("../utils/throttle"); var styles = function styles(theme) { return { verticalAnchorRoot: { position: 'relative', display: 'flex', overflow: 'hidden', width: '100%' }, anchorWrapper: { marginTop: 0, marginBottom: 0, paddingLeft: 0, paddingRight: theme.spacing(4) }, ul: { position: 'relative', zIndex: 2, listStyleType: 'none', paddingLeft: theme.spacing(4) }, active: { color: " ".concat(theme.palette.primary.dark, " !important") }, wrapper: { position: 'relative', paddingRight: 0 }, activeMask: { position: 'absolute', backgroundColor: (0, _colorManipulator.fade)(theme.palette.primary.main, 0.2), borderLeft: "2px solid ".concat(theme.palette.primary.dark), transition: 'all .2s ease', zIndex: 1, width: '100%', right: 0, // height: 40, left: -2 }, link: { display: 'flex', alignItems: 'center', textDecoration: 'none', color: theme.palette.common.black, cursor: 'pointer', height: 40 }, veLinkActive: { color: theme.palette.primary.dark }, hoLink: { color: theme.palette.common.black, textDecoration: 'none', '&:hover': { backgroundColor: (0, _colorManipulator.fade)(theme.palette.primary.main, 0.2) }, padding: "".concat(theme.spacing(1.5), "px ").concat(theme.spacing(2), "px"), textAlign: 'center', cursor: 'pointer', minWidth: 120 }, hoLinkActive: { // transition: 'all 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms', borderBottom: "2px solid ".concat(theme.palette.primary.main), color: theme.palette.primary.main }, line: { height: 'inherit', backgroundColor: theme.palette.grey['300'], marginLeft: 0, marginTop: 0, marginBottom: 0, paddingLeft: 2 }, horizontalAnchorRoot: { display: 'flex' } }; }; exports.styles = styles; var scrollToAnchor = function scrollToAnchor(anchorName) { if (anchorName) { var anchorElement = document.querySelector(anchorName); if (anchorElement) { anchorElement.scrollIntoView(); } } }; exports.scrollToAnchor = scrollToAnchor; var Anchor = /*#__PURE__*/ function (_React$Component) { (0, _inherits2.default)(Anchor, _React$Component); function Anchor() { var _getPrototypeOf2; var _this; (0, _classCallCheck2.default)(this, Anchor); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = (0, _possibleConstructorReturn2.default)(this, (_getPrototypeOf2 = (0, _getPrototypeOf3.default)(Anchor)).call.apply(_getPrototypeOf2, [this].concat(args))); _this.state = { linkToTop: 10, linkHeight: 40, links: {}, active: '' }; _this.level = 0; _this.container = null; _this.wrapper = null; _this.nearestLink = function (links) { var min = { key: '', value: Infinity }; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = links[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var link = _step.value; var sel = link.value; var ele = document.querySelector(sel); var dh = ele ? _this.getOffsetTop(ele, _this.container) : Infinity; if (dh > 50 && sel === _this.props.links[0].value) { sel = ''; } var absDh = Math.abs(dh); if (absDh < min.value) { min = { key: sel, value: absDh }; } if (link.children) { var m = _this.nearestLink(link.children); if (m.value < min.value) { min = m; } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return min; }; _this.scrollDirection = function (pre, cur) { if (pre === '') { return 'down'; } if (cur === '') { return 'up'; } var preHeight = document.querySelector(pre).getBoundingClientRect().top; var curHeight = document.querySelector(cur).getBoundingClientRect().top; var dh = preHeight - curHeight; if (dh > 0) { return 'up'; } return 'down'; }; _this.setMask = function (sel) { var horizontal = _this.props.horizontal; if (!horizontal) { var links = _this.wrapper.querySelectorAll('a'); var target = null; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = links[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var link = _step2.value; if (link.name === sel) { target = link; break; } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return != null) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } var top = target && _this.getOffsetTop(target, _this.wrapper); var height = target && target.getBoundingClientRect().height; _this.setState({ linkToTop: top, linkHeight: height }); } }; _this.changeActiveLink = function (sel) { var onChange = _this.props.onChange; if (_this.state.active !== sel) { var dir = _this.scrollDirection(_this.state.active, sel); onChange && onChange({ name: sel, direction: dir }); _this.state.active = sel; } var activeLink = (0, _defineProperty2.default)({}, sel, true); _this.setMask(sel); _this.setState({ links: activeLink }); return true; }; _this.scrollHandle = function (e) { var links = _this.props.links; _this.setLinks(links); }; _this.renderItem = function (link, index, children) { var _this$props = _this.props, classes = _this$props.classes, hash = _this$props.hash; var selected = _this.state.links[link.value]; var mergeClassName = (0, _classnames.default)(classes.link, (0, _defineProperty2.default)({}, classes.veLinkActive, selected)); var prop = {}; if (!hash) { prop.href = link.value; } return _react.default.createElement("li", { key: index, className: classes.li }, _react.default.createElement("a", (0, _extends2.default)({ name: link.value, className: mergeClassName, onClick: function onClick(e) { return _this.scrollToAnchor(link.value); } }, prop), link.label), children && _this.renderLinks(children)); }; _this.renderLink = function (link, index) { return _this.renderItem(link, index, link.children); }; _this.renderLinks = function (links) { var classes = _this.props.classes; var result = links.map(function (link, index) { return _this.renderLink(link, index); }); return _react.default.createElement("ul", { className: classes.ul }, result); }; _this.renderHorizontalLinks = function (links) { var _this$props2 = _this.props, classes = _this$props2.classes, hash = _this$props2.hash; var result = links.map(function (link, index) { var selected = _this.state.links[link.value]; var mergeClassName = (0, _classnames.default)(classes.hoLink, (0, _defineProperty2.default)({}, classes.hoLinkActive, selected)); var prop = {}; if (!hash) { prop.href = link.value; } return _react.default.createElement("a", (0, _extends2.default)({ key: link.value, name: link.value, className: mergeClassName, onClick: function onClick(e) { return _this.scrollToAnchor(link.value); } }, prop), link.label); }); return _react.default.createElement("div", { ref: function ref(e) { _this.setRef(e); }, className: classes.horizontalAnchorRoot }, result); }; _this.scrollToAnchor = function (id, index) { if (_this.props.hash) { return scrollToAnchor(id); } console.log('scrollToAnchor'); }; _this.setRef = function (e) { _this.wrapper = e; }; return _this; } (0, _createClass2.default)(Anchor, [{ key: "componentDidMount", value: function componentDidMount() { var sel = this.props.container; this.container = document.querySelector(sel) || window; this.ths = (0, _throttle.throttle)(this.scrollHandle, 50); this.container.addEventListener('scroll', this.ths); this.setLinks(this.props.links); } }, { key: "componentWillUnmount", value: function componentWillUnmount() { this.container.removeEventListener('scroll', this.ths, false); } // find the nearest link to the contianer }, { key: "setLinks", value: function setLinks(links) { var nearestLink = this.nearestLink(links); this.changeActiveLink(nearestLink.key); } // 找到子元素在父元素中的相对位置 }, { key: "getOffsetTop", value: function getOffsetTop(element, container) { var eleRectTop = element.getBoundingClientRect().top; if (container === window) { container = element.ownerDocument.documentElement; return eleRectTop - container.clientTop; } var containerRectTop = container.getBoundingClientRect().top; return eleRectTop - containerRectTop; } // 激活高亮选项 }, { key: "render", value: function render() { var _this$props3 = this.props, classes = _this$props3.classes, links = _this$props3.links, style = _this$props3.style, horizontal = _this$props3.horizontal; var _this$state = this.state, active = _this$state.active, linkToTop = _this$state.linkToTop, linkHeight = _this$state.linkHeight; var maskStyle = { top: linkToTop, height: linkHeight }; return horizontal ? this.renderHorizontalLinks(links) : _react.default.createElement("div", { className: classes.verticalAnchorRoot, style: style }, _react.default.createElement("div", { className: classes.line }), _react.default.createElement("div", { ref: this.setRef, className: classes.wrapper }, active && _react.default.createElement("div", { className: classes.activeMask, style: maskStyle }), _react.default.createElement("div", { className: classes.anchorWrapper }, this.renderLinks(links)))); } }]); return Anchor; }(_react.default.Component); Anchor.propTypes = { /** * Override or extend the styles applied to the component. * See [CSS API](#css-api) below for more details. */ classes: _propTypes.default.object, /** * selector, which will be used to find The scope of the anchors, * the default value is window */ container: _propTypes.default.string, /** * The mode of Anchor, you will consider this only in SPA */ hash: _propTypes.default.bool, /** * The orientation of Anchor, * if true, the orientation will be horizontal, * if false, the orientation will be vertical */ horizontal: _propTypes.default.bool, /** * The links you want to render on Anchor, * links: PropTypes.arrayOf(PropTypes.shape({ * label: PropTypes.node, * value: PropTypes.string, * children: PropTypes.array, * })).isRequired, * */ links: _propTypes.default.array.isRequired, /** * Callback fired when the active link changed */ onChange: _propTypes.default.func }; Anchor.defaultProps = { horizontal: false, hash: false }; var _default = (0, _withStyles.default)(styles, { name: 'RMAnchor' })(Anchor); exports.default = _default;