UNPKG

@devbookhq/docusaurus-code-video-plugin

Version:

Add a video to a Docusaurus code block and highlight code lines as the video plays.

84 lines (83 loc) 2.91 kB
import React, { useCallback, useEffect, useRef, useLayoutEffect, useState, } from 'react'; import Draggable from 'react-draggable'; import CloseIcon from './CloseIcon'; import YouTube from 'react-youtube'; import styles from './styles.module.css'; import usePosition from './usePosition'; function VideoModal({ youtubeID, onClose, onTimeChange, }) { const [isDragged, setIsDragged] = useState(false); const [player, setPlayer] = useState(); const yRef = useRef(null); const draggableContainerRef = useRef(null); const { changePosition, position, } = usePosition(); useEffect(function checkTime() { if (!player) return; if (!onTimeChange) return; const interval = setInterval(() => { const time = player.getCurrentTime(); onTimeChange(time); }, 400); return () => { clearInterval(interval); }; }, [ player, onTimeChange, ]); useLayoutEffect(() => { if (!draggableContainerRef.current) return; const observer = new IntersectionObserver(([entry]) => { if (!entry) return; if (!entry.isIntersecting) { changePosition({ x: 0, y: 0 }); } }); observer.observe(draggableContainerRef.current); return () => { observer.disconnect(); }; }, [ position, changePosition, draggableContainerRef, ]); const stopDragging = useCallback((_, data) => { setIsDragged(false); changePosition({ x: data.x, y: data.y, }); }, []); return (<> {position && <Draggable nodeRef={draggableContainerRef} onStart={() => setIsDragged(true)} onStop={stopDragging} position={position}> <div className={styles['modal']} ref={draggableContainerRef}> <div className={styles['modal-header']}> <div className={styles['modal-close']} onClick={onClose}> <CloseIcon /> </div> </div> <YouTube ref={yRef} style={{ pointerEvents: isDragged ? 'none' : 'auto' }} iframeClassName={styles['iframe']} onReady={(event) => setPlayer(event.target)} videoId={youtubeID} opts={{ host: 'https://www.youtube-nocookie.com', width: '100%', height: '100%', playerVars: { modestbranding: 1, controls: 1, autoplay: 1, showinfo: 0, fs: 0, rel: 0, iv_load_policy: 3, cc_load_policy: 1, }, }}/> </div> </Draggable>} </>); } export default VideoModal;