@daredrop/react-scroll
Version:
A scroll component for React.js
292 lines (219 loc) • 10 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _scrollSpy = require('./scroll-spy');
var _scrollSpy2 = _interopRequireDefault(_scrollSpy);
var _scroller = require('./scroller');
var _scroller2 = _interopRequireDefault(_scroller);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _scrollHash = require('./scroll-hash');
var _scrollHash2 = _interopRequireDefault(_scrollHash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var protoTypes = {
to: _propTypes2.default.string.isRequired,
containerId: _propTypes2.default.string,
container: _propTypes2.default.object,
activeClass: _propTypes2.default.string,
spy: _propTypes2.default.bool,
horizontal: _propTypes2.default.bool,
smooth: _propTypes2.default.oneOfType([_propTypes2.default.bool, _propTypes2.default.string]),
offset: _propTypes2.default.number,
delay: _propTypes2.default.number,
isDynamic: _propTypes2.default.bool,
onClick: _propTypes2.default.func,
duration: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.func]),
absolute: _propTypes2.default.bool,
onSetActive: _propTypes2.default.func,
onSetInactive: _propTypes2.default.func,
ignoreCancelEvents: _propTypes2.default.bool,
hashSpy: _propTypes2.default.bool,
saveHashHistory: _propTypes2.default.bool,
spyThrottle: _propTypes2.default.number
};
exports.default = function (Component, customScroller) {
var scroller = customScroller || _scroller2.default;
var Link = function (_React$PureComponent) {
_inherits(Link, _React$PureComponent);
function Link(props) {
_classCallCheck(this, Link);
var _this = _possibleConstructorReturn(this, (Link.__proto__ || Object.getPrototypeOf(Link)).call(this, props));
_initialiseProps.call(_this);
_this.state = {
active: false
};
return _this;
}
_createClass(Link, [{
key: 'getScrollSpyContainer',
value: function getScrollSpyContainer() {
var containerId = this.props.containerId;
var container = this.props.container;
if (containerId && !container) {
return document.getElementById(containerId);
}
if (container && container.nodeType) {
return container;
}
return document;
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
if (this.props.spy || this.props.hashSpy) {
var scrollSpyContainer = this.getScrollSpyContainer();
if (!_scrollSpy2.default.isMounted(scrollSpyContainer)) {
_scrollSpy2.default.mount(scrollSpyContainer, this.props.spyThrottle);
}
if (this.props.hashSpy) {
if (!_scrollHash2.default.isMounted()) {
_scrollHash2.default.mount(scroller);
}
_scrollHash2.default.mapContainer(this.props.to, scrollSpyContainer);
}
_scrollSpy2.default.addSpyHandler(this.spyHandler, scrollSpyContainer);
this.setState({
container: scrollSpyContainer
});
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
_scrollSpy2.default.unmount(this.stateHandler, this.spyHandler);
}
}, {
key: 'render',
value: function render() {
var className = "";
if (this.state && this.state.active) {
className = ((this.props.className || "") + " " + (this.props.activeClass || "active")).trim();
} else {
className = this.props.className;
}
var props = _extends({}, this.props);
for (var prop in protoTypes) {
if (props.hasOwnProperty(prop)) {
delete props[prop];
}
}
props.className = className;
props.onClick = this.handleClick;
return _react2.default.createElement(Component, props);
}
}]);
return Link;
}(_react2.default.PureComponent);
var _initialiseProps = function _initialiseProps() {
var _this2 = this;
this.scrollTo = function (to, props) {
scroller.scrollTo(to, _extends({}, _this2.state, props));
};
this.handleClick = function (event) {
/*
* give the posibility to override onClick
*/
if (_this2.props.onClick) {
_this2.props.onClick(event);
}
/*
* dont bubble the navigation
*/
if (event.stopPropagation) event.stopPropagation();
if (event.preventDefault) event.preventDefault();
/*
* do the magic!
*/
_this2.scrollTo(_this2.props.to, _this2.props);
};
this.spyHandler = function (x, y) {
var scrollSpyContainer = _this2.getScrollSpyContainer();
if (_scrollHash2.default.isMounted() && !_scrollHash2.default.isInitialized()) {
return;
}
var horizontal = _this2.props.horizontal;
var to = _this2.props.to;
var element = null;
var isInside = void 0;
var isOutside = void 0;
if (horizontal) {
var elemLeftBound = 0;
var elemRightBound = 0;
var containerLeft = 0;
if (scrollSpyContainer.getBoundingClientRect) {
var containerCords = scrollSpyContainer.getBoundingClientRect();
containerLeft = containerCords.left;
}
if (!element || _this2.props.isDynamic) {
element = scroller.get(to);
if (!element) {
return;
}
var cords = element.getBoundingClientRect();
elemLeftBound = cords.left - containerLeft + x;
elemRightBound = elemLeftBound + cords.width;
}
var offsetX = x - _this2.props.offset;
isInside = offsetX >= Math.floor(elemLeftBound) && offsetX < Math.floor(elemRightBound);
isOutside = offsetX < Math.floor(elemLeftBound) || offsetX >= Math.floor(elemRightBound);
} else {
var elemTopBound = 0;
var elemBottomBound = 0;
var containerTop = 0;
if (scrollSpyContainer.getBoundingClientRect) {
var _containerCords = scrollSpyContainer.getBoundingClientRect();
containerTop = _containerCords.top;
}
if (!element || _this2.props.isDynamic) {
element = scroller.get(to);
if (!element) {
return;
}
var _cords = element.getBoundingClientRect();
elemTopBound = _cords.top - containerTop + y;
elemBottomBound = elemTopBound + _cords.height;
}
var offsetY = y - _this2.props.offset;
isInside = offsetY >= Math.floor(elemTopBound) && offsetY < Math.floor(elemBottomBound);
isOutside = offsetY < Math.floor(elemTopBound) || offsetY >= Math.floor(elemBottomBound);
}
var activeLink = scroller.getActiveLink();
if (isOutside) {
if (to === activeLink) {
scroller.setActiveLink(void 0);
}
if (_this2.props.hashSpy && _scrollHash2.default.getHash() === to) {
var _props$saveHashHistor = _this2.props.saveHashHistory,
saveHashHistory = _props$saveHashHistor === undefined ? false : _props$saveHashHistor;
_scrollHash2.default.changeHash("", saveHashHistory);
}
if (_this2.props.spy && _this2.state.active) {
_this2.setState({ active: false });
_this2.props.onSetInactive && _this2.props.onSetInactive(to, element);
}
}
if (isInside && (activeLink !== to || _this2.state.active === false)) {
scroller.setActiveLink(to);
var _props$saveHashHistor2 = _this2.props.saveHashHistory,
_saveHashHistory = _props$saveHashHistor2 === undefined ? false : _props$saveHashHistor2;
_this2.props.hashSpy && _scrollHash2.default.changeHash(to, _saveHashHistory);
if (_this2.props.spy) {
_this2.setState({ active: true });
_this2.props.onSetActive && _this2.props.onSetActive(to, element);
}
}
};
};
;
Link.propTypes = protoTypes;
Link.defaultProps = { offset: 0 };
return Link;
};