UNPKG

ahooks

Version:
129 lines (128 loc) 4.23 kB
import { useEffect, useState, useRef } from 'react'; import screenfull from 'screenfull'; import useLatest from '../useLatest'; import useMemoizedFn from '../useMemoizedFn'; import { getTargetElement } from '../utils/domTarget'; import { isBoolean } from '../utils'; const useFullscreen = (target, options) => { const { onExit, onEnter, pageFullscreen = false } = options || {}; const { className = 'ahooks-page-fullscreen', zIndex = 999999 } = isBoolean(pageFullscreen) || !pageFullscreen ? {} : pageFullscreen; const onExitRef = useLatest(onExit); const onEnterRef = useLatest(onEnter); // The state of full screen may be changed by other scripts/components, // so the initial value needs to be computed dynamically. const [state, setState] = useState(getIsFullscreen); const stateRef = useRef(getIsFullscreen()); function getIsFullscreen() { return (screenfull.isEnabled && !!screenfull.element && screenfull.element === getTargetElement(target)); } const invokeCallback = (fullscreen) => { var _a, _b; if (fullscreen) { (_a = onEnterRef.current) === null || _a === void 0 ? void 0 : _a.call(onEnterRef); } else { (_b = onExitRef.current) === null || _b === void 0 ? void 0 : _b.call(onExitRef); } }; const updateFullscreenState = (fullscreen) => { // Prevent repeated calls when the state is not changed. if (stateRef.current !== fullscreen) { invokeCallback(fullscreen); setState(fullscreen); stateRef.current = fullscreen; } }; const onScreenfullChange = () => { const fullscreen = getIsFullscreen(); updateFullscreenState(fullscreen); }; const togglePageFullscreen = (fullscreen) => { const el = getTargetElement(target); if (!el) { return; } let styleElem = document.getElementById(className); if (fullscreen) { el.classList.add(className); if (!styleElem) { styleElem = document.createElement('style'); styleElem.setAttribute('id', className); styleElem.textContent = ` .${className} { position: fixed; left: 0; top: 0; right: 0; bottom: 0; width: 100% !important; height: 100% !important; z-index: ${zIndex}; }`; el.appendChild(styleElem); } } else { el.classList.remove(className); if (styleElem) { styleElem.remove(); } } updateFullscreenState(fullscreen); }; const enterFullscreen = () => { const el = getTargetElement(target); if (!el) { return; } if (pageFullscreen) { togglePageFullscreen(true); return; } if (screenfull.isEnabled) { try { screenfull.request(el); } catch (error) { console.error(error); } } }; const exitFullscreen = () => { const el = getTargetElement(target); if (!el) { return; } if (pageFullscreen) { togglePageFullscreen(false); return; } if (screenfull.isEnabled && screenfull.element === el) { screenfull.exit(); } }; const toggleFullscreen = () => { if (state) { exitFullscreen(); } else { enterFullscreen(); } }; useEffect(() => { if (!screenfull.isEnabled || pageFullscreen) { return; } screenfull.on('change', onScreenfullChange); return () => { screenfull.off('change', onScreenfullChange); }; }, []); return [ state, { enterFullscreen: useMemoizedFn(enterFullscreen), exitFullscreen: useMemoizedFn(exitFullscreen), toggleFullscreen: useMemoizedFn(toggleFullscreen), isEnabled: screenfull.isEnabled, }, ]; }; export default useFullscreen;