diff --git a/.changeset/fresh-cars-type.md b/.changeset/fresh-cars-type.md new file mode 100644 index 000000000..6c8d57e0d --- /dev/null +++ b/.changeset/fresh-cars-type.md @@ -0,0 +1,5 @@ +--- +"nextjs-website": minor +--- + +Implement "stop" video function diff --git a/apps/nextjs-website/react-components/components/VideoImage/VideoImage.helpers.tsx b/apps/nextjs-website/react-components/components/VideoImage/VideoImage.helpers.tsx index eb50d1c29..062a75c9f 100644 --- a/apps/nextjs-website/react-components/components/VideoImage/VideoImage.helpers.tsx +++ b/apps/nextjs-website/react-components/components/VideoImage/VideoImage.helpers.tsx @@ -20,6 +20,7 @@ export const renderVideo = ({ loop, autoplay, fallback, + onClick, onVideoEnd, }: RenderVideoProps) => { // Determine the type based on the structure of src @@ -46,6 +47,7 @@ export const renderVideo = ({ loop={loop} autoPlay={autoplay} onEnded={onVideoEnd} + onClick={onClick} style={{ overflow: 'hidden', width: '100%', diff --git a/apps/nextjs-website/react-components/components/VideoImage/VideoImage.tsx b/apps/nextjs-website/react-components/components/VideoImage/VideoImage.tsx index 48e4d2b81..cab4240e4 100644 --- a/apps/nextjs-website/react-components/components/VideoImage/VideoImage.tsx +++ b/apps/nextjs-website/react-components/components/VideoImage/VideoImage.tsx @@ -23,12 +23,13 @@ const VideoImage = (props: VideoImageProps) => { theme, fallback, playButtonLabel, + pausedplayButtonLabel, isCentered = false, } = props; const videoRef = useRef(null); const isVisible = useIsVisible(videoRef); const [error, setError] = useState(false); - const [isPlaying, setIsPlaying] = useState(false); + const [videoState, setVideoState] = useState<'playing' | 'paused' | 'stopped'>('stopped'); const textColor = TextColor(theme); @@ -41,15 +42,25 @@ const VideoImage = (props: VideoImageProps) => { }, [isVisible]); const play = (e?: React.MouseEvent) => { - try { - e?.preventDefault(); - videoRef.current?.play(); - setIsPlaying(true); - } catch (error) {} + e?.preventDefault(); + if (videoRef.current) { + videoRef.current.play().then(() => { + setVideoState('playing'); + }).catch(() => { + // Handle play error + }); + } }; const handleVideoEnd = () => { - setIsPlaying(false); + setVideoState('stopped'); + }; + + const pause = () => { + if (videoRef.current) { + videoRef.current.pause(); + setVideoState('paused'); + } }; const isImage = (src: string) => { @@ -67,7 +78,7 @@ const VideoImage = (props: VideoImageProps) => {
- {!full && !isPlaying && ( + {!full && videoState !== 'playing' && (
{ zIndex: 50, }} > - + {videoState === 'stopped' && ( + + )} {typeof src === 'string' ? !isImage(src) && isVideo(src) && ( @@ -124,7 +137,7 @@ const VideoImage = (props: VideoImageProps) => { alignSelf: 'flex-start', }} > - {playButtonLabel} + {videoState === 'paused' ? pausedplayButtonLabel : playButtonLabel}

{ alignSelf: 'flex-start', }} > - {playButtonLabel} + {videoState === 'paused' ? pausedplayButtonLabel : playButtonLabel}

{ autoplay, fallback, onVideoEnd: handleVideoEnd, + onClick: pause, }) : isImage(src.url) ? renderImage({ @@ -204,6 +218,7 @@ const VideoImage = (props: VideoImageProps) => { autoplay, fallback, onVideoEnd: handleVideoEnd, + onClick: pause, })}
{caption && ( @@ -217,4 +232,4 @@ const VideoImage = (props: VideoImageProps) => { ); }; -export default VideoImage; +export default VideoImage; \ No newline at end of file diff --git a/apps/nextjs-website/react-components/types/VideoImage/VideoImage.types.ts b/apps/nextjs-website/react-components/types/VideoImage/VideoImage.types.ts index 75f81c994..3cd11f239 100644 --- a/apps/nextjs-website/react-components/types/VideoImage/VideoImage.types.ts +++ b/apps/nextjs-website/react-components/types/VideoImage/VideoImage.types.ts @@ -12,6 +12,7 @@ export interface VideoImageProps extends CommonProps { reverse?: boolean; fallback?: string; playButtonLabel?: string; + pausedplayButtonLabel?: string; isCentered: boolean; } @@ -34,6 +35,7 @@ export interface RenderVideoProps { autoplay: boolean; onVideoEnd: () => void; fallback: React.ReactNode; + onClick?: () => void; } // Define TypeScript types for ImageProps diff --git a/apps/nextjs-website/src/lib/fetch/types/PageSection.ts b/apps/nextjs-website/src/lib/fetch/types/PageSection.ts index 41f3408e4..4ce8075f3 100644 --- a/apps/nextjs-website/src/lib/fetch/types/PageSection.ts +++ b/apps/nextjs-website/src/lib/fetch/types/PageSection.ts @@ -254,6 +254,7 @@ const VideoImageSectionCodec = t.strict({ theme: t.union([t.literal('light'), t.literal('dark')]), fallback: t.string, playButtonLabel: t.string, + pausedplayButtonLabel: t.string, sectionID: t.union([t.string, t.null]), isCentered: t.boolean, }); diff --git a/apps/nextjs-website/stories/VideoImage/videoImageCommons.tsx b/apps/nextjs-website/stories/VideoImage/videoImageCommons.tsx index cf44f4d98..66bb59553 100644 --- a/apps/nextjs-website/stories/VideoImage/videoImageCommons.tsx +++ b/apps/nextjs-website/stories/VideoImage/videoImageCommons.tsx @@ -13,6 +13,7 @@ const createVideoImageDefaults = (theme: 'dark' | 'light') => ({ theme, fallback: 'Ops! Something went wrong... Please try again later.', playButtonLabel: 'Watch the video', + pausedplayButtonLabel: 'Resume video', }); // Usage example