UNPKG

organism-react-scroll-nav

Version:
160 lines (155 loc) 4.42 kB
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;