yet-another-react-lightbox
Advanced tools
Comparing version 1.4.1 to 1.5.0
@@ -1,3 +0,3 @@ | ||
/// <reference types="react" /> | ||
import { Plugin } from "../types.js"; | ||
import * as React from "react"; | ||
import { LightboxProps, Plugin } from "../types.js"; | ||
/** Video slide attributes */ | ||
@@ -13,2 +13,22 @@ export interface SlideVideo { | ||
height?: number; | ||
/** if `true`, the video automatically begins to play */ | ||
autoPlay?: boolean; | ||
/** if `true`, the browser will offer controls to allow the user to control video playback */ | ||
controls?: boolean; | ||
/** indicates what controls to show */ | ||
controlsList?: string; | ||
/** indicates whether to use CORS to fetch the related video */ | ||
crossOrigin?: string; | ||
/** video preload setting */ | ||
preload?: string; | ||
/** if `true`, the browser will automatically seek back to the start upon reaching the end of the video */ | ||
loop?: boolean; | ||
/** the default setting of the audio contained in the video */ | ||
muted?: boolean; | ||
/** if `true`, the video is to be played "inline", that is within the element's playback area. */ | ||
playsInline?: boolean; | ||
/** prevents the browser from suggesting a Picture-in-Picture context menu */ | ||
disablePictureInPicture?: boolean; | ||
/** disables the capability of remote playback */ | ||
disableRemotePlayback?: boolean; | ||
/** an array of video files */ | ||
@@ -27,9 +47,15 @@ sources?: { | ||
} | ||
interface LightboxProps { | ||
/** video plugin settings */ | ||
video?: Pick<SlideVideo, "autoPlay" | "controls" | "controlsList" | "crossOrigin" | "preload" | "loop" | "muted" | "playsInline" | "disablePictureInPicture" | "disableRemotePlayback">; | ||
} | ||
} | ||
declare type VideoSlideProps = Required<Pick<LightboxProps, "video">> & { | ||
slide: SlideVideo; | ||
offset: number; | ||
}; | ||
/** Video slide */ | ||
export declare const VideoSlide: ({ slide: { sources, poster, width, height } }: { | ||
slide: SlideVideo; | ||
}) => JSX.Element; | ||
export declare const VideoSlide: React.FC<VideoSlideProps>; | ||
/** Video plugin */ | ||
export declare const Video: Plugin; | ||
export default Video; |
import * as React from "react"; | ||
import PropTypes from "prop-types"; | ||
import { SlideTypesPropTypes } from "../types.js"; | ||
import { clsx, cssClass, useContainerRect } from "../core/index.js"; | ||
import { clsx, cssClass, useContainerRect, useLatest } from "../core/index.js"; | ||
SlideTypesPropTypes.push(PropTypes.shape({ | ||
@@ -10,2 +10,12 @@ type: PropTypes.oneOf(["video"]).isRequired, | ||
height: PropTypes.number, | ||
autoPlay: PropTypes.bool, | ||
controls: PropTypes.bool, | ||
controlsList: PropTypes.string, | ||
crossOrigin: PropTypes.string, | ||
preload: PropTypes.string, | ||
loop: PropTypes.bool, | ||
muted: PropTypes.bool, | ||
playsInline: PropTypes.bool, | ||
disablePictureInPicture: PropTypes.bool, | ||
disableRemotePlayback: PropTypes.bool, | ||
sources: PropTypes.arrayOf(PropTypes.shape({ | ||
@@ -16,4 +26,28 @@ src: PropTypes.string.isRequired, | ||
})); | ||
export const VideoSlide = ({ slide: { sources, poster, width, height } }) => { | ||
export const VideoSlide = ({ slide, video, offset }) => { | ||
const { setContainerRef, containerRect } = useContainerRect(); | ||
const videoRef = React.useRef(null); | ||
React.useEffect(() => { | ||
if (offset !== 0 && videoRef.current && !videoRef.current.paused) { | ||
videoRef.current.pause(); | ||
} | ||
}, [offset]); | ||
React.useEffect(() => { | ||
if (offset === 0 && videoRef.current && (slide.autoPlay || video.autoPlay)) { | ||
videoRef.current.play().catch(() => { }); | ||
} | ||
}, [offset, video.autoPlay, slide.autoPlay]); | ||
const latestOffset = useLatest(offset); | ||
const latestVideoAutoPlay = useLatest(video.autoPlay); | ||
const latestSlideAutoPlay = useLatest(slide.autoPlay); | ||
const setVideoRef = React.useCallback((el) => { | ||
videoRef.current = el; | ||
if (el && | ||
latestOffset.current === 0 && | ||
(latestVideoAutoPlay.current || latestSlideAutoPlay.current) && | ||
el.paused) { | ||
el.play().catch(() => { }); | ||
} | ||
}, [latestOffset, latestVideoAutoPlay, latestSlideAutoPlay]); | ||
const { width, height, poster, sources } = slide; | ||
const scaleWidthAndHeight = () => { | ||
@@ -28,2 +62,19 @@ if (!width || !height || !containerRect) | ||
}; | ||
const resolveBoolean = (attr) => { | ||
if (slide[attr] === false) | ||
return null; | ||
if (slide[attr] === true) | ||
return { [attr]: true }; | ||
if (video[attr] === false) | ||
return null; | ||
if (video[attr] === true) | ||
return { [attr]: true }; | ||
return null; | ||
}; | ||
const resolveString = (attr) => { | ||
if (video[attr] || slide[attr]) { | ||
return { [attr]: slide[attr] || video[attr] }; | ||
} | ||
return null; | ||
}; | ||
return (React.createElement(React.Fragment, null, sources && (React.createElement("div", { ref: setContainerRef, style: { | ||
@@ -33,18 +84,26 @@ width: "100%", | ||
...(width ? { maxWidth: `${width}px` } : null), | ||
}, className: clsx(cssClass("video_container"), cssClass("flex_center")) }, containerRect && (React.createElement("video", { controls: true, playsInline: true, poster: poster, ...scaleWidthAndHeight() }, sources.map(({ src, type }, index) => (React.createElement("source", { key: index, src: src, type: type }))))))))); | ||
}, className: clsx(cssClass("video_container"), cssClass("flex_center")) }, containerRect && (React.createElement("video", { ref: setVideoRef, poster: poster, ...scaleWidthAndHeight(), ...resolveBoolean("controls"), ...resolveBoolean("playsInline"), ...resolveBoolean("loop"), ...resolveBoolean("muted"), ...resolveBoolean("playsInline"), ...resolveBoolean("disablePictureInPicture"), ...resolveBoolean("disableRemotePlayback"), ...resolveString("controlsList"), ...resolveString("crossOrigin"), ...resolveString("preload") }, sources.map(({ src, type }, index) => (React.createElement("source", { key: index, src: src, type: type }))))))))); | ||
}; | ||
export const Video = ({ augment }) => { | ||
augment(({ render: { slide: renderSlide, ...restRender }, ...restProps }) => ({ | ||
render: { | ||
slide: (slide, offset, rect) => { | ||
if ("type" in slide && slide.type === "video") { | ||
return React.createElement(VideoSlide, { slide: slide }); | ||
} | ||
return renderSlide === null || renderSlide === void 0 ? void 0 : renderSlide(slide, offset, rect); | ||
augment(({ render: { slide: renderSlide, ...restRender }, video: originalVideo, ...restProps }) => { | ||
const video = { | ||
controls: true, | ||
playsInline: true, | ||
...originalVideo, | ||
}; | ||
return { | ||
render: { | ||
slide: (slide, offset, rect) => { | ||
if ("type" in slide && slide.type === "video") { | ||
return React.createElement(VideoSlide, { slide: slide, video: video, offset: offset }); | ||
} | ||
return renderSlide === null || renderSlide === void 0 ? void 0 : renderSlide(slide, offset, rect); | ||
}, | ||
...restRender, | ||
}, | ||
...restRender, | ||
}, | ||
...restProps, | ||
})); | ||
video, | ||
...restProps, | ||
}; | ||
}); | ||
}; | ||
export default Video; |
{ | ||
"name": "yet-another-react-lightbox", | ||
"version": "1.4.1", | ||
"version": "1.5.0", | ||
"description": "Modern React lightbox component", | ||
@@ -5,0 +5,0 @@ "author": "Igor Danchenko", |
96975
2068