@smitch/fluid
Version:
A Next/React ui-component libray.
126 lines (125 loc) • 6.96 kB
JavaScript
'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useRef, useEffect, useCallback, useMemo, useState } from 'react';
import VideoTracks from './VideoTracks';
import { twMerge } from 'tailwind-merge';
import { Loading, Alert } from '..';
var posterSrc = '/poster.png';
var loadingClasses = '[&&::-webkit-media-controls-panel]:!hidden [&&::-webkit-media-controls-enclosure]:!hidden [&&::-webkit-media-controls]:!hidden';
var grayscaleClasses = {
none: '',
grayscale: 'grayscale',
sepia: 'sepia',
};
var aspects = {
square: 'aspect-square',
phone: 'aspect-[9/16]',
video: 'aspect-video',
television: 'aspect-[4/3]',
cinema: 'aspect-[21/9]',
ultrawide: 'aspect-[12/5]',
};
var Video = function (_a) {
var src = _a.src, _b = _a.poster, poster = _b === void 0 ? posterSrc : _b, tracks = _a.tracks, srcLangs = _a.srcLangs, trackIndex = _a.trackIndex, _c = _a.controls, controls = _c === void 0 ? true : _c, _d = _a.aspect, aspect = _d === void 0 ? 'video' : _d, _e = _a.videoWidth, videoWidth = _e === void 0 ? '100%' : _e, _f = _a.videoHeight, videoHeight = _f === void 0 ? 'auto' : _f, _g = _a.loop, loop = _g === void 0 ? false : _g, muted = _a.muted, autoplay = _a.autoplay, setDuration = _a.setDuration, setTime = _a.setTime, play = _a.play, togglePlay = _a.togglePlay, _h = _a.preload, preload = _h === void 0 ? 'metadata' : _h, _j = _a.fallback, fallback = _j === void 0 ? 'Your browser does not support the video tag.' : _j, currentTime = _a.currentTime, playEnded = _a.playEnded, _k = _a.volume, volume = _k === void 0 ? 5 : _k, _l = _a.formats, formats = _l === void 0 ? ['mp4'] : _l, _m = _a.pictureInPicture, pictureInPicture = _m === void 0 ? false : _m, _o = _a.defaultError, defaultError = _o === void 0 ? 'Video cannot be loaded.' : _o, _p = _a.grayscale, grayscale = _p === void 0 ? 'none' : _p, _q = _a.blur, blur = _q === void 0 ? false : _q, _r = _a.className, className = _r === void 0 ? '' : _r;
var videoRef = useRef(null);
var _s = useState(false), loading = _s[0], setLoading = _s[1];
var _t = useState(''), error = _t[0], setError = _t[1];
var aspectRatioClasses = useMemo(function () { return aspects[aspect]; }, [aspect]);
useEffect(function () {
var node = videoRef.current;
if (node)
play ? node.play() : node.pause();
}, [play]);
useEffect(function () {
var node = videoRef.current;
if (node && trackIndex) {
var textTracks = node.textTracks;
for (var i = 0; i < textTracks.length; i++) {
if (i === Number(trackIndex))
textTracks[i].mode = 'showing';
else
textTracks[i].mode = 'disabled';
}
}
}, [trackIndex]);
useEffect(function () {
var node = videoRef.current;
if (node && typeof document !== null && node.duration) {
if (document.pictureInPictureElement) {
document.exitPictureInPicture();
}
else if (document.pictureInPictureEnabled) {
node.requestPictureInPicture();
}
}
}, [pictureInPicture]);
useEffect(function () {
var node = videoRef.current;
if (node && currentTime) {
node.currentTime = currentTime;
}
}, [currentTime]);
useEffect(function () {
var node = videoRef.current;
if (node)
node.volume = volume / 10;
}, [volume]);
var handleLoadedmetadata = useCallback(function () {
if (videoRef.current && setDuration)
setDuration(videoRef.current.duration);
}, [setDuration]);
var handleTogglePlay = function () {
if (togglePlay)
togglePlay();
};
var handleEnd = useCallback(function () {
var node = videoRef.current;
if (node && !loop) {
node.currentTime = 0;
}
if (playEnded)
playEnded();
}, [playEnded, loop]);
var handleTime = useCallback(function () {
if (videoRef.current && setTime)
setTime(videoRef.current.currentTime);
}, [setTime]);
var handleError = useCallback(function () {
var _a;
var node = videoRef.current;
if (node) {
var error_1 = ((_a = node.error) === null || _a === void 0 ? void 0 : _a.message) || defaultError;
setError(error_1);
setLoading(false);
}
}, [setError, defaultError]);
var handleWaiting = useCallback(function () {
setLoading(true);
}, [setLoading]);
var handleCanPlay = useCallback(function () {
setLoading(false);
}, [setLoading]);
var setVideoRef = useCallback(function (node) {
if (node) {
videoRef.current = node;
node.addEventListener('waiting', handleWaiting);
node.addEventListener('canplay', handleCanPlay);
node.addEventListener('loadedmetadata', handleLoadedmetadata, true);
node.addEventListener('ended', handleEnd, true);
node.addEventListener('timeupdate', handleTime, true);
node.addEventListener('error', handleError, true);
}
return function () {
if (node) {
node.removeEventListener('waiting', handleWaiting);
node.removeEventListener('canplay', handleCanPlay);
node.removeEventListener('loadedmetadata', handleLoadedmetadata, true);
node.removeEventListener('ended', handleEnd, true);
node.removeEventListener('timeupdate', handleTime, true);
node.removeEventListener('error', handleError, true);
}
};
}, [handleEnd, handleError, handleLoadedmetadata, handleTime, handleWaiting, handleCanPlay]);
return (_jsxs("figure", { className: twMerge("video-figure group overflow-hidden flex items-center relative ".concat(aspectRatioClasses), className), children: [_jsxs("video", { poster: poster, width: videoWidth, height: videoHeight, controls: controls, loop: loop, ref: setVideoRef, className: "video bg-black ".concat(grayscaleClasses[grayscale], " ").concat(blur ? 'blur' : '', " ").concat(videoHeight === '100%' ? 'object-cover h-full' : '', " ").concat(loading ? loadingClasses : ''), muted: muted, autoPlay: autoplay, preload: preload, onClick: handleTogglePlay, children: [formats.map(function (format, index) { return (_jsx("source", { src: "".concat(src.slice(0, src.lastIndexOf('.')), ".").concat(format), type: "video/".concat(format) }, index)); }), tracks ? (_jsx(VideoTracks, { tracks: tracks, srcLangs: srcLangs })) : null, _jsx("p", { children: fallback })] }), error && (_jsx(Alert, { title: 'Error', message: error, status: 'error', layout: 'solid', className: '!absolute inset-0' })), loading && (_jsx(Loading, { className: 'absolute w-full', size: 'lg' }))] }));
};
export default Video;