@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
JavaScript
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;