import { VisuallyHidden } from '@ariakit/react'; import { getClassNames } from '@websolutespa/bom-core'; import { useIntersectionObserver, useLayout, useMounted, useReducedMotionLocal } from '@websolutespa/bom-mixer-hooks'; import { memo, useCallback, useEffect, useId, useRef, useState } from 'react'; import styled from 'styled-components'; import { Button } from '../button/button'; import { UIStyledComponentProps } from '../types'; import { IMediaItemProps } from './media-items'; const StyledMediaVideo = styled.video` max-width: 100%; // height: auto; user-select: none; color: transparent; &.video { &--muted { &::cue { background-color: transparent; background-image: none; color: transparent; font-size: 0; } } } `; const StyledButton = styled(Button)` position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; `; export type MediaVideoProps = UIStyledComponentProps; const MediaVideo_ = ({ className, onLoaded, canLoad = true, src: mediaSrc, mimeType = 'video/mp4', ...props }: MediaVideoProps) => { const videoRef = useRef(null); const { locale } = useLayout(); const [src, setSrc] = useState(); useEffect(() => { if (videoRef.current && src) { const video = videoRef.current; const onReadyState = () => { if ( typeof onLoaded === 'function' && videoRef.current && videoRef.current.readyState && videoRef.current.readyState >= 2 ) { onLoaded(videoRef as React.RefObject); } }; if ( video.readyState && video.readyState >= 2 ) { onReadyState(); } else { video.addEventListener('loadeddata', onReadyState); return () => { video.removeEventListener('loadeddata', onReadyState); }; } } return () => { }; }, [videoRef, onLoaded, src]); const play = useCallback(() => { if (!videoRef.current) { return; } videoRef.current.play(); }, [videoRef]); const pause = () => { if (!videoRef.current) { return; } videoRef.current.pause(); }; const isIntersecting = useIntersectionObserver(videoRef, { threshold: 0, root: null, rootMargin: '0px', }); const shouldLoad = isIntersecting && canLoad; // handle intersection useEffect(() => { if (shouldLoad && src !== mediaSrc) { setSrc(mediaSrc); } }, [shouldLoad, src, mediaSrc]); const mounted = useMounted(); const id = useId(); const { reducedMotionLocal, toggleReducedMotionLocal, setReducedMotionLocal } = useReducedMotionLocal(); const shouldPlay = shouldLoad && mounted && !reducedMotionLocal; // handle shouldPlay useEffect(() => { if (shouldPlay) { play(); } else { pause(); } }, [shouldPlay, play]); const classNames = getClassNames(className, 'video', 'video--muted'); return ( <> {mounted && ( toggleReducedMotionLocal()} onBlur={() => setReducedMotionLocal(true)} > {reducedMotionLocal ? 'Play' : 'Pause'} )} {src && ( <> {mimeType && ( )} {locale && ( )} )} ); }; export const MediaVideo = memo(MediaVideo_);