UNPKG

@smitch/fluid

Version:

A Next/React ui-component libray.

126 lines (125 loc) 6.96 kB
'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;