import React, { useMemo, useState, useRef, useEffect, useCallback, } from 'react'; import StickyEvents from 'sticky-events'; import { debounce } from 'throttle-debounce'; import loggerFactory from '~/utils/logger'; import { useSidebarCollapsed } from '~/stores/ui'; import GrowiSubNavigation from './GrowiSubNavigation'; const logger = loggerFactory('growi:cli:GrowiSubNavigationSticky'); /** * Subnavigation * * needs: * #grw-subnav-fixed-container element * #grw-subnav-sticky-trigger element * * @param {object} props */ const GrowiSubNavigationSwitcher = (props) => { const { data: isSidebarCollapsed } = useSidebarCollapsed(); const [isVisible, setVisible] = useState(false); const [width, setWidth] = useState(null); const fixedContainerRef = useRef(); const stickyEvents = useMemo(() => new StickyEvents({ stickySelector: '#grw-subnav-sticky-trigger' }), []); const resetWidth = useCallback(() => { const instance = fixedContainerRef.current; if (instance == null || instance.parentNode == null) { return; } // get parent width const { clientWidth } = instance.parentNode; // update style setWidth(clientWidth); }, []); // setup effect by resizing event useEffect(() => { const resizeHandler = debounce(100, resetWidth); window.addEventListener('resize', resizeHandler); // return clean up handler return () => { window.removeEventListener('resize', resizeHandler); }; }, [resetWidth]); const stickyChangeHandler = useCallback((event) => { logger.debug('StickyEvents.CHANGE detected'); setVisible(event.detail.isSticky); }, []); // setup effect by sticky event useEffect(() => { // sticky // See: https://github.com/ryanwalters/sticky-events const { stickySelector } = stickyEvents; const elem = document.querySelector(stickySelector); elem.addEventListener(StickyEvents.CHANGE, stickyChangeHandler); // return clean up handler return () => { elem.removeEventListener(StickyEvents.CHANGE, stickyChangeHandler); }; }, [stickyChangeHandler, stickyEvents]); // update width when sidebar collapsing changed useEffect(() => { if (isSidebarCollapsed != null) { setTimeout(resetWidth, 300); } }, [isSidebarCollapsed, resetWidth]); // initialize useEffect(() => { resetWidth(); setTimeout(() => { stickyEvents.state.values((sticky) => { setVisible(sticky.isSticky); }); }, 100); }, [resetWidth, stickyEvents]); return (