organism-react-scroll-nav
Version:
A React scroll spy library with flux
160 lines (155 loc) • 4.42 kB
JavaScript
import _objectSpread from "reshow-runtime/es/helpers/objectSpread2";
import _objectWithoutProperties from "reshow-runtime/es/helpers/objectWithoutProperties";
var _excluded = ["noDelay", "monitorScroll", "attachDestRetry", "id", "scrollMargin", "children", "container", "className", "attachDest"];
//@ts-check
import React from "react";
var {
useRef,
useMemo,
useState,
useEffect,
useCallback
} = React;
import { mixClass, build, getDisplayName, SemanticUI } from "react-atomic-molecule";
import { useDebounce, useMounted } from "reshow-hooks";
import scrollStore from "../../stores/scrollStore.mjs";
import fastScrollStore from "../../stores/fastScrollStore.mjs";
/**
* @typedef {any} ScrollSpyProps
*/
/**
* @param {ScrollSpyProps} props
*/
var useScrollSpy = function useScrollSpy(props) {
/**
* monitorScroll use in store, in component just for reset props.
*/
var {
noDelay = false,
monitorScroll = true,
attachDestRetry = 20,
id,
scrollMargin,
children,
container,
className,
attachDest
} = props,
restProps = _objectWithoutProperties(props, _excluded);
var [targetId, setTargetId] = useState(id);
var _mount = useMounted();
var lastEl = useRef(null);
/** @type {React.RefObject<object>} */
var lastConfig = useRef({});
lastConfig.current = _objectSpread(_objectSpread({}, lastConfig.current), {}, {
id: targetId,
attachDest: lastConfig.current.attachDest || attachDest,
monitorScroll,
scrollMargin
});
var nextContainer = useRef(null);
useEffect(function () {
var store = noDelay ? fastScrollStore : scrollStore;
var id = store.scroller.attach(expose);
lastConfig.current.store = store;
setTargetId(id);
return function () {
store.scroller.detach(expose);
};
}, []);
var warnDebounce = useDebounce(
/**
* @param {object} args
*/
function (args) {
// for lazy render component, that warn delay 1.5 secs.
if (!lastEl.current && _mount()) {
// maybe could get lastEl late.
console.warn('Please use SemanticUI. props.container -> import {SemanticUI} from "react-atomic-molecule"', args);
}
}, 1500);
var getOffsetEl = useCallback(function () {
if (lastEl.current) {
return lastEl.current;
} else {
warnDebounce({
targetId,
container: nextContainer.current
});
}
}, [targetId]);
var expose = {
lastConfig,
getOffsetEl,
detach: function detach() {
return lastConfig.current.store.scroller.detach(expose);
},
getId: function getId() {
return lastConfig.current.id;
},
setId: setTargetId,
getAttachDest: function getAttachDest() {
return lastConfig.current.attachDest;
},
/**
* @param {object} attachDest the scroll-node
*/
setAttachDest: function setAttachDest(attachDest) {
return lastConfig.current.attachDest = attachDest;
},
getMonitorScroll: function getMonitorScroll() {
return lastConfig.current.monitorScroll;
},
getScrollMargin: function getScrollMargin() {
return lastConfig.current.scrollMargin;
},
getAttachDestRetry: function getAttachDestRetry() {
return attachDestRetry;
}
};
restProps.id = targetId;
restProps.refCb = lastEl;
restProps.className = mixClass(className, "spy-tar-" + targetId, "scroll-spy");
return {
targetId,
className,
children,
container,
noDelay,
nextContainer,
restProps
};
};
/**
* @param {ScrollSpyProps} props
*/
var ScrollSpy = function ScrollSpy(props) {
var {
targetId,
children,
container,
noDelay,
nextContainer,
restProps
} = useScrollSpy(props);
return useMemo(function () {
var hasScrollReceiver = "ScrollReceiver" === getDisplayName(children) ? true : false;
var nextProps;
if (hasScrollReceiver) {
nextContainer.current = children;
nextProps = _objectSpread(_objectSpread(_objectSpread({}, children.props), restProps), {}, {
scrollMargin: props.scrollMargin,
targetId,
container,
noDelay
});
} else {
nextContainer.current = container || SemanticUI;
nextProps = _objectSpread(_objectSpread({}, restProps), {}, {
children
});
}
return build(nextContainer.current)(nextProps);
}, [children, targetId]);
};
export default ScrollSpy;