1+ import {
2+ Card ,
3+ CardBody ,
4+ CardTitle ,
5+ Title ,
6+ } from "@patternfly/react-core" ;
7+ import React from "react" ;
8+
9+ interface VideoPlayerProps {
10+ id ?: string ;
11+ title : string ;
12+ video ?: string | null ;
13+ video_img ?: string | null ;
14+ className ?: string ;
15+ autoPlay ?: boolean ;
16+ controls ?: boolean ;
17+ width ?: string | number ;
18+ height ?: string | number ;
19+ }
20+
21+ const VideoPlayerWrapper : React . FC < VideoPlayerProps > = ( {
22+ id,
23+ title,
24+ video,
25+ video_img,
26+ className,
27+ autoPlay = false ,
28+ controls = true ,
29+ width = "100%" ,
30+ height = "auto" ,
31+ } ) => {
32+ // Extract video ID from YouTube URL for embedding
33+ const getYouTubeEmbedUrl = ( url : string ) => {
34+ // Match various YouTube URL formats
35+ let videoId = '' ;
36+
37+ // Standard YouTube URL: https://www.youtube.com/watch?v=VIDEO_ID
38+ const standardMatch = url . match ( / [ ? & ] v = ( [ ^ & \s ] { 11 } ) / ) ;
39+ if ( standardMatch ) {
40+ videoId = standardMatch [ 1 ] ;
41+ } else {
42+ // Short YouTube URL: https://youtu.be/VIDEO_ID
43+ const shortMatch = url . match ( / y o u t u \. b e \/ ( [ ^ ? \s ] { 11 } ) / ) ;
44+ if ( shortMatch ) {
45+ videoId = shortMatch [ 1 ] ;
46+ }
47+ }
48+
49+ if ( videoId ) {
50+ const autoPlayParam = autoPlay ? '&autoplay=1' : '' ;
51+ return `https://www.youtube.com/embed/${ videoId } ?rel=0${ autoPlayParam } ` ;
52+ }
53+ return url ;
54+ } ;
55+
56+ // Check if URL is a YouTube video
57+ const isYouTubeUrl = ( url : string ) => {
58+ return url . includes ( 'youtube.com' ) || url . includes ( 'youtu.be' ) ;
59+ } ;
60+
61+ const renderVideoContent = ( ) => {
62+ if ( video ) {
63+ if ( isYouTubeUrl ( video ) ) {
64+ // YouTube video embedding
65+ return (
66+ < div
67+ style = { {
68+ position : 'relative' ,
69+ paddingBottom : '56.25%' , // 16:9 aspect ratio
70+ height : 0 ,
71+ overflow : 'hidden' ,
72+ maxWidth : '100%' ,
73+ background : '#000' ,
74+ borderRadius : 'var(--pf-global--BorderRadius--sm)'
75+ } }
76+ >
77+ < iframe
78+ title = { title }
79+ src = { getYouTubeEmbedUrl ( video ) }
80+ style = { {
81+ position : 'absolute' ,
82+ top : 0 ,
83+ left : 0 ,
84+ width : '100%' ,
85+ height : '100%' ,
86+ border : 0
87+ } }
88+ allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
89+ referrerPolicy = "strict-origin-when-cross-origin"
90+ allowFullScreen
91+ />
92+ </ div >
93+ ) ;
94+ } else {
95+ // Direct video file
96+ return (
97+ < video
98+ src = { video }
99+ controls = { controls }
100+ autoPlay = { autoPlay }
101+ style = { {
102+ width,
103+ height,
104+ maxWidth : '100%' ,
105+ borderRadius : 'var(--pf-global--BorderRadius--sm)'
106+ } }
107+ title = { title }
108+ >
109+ Your browser does not support the video tag.
110+ </ video >
111+ ) ;
112+ }
113+ } else if ( video_img ) {
114+ // Show poster image when no video URL is provided
115+ return (
116+ < div style = { { textAlign : 'center' } } >
117+ < img
118+ src = { video_img }
119+ alt = { title }
120+ style = { {
121+ maxWidth : '100%' ,
122+ height : 'auto' ,
123+ borderRadius : 'var(--pf-global--BorderRadius--sm)' ,
124+ objectFit : 'cover' ,
125+ } }
126+ />
127+ </ div >
128+ ) ;
129+ }
130+
131+ // Fallback when neither video nor poster image is available
132+ return (
133+ < div
134+ style = { {
135+ textAlign : 'center' ,
136+ padding : '2rem' ,
137+ backgroundColor : 'var(--pf-global--BackgroundColor--200)' ,
138+ borderRadius : 'var(--pf-global--BorderRadius--sm)' ,
139+ color : 'var(--pf-global--Color--200)'
140+ } }
141+ >
142+ No video content available
143+ </ div >
144+ ) ;
145+ } ;
146+
147+ return (
148+ < Card
149+ id = { id }
150+ className = { className }
151+ style = { {
152+ maxWidth : "1440px" ,
153+ margin : "0 auto" ,
154+ width : "100%"
155+ } }
156+ >
157+ < CardTitle >
158+ < Title headingLevel = "h4" size = "lg" >
159+ { title }
160+ </ Title >
161+ </ CardTitle >
162+ < CardBody >
163+ { renderVideoContent ( ) }
164+ </ CardBody >
165+ </ Card >
166+ ) ;
167+ } ;
168+
169+ export default VideoPlayerWrapper ;
0 commit comments