organism-react-scroll-nav
Version:
A React scroll spy library with flux
178 lines (170 loc) • 5.72 kB
JavaScript
;
var _interopRequireDefault = require("reshow-runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("reshow-runtime/helpers/interopRequireWildcard");
exports.__esModule = true;
exports["default"] = void 0;
var _objectSpread2 = _interopRequireDefault(require("reshow-runtime/helpers/objectSpread2"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("reshow-runtime/helpers/objectWithoutPropertiesLoose"));
var React = _interopRequireWildcard(require("react"));
var _smoothScrollTo = _interopRequireDefault(require("smooth-scroll-to"));
var _getoffset = _interopRequireWildcard(require("getoffset"));
var _callFunc = _interopRequireDefault(require("call-func"));
var _winDoc = require("win-doc");
var _anchorLib = require("anchor-lib");
var _index = require("../../index.js");
var _scrollStore = _interopRequireDefault(require("../../stores/scrollStore.js"));
var _fastScrollStore = _interopRequireDefault(require("../../stores/fastScrollStore.js"));
var _jsxRuntime = require("react/jsx-runtime");
var _excluded = ["targetId", "scrollRefLoc", "scrollRefId", "scrollMargin", "style", "preventDefault", "noDelay", "onClick"]; // @ts-check
var useEffect = React.useEffect,
useState = React.useState,
useCallback = React.useCallback,
useRef = React.useRef;
var scollTimer = null;
var resetTimer = function resetTimer() {
if (scollTimer) {
clearTimeout(scollTimer);
scollTimer = null;
}
};
/**
* @typedef {object} SmoothScrollLinkProps
*/
/**
* @param {SmoothScrollLinkProps} props
*/
var useSmoothScrollLink = function useSmoothScrollLink(props) {
var targetId = props.targetId,
_props$scrollRefLoc = props.scrollRefLoc,
scrollRefLoc = _props$scrollRefLoc === void 0 ? "bottom" : _props$scrollRefLoc,
_props$scrollRefId = props.scrollRefId,
scrollRefId = _props$scrollRefId === void 0 ? "" : _props$scrollRefId,
scrollMargin = props.scrollMargin,
style = props.style,
_props$preventDefault = props.preventDefault,
preventDefault = _props$preventDefault === void 0 ? true : _props$preventDefault,
_props$noDelay = props.noDelay,
noDelay = _props$noDelay === void 0 ? false : _props$noDelay,
onClick = props.onClick,
restProps = (0, _objectWithoutPropertiesLoose2["default"])(props, _excluded);
/**
* @type {[scrollRefElement, setScrollRefElement]}
*/
var _useState = useState(),
scrollRefElement = _useState[0],
setScrollRefElement = _useState[1];
/** @type {any} */
var lastScroll = useRef(null);
/**
* @param {number=} duringTime
*/
var _scrollTo = function scrollTo(duringTime) {
var getStore = function getStore() {
return noDelay ? _fastScrollStore["default"] : _scrollStore["default"];
};
var offset = getStore().scroller.getOffset(targetId);
if (offset) {
var margin = getMargin();
var to = offset.top - margin;
/**
* Let user could cancel scroll with different direction.
*/
if (lastScroll.current === to) {
return;
}
setTimeout(function () {
return lastScroll.current = to;
});
(0, _smoothScrollTo["default"])(to, duringTime, undefined, function () {
resetTimer();
scollTimer = setTimeout(function () {
return _scrollTo(duringTime);
}, 800);
});
}
};
useEffect(function () {
var dom = (0, _winDoc.doc)().getElementById(scrollRefId);
if (dom) {
setScrollRefElement(dom);
}
if ((0, _anchorLib.getAnchorPath)().anchor.substring(1) === targetId) {
setTimeout(function () {
return _scrollTo(1);
});
}
return function () {
resetTimer();
};
}, []);
/**
* When modify getMargin number, should also take care store isActive logic.
*
* https://github.com/react-atomic/organism-react-scroll-nav/blob/main/src/stores/scrollStore.js#L119
*/
var getMargin = useCallback(function () {
var margin = 0;
if (scrollRefElement) {
var refOffset = /**@type OffsetType*/(0, _getoffset["default"])(scrollRefElement);
switch (scrollRefLoc) {
case "bottom":
margin += refOffset.bottom - refOffset.top;
break;
default:
case "top":
break;
}
}
if (!isNaN(scrollMargin)) {
margin += scrollMargin;
}
margin -= 2;
return margin;
}, [scrollRefLoc, scrollMargin, scrollRefElement]);
var handler = {
/**
* @param {object} e
*/
click: function click(e) {
lastScroll.current = null;
if (preventDefault) {
e.preventDefault();
}
(0, _callFunc["default"])(onClick);
_scrollTo();
}
};
return {
restProps: restProps,
handler: handler,
targetId: targetId,
margin: getMargin(),
style: style
};
};
/**
* @param {SmoothScrollLinkProps} props
*/
var SmoothScrollLink = function SmoothScrollLink(props) {
var _useSmoothScrollLink = useSmoothScrollLink(props),
restProps = _useSmoothScrollLink.restProps,
handler = _useSmoothScrollLink.handler,
margin = _useSmoothScrollLink.margin,
style = _useSmoothScrollLink.style,
targetId = _useSmoothScrollLink.targetId;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.ScrollReceiver, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({
atom: "a"
}, restProps), {}, {
targetId: targetId,
scrollMargin: margin,
style: (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, Styles.link), style),
onClick: handler.click
}));
};
var _default = exports["default"] = SmoothScrollLink;
var Styles = {
link: {
cursor: "pointer"
}
};
module.exports = exports.default;