105 lines
3.1 KiB
TypeScript
105 lines
3.1 KiB
TypeScript
import React, { VideoHTMLAttributes, forwardRef, useRef, useState, useEffect } from 'react';
|
|
|
|
import classNames from 'classnames';
|
|
import { Box, IconButton, Icon, Icons, Tooltip, TooltipProvider, Text } from 'folds';
|
|
import * as css from './media.css';
|
|
import * as videoCss from './videoControls.css';
|
|
|
|
type VideoProps = VideoHTMLAttributes<HTMLVideoElement> & {
|
|
disableControls?: boolean;
|
|
onExpand?: () => void;
|
|
};
|
|
|
|
export const Video = forwardRef<HTMLVideoElement, VideoProps>(
|
|
({ className, disableControls, onExpand, ...props }, ref) => {
|
|
const videoRef = useRef<HTMLVideoElement>(null);
|
|
const [showControls, setShowControls] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (typeof ref === 'function') {
|
|
ref(videoRef.current);
|
|
} else if (ref) {
|
|
ref.current = videoRef.current;
|
|
}
|
|
}, [ref]);
|
|
|
|
useEffect(() => {
|
|
if (!onExpand) return;
|
|
const video = videoRef.current;
|
|
if (!video) return;
|
|
|
|
const handleFullscreenRequest = (evt: Event) => {
|
|
evt.preventDefault();
|
|
evt.stopImmediatePropagation();
|
|
onExpand();
|
|
};
|
|
|
|
video.addEventListener('webkitbeginfullscreen', handleFullscreenRequest);
|
|
return () => {
|
|
video.removeEventListener('webkitbeginfullscreen', handleFullscreenRequest);
|
|
};
|
|
}, [onExpand]);
|
|
|
|
if (disableControls) {
|
|
return (
|
|
// eslint-disable-next-line jsx-a11y/media-has-caption
|
|
<video
|
|
className={classNames(css.Video, className)}
|
|
{...props}
|
|
ref={videoRef}
|
|
loop={props.autoPlay}
|
|
muted={props.autoPlay}
|
|
playsInline
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Box
|
|
className={videoCss.VideoContainer}
|
|
onMouseEnter={() => setShowControls(true)}
|
|
onMouseLeave={() => setShowControls(false)}
|
|
>
|
|
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
|
|
<video
|
|
className={classNames(css.Video, className)}
|
|
{...props}
|
|
ref={videoRef}
|
|
loop={props.autoPlay}
|
|
muted={props.autoPlay}
|
|
playsInline
|
|
controlsList={onExpand ? 'nofullscreen' : undefined}
|
|
onDoubleClick={onExpand ? (e) => { e.stopPropagation(); onExpand(); } : undefined}
|
|
/>
|
|
|
|
{onExpand && (
|
|
<Box className={classNames(videoCss.VideoControlsOverlay, !showControls && videoCss.VideoControlsOverlayHidden)} gap="200">
|
|
<TooltipProvider
|
|
tooltip={
|
|
<Tooltip variant="Secondary">
|
|
<Text size="T200">Expand</Text>
|
|
</Tooltip>
|
|
}
|
|
position="Bottom"
|
|
align="Center"
|
|
>
|
|
{(triggerRef) => (
|
|
<IconButton
|
|
ref={triggerRef}
|
|
variant="Secondary"
|
|
size="300"
|
|
radii="300"
|
|
onClick={onExpand}
|
|
aria-label="Expand video"
|
|
>
|
|
<Icon size="50" src={Icons.Plus} />
|
|
</IconButton>
|
|
)}
|
|
</TooltipProvider>
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
);
|
|
}
|
|
);
|