From 9e75eb93cdb8bf94e6477c939e9fe46871e80de4 Mon Sep 17 00:00:00 2001 From: winoffrg <61311751+WINOFFRG@users.noreply.github.com> Date: Sun, 23 Aug 2026 15:33:46 +0530 Subject: [PATCH] feat: exclusive playback provider --- apps/www/app/(home)/page.tsx | 5 +- .../ui/exclusive-playback-provider.tsx | 65 +++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 apps/www/registry/default/ui/exclusive-playback-provider.tsx diff --git a/apps/www/app/(home)/page.tsx b/apps/www/app/(home)/page.tsx index bd0d4683..0a585e0d 100644 --- a/apps/www/app/(home)/page.tsx +++ b/apps/www/app/(home)/page.tsx @@ -8,6 +8,7 @@ import { HomeNoscriptContent } from "@/components/home-noscript-content" import { ImmersiveScrollPlayer } from "@/components/immersive-scroll-player" import { VideoPlayerContainer } from "@/components/players/video-player/player-container" import { ScrollIndicator } from "@/components/scroll-indicator" +import { ExclusivePlaybackProvider } from "@/registry/default/ui/exclusive-playback-provider" export const metadata: Metadata = { alternates: { @@ -17,7 +18,7 @@ export const metadata: Metadata = { export default function Home() { return ( - <> + @@ -100,6 +101,6 @@ export default function Home() { `} /> - + ) } diff --git a/apps/www/registry/default/ui/exclusive-playback-provider.tsx b/apps/www/registry/default/ui/exclusive-playback-provider.tsx new file mode 100644 index 00000000..12d3bef8 --- /dev/null +++ b/apps/www/registry/default/ui/exclusive-playback-provider.tsx @@ -0,0 +1,65 @@ +"use client" + +import { Slot } from "@radix-ui/react-slot" +import * as React from "react" + +export interface ExclusivePlaybackProviderProps extends React.ComponentPropsWithoutRef<"div"> { + asChild?: boolean +} + +export const ExclusivePlaybackProvider = React.forwardRef< + HTMLDivElement, + ExclusivePlaybackProviderProps +>(function ExclusivePlaybackProvider( + { asChild, onEndedCapture, onPauseCapture, onPlayCapture, ...props }, + forwardedRef +) { + const activeMediaRef = React.useRef(null) + const Component = asChild ? Slot : "div" + + const handlePlayCapture = (event: React.SyntheticEvent) => { + onPlayCapture?.(event) + if (event.defaultPrevented) return + + const mediaElement = getMediaElement(event) + if (!mediaElement || activeMediaRef.current === mediaElement) return + + activeMediaRef.current?.pause() + activeMediaRef.current = mediaElement + } + + const releaseMedia = (event: React.SyntheticEvent) => { + const mediaElement = getMediaElement(event) + if (activeMediaRef.current === mediaElement) { + activeMediaRef.current = null + } + } + + const handlePauseCapture = (event: React.SyntheticEvent) => { + onPauseCapture?.(event) + if (!event.defaultPrevented) releaseMedia(event) + } + + const handleEndedCapture = (event: React.SyntheticEvent) => { + onEndedCapture?.(event) + if (!event.defaultPrevented) releaseMedia(event) + } + + return ( + + ) +}) + +ExclusivePlaybackProvider.displayName = "ExclusivePlaybackProvider" + +function getMediaElement( + event: React.SyntheticEvent +): HTMLMediaElement | null { + return event.target instanceof HTMLMediaElement ? event.target : null +}