Spaces:
Sleeping
Sleeping
| import React from 'react'; | |
| /** | |
| * Extracts YouTube video ID from various URL formats | |
| * Supports: | |
| * - https://www.youtube.com/watch?v=VIDEO_ID | |
| * - https://youtu.be/VIDEO_ID | |
| * - https://www.youtube.com/embed/VIDEO_ID | |
| * - Direct VIDEO_ID | |
| */ | |
| function extractVideoId(url) { | |
| if (!url) return null; | |
| // If it's already just an ID (no URL) | |
| if (!url.includes('http') && !url.includes('youtube') && !url.includes('youtu.be')) { | |
| return url; | |
| } | |
| // Extract from various YouTube URL formats | |
| const patterns = [ | |
| /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/, | |
| /^([a-zA-Z0-9_-]{11})$/ // Direct ID | |
| ]; | |
| for (const pattern of patterns) { | |
| const match = url.match(pattern); | |
| if (match && match[1]) { | |
| return match[1]; | |
| } | |
| } | |
| return null; | |
| } | |
| export default function YouTubeEmbed({ url, title = 'Project walkthrough video' }) { | |
| const videoId = extractVideoId(url); | |
| if (!videoId) { | |
| return null; | |
| } | |
| const embedUrl = `https://www.youtube.com/embed/${videoId}?rel=0&modestbranding=1`; | |
| return ( | |
| <section className="mt-8" aria-labelledby="walkthrough-heading"> | |
| <h2 id="walkthrough-heading" className="h3 mb-4">Walkthrough Video</h2> | |
| <div className="relative aspect-video overflow-hidden rounded-xl bg-slate-100"> | |
| <iframe | |
| src={embedUrl} | |
| title={title} | |
| allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" | |
| allowFullScreen | |
| className="absolute inset-0 w-full h-full" | |
| loading="lazy" | |
| /> | |
| </div> | |
| </section> | |
| ); | |
| } | |