@6thquake/react-material
Version:
React components that implement Google's Material Design.
511 lines (429 loc) • 14.2 kB
JavaScript
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;
;