import React, { useState, useCallback, useRef, useEffect, } from 'react'; import { animateScroll } from 'react-scroll'; import { useRipple } from 'react-use-ripple'; import StickyEvents from 'sticky-events'; import { usePageCreateModal } from '~/stores/modal'; import { useCurrentPagePath } from '~/stores/page'; import { useIsAbleToChangeEditorMode } from '~/stores/ui'; import loggerFactory from '~/utils/logger'; import { CreatePageIcon } from './Icons/CreatePageIcon'; import { ReturnTopIcon } from './Icons/ReturnTopIcon'; import styles from './Fab.module.scss'; const logger = loggerFactory('growi:cli:Fab'); export const Fab = (): JSX.Element => { const { data: isAbleToChangeEditorMode } = useIsAbleToChangeEditorMode(); const { data: currentPath = '' } = useCurrentPagePath(); const { open: openCreateModal } = usePageCreateModal(); const [animateClasses, setAnimateClasses] = useState('invisible'); const [buttonClasses, setButtonClasses] = useState(''); const [isSticky, setIsSticky] = useState(false); // ripple const createBtnRef = useRef(null); useRipple(createBtnRef, { rippleColor: 'rgba(255, 255, 255, 0.3)' }); /** * After the fade animation is finished, fix the button display status. * Prevents the fade animation occurred each time by button components rendered. * Check Fab.module.scss for fade animation time. */ useEffect(() => { const timer = setTimeout(() => { if (isSticky) { setAnimateClasses('visible'); setButtonClasses(''); } else { setAnimateClasses('invisible'); } }, 500); return () => clearTimeout(timer); }, [isSticky]); const stickyChangeHandler = useCallback((event) => { logger.debug('StickyEvents.CHANGE detected'); const newAnimateClasses = event.detail.isSticky ? 'animated fadeInUp faster' : 'animated fadeOut faster'; const newButtonClasses = event.detail.isSticky ? '' : 'disabled grw-pointer-events-none'; setAnimateClasses(newAnimateClasses); setButtonClasses(newButtonClasses); setIsSticky(event.detail.isSticky); }, []); // setup effect by sticky event useEffect(() => { // sticky // See: https://github.com/ryanwalters/sticky-events const stickyEvents = new StickyEvents({ stickySelector: '#grw-fav-sticky-trigger' }); const { stickySelector } = stickyEvents; const elem = document.querySelector(stickySelector); elem.addEventListener(StickyEvents.CHANGE, stickyChangeHandler); // return clean up handler return () => { elem.removeEventListener(StickyEvents.CHANGE, stickyChangeHandler); }; }, [stickyChangeHandler]); const PageCreateButton = useCallback(() => { return (
); }, [animateClasses, buttonClasses, currentPath, openCreateModal]); const ScrollToTopButton = useCallback(() => { const clickHandler = () => { animateScroll.scrollToTop({ duration: 200 }); }; return (
); }, [animateClasses, buttonClasses]); if (currentPath == null) { return <>; } return (
{isAbleToChangeEditorMode && }
); };