elements
lifecycle
browser
- useAudio
- useBattery
- useBluetooth
- useBreakpoints
- useBroadcastChannel
- useBrowserLocation
- useClipboard
- useCopy
- useCssVar
- useDisplayMedia
- useDocumentEvent
- useDocumentTitle
- useDocumentVisibility
- useEventListener
- useEventSource
- useEyeDropper
- useFavicon
- useFileSystemAccess
- useFps
- useFullscreen
- useGamepad
- useGeolocation
- useMeasure
- useMediaControls
- useMediaQuery
- useMemory
- useNetwork
- useObjectUrl
- useOnline
- useOtpCredential
- usePermission
- usePictureInPicture
- usePointerLock
- usePostMessage
- useRaf
- useShare
- useSpeechRecognition
- useSpeechSynthesis
- useSticky
- useVibrate
- useVirtualKeyboard
- useWakeLock
- useWebSocket
utilities
state
- useBoolean
- useControllableState
- useCookie
- useCookies
- useCounter
- useCycleList
- useDefault
- useDisclosure
- useField
- useHash
- useList
- useLocalStorage
- useMap
- useMask
- useMergedRef
- useObject
- useOffsetPagination
- useQueue
- useRafState
- useRefState
- useSessionStorage
- useSet
- useStateHistory
- useStep
- useStorage
- useToggle
- useUrlSearchParam
- useUrlSearchParams
- useValidatedState
- useWizard
user
sensors
- useDeviceMotion
- useDeviceOrientation
- useHotkeys
- useIdle
- useInfiniteScroll
- useIntersectionObserver
- useKeyboard
- useKeyPress
- useKeysPressed
- useMouse
- useMutationObserver
- useOrientation
- usePageLeave
- useParallax
- usePerformanceObserver
- useResizeObserver
- useScroll
- useScrollIntoView
- useScrollTo
- useSwipe
- useTextSelection
- useVisibility
- useWindowEvent
- useWindowFocus
- useWindowScroll
- useWindowSize
API not supported, make sure to check for compatibility with different browsers when using this API
import { useDisplayMedia } from '@siberiacancode/reactuse';
import { MicIcon, MicOffIcon, MonitorUpIcon, PhoneOffIcon } from 'lucide-react';
import { useState } from 'react';
import { cn } from '@/utils/lib';
const PARTICIPANTS = [
{
id: 1,
name: 'siberiacancode',
initials: 'SC'
},
{
id: 2,
name: 'charmander',
avatar:
'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/4.png'
}
];
const Demo = () => {
const displayMedia = useDisplayMedia();
const [muted, setMuted] = useState(false);
if (!displayMedia.supported) {
return (
<p>
API not supported, make sure to check for compatibility with different browsers when using
this{' '}
<a
href='https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia'
rel='noreferrer'
target='_blank'
>
API
</a>
</p>
);
}
return (
<section className='flex w-[500px] flex-col gap-3 p-4'>
<div className='border-border flex flex-col overflow-hidden rounded-xl border bg-neutral-950'>
<div className='relative flex aspect-[24/9] items-center justify-center bg-black'>
<video
autoPlay
muted
playsInline
ref={displayMedia.ref}
className={cn('size-full object-contain p-2', !displayMedia.sharing && 'hidden')}
/>
{!displayMedia.sharing && (
<div className='grid size-full grid-cols-2 gap-2 p-2'>
{PARTICIPANTS.map((participant) => (
<div
key={participant.id}
className='flex flex-col items-center justify-center gap-2 rounded-lg bg-neutral-900 p-3'
>
{participant.initials && (
<div
className='size-12 bg-gradient-to-br from-neutral-700 to-neutral-900 text-sm font-semibold text-white'
data-slot='avatar'
>
<span data-slot='avatar-fallback'>{participant.initials}</span>
</div>
)}
{participant.avatar && (
<div className='size-12 bg-neutral-800' data-slot='avatar'>
<img
alt={participant.name}
className='object-cover'
data-slot='avatar-image'
src={participant.avatar}
/>
</div>
)}
<span className='text-xs font-medium text-white'>{participant.name}</span>
</div>
))}
</div>
)}
{displayMedia.sharing && (
<div className='absolute top-3 left-3 flex items-center gap-1.5 rounded-full border border-neutral-200 bg-white px-2.5 py-1 text-[10px] font-semibold text-neutral-900 shadow-sm'>
SHARING
</div>
)}
</div>
<div className='flex items-center justify-between gap-2 p-3'>
<button
aria-label={muted ? 'Unmute' : 'Mute'}
data-variant={muted ? 'destructive' : 'secondary'}
type='button'
onClick={() => setMuted((value) => !value)}
>
{muted ? <MicOffIcon className='size-4' /> : <MicIcon className='size-4' />}
</button>
<div className='flex items-center gap-2'>
<button
aria-label={displayMedia.sharing ? 'Stop sharing' : 'Share screen'}
data-variant={displayMedia.sharing ? 'destructive' : 'secondary'}
type='button'
onClick={displayMedia.sharing ? displayMedia.stop : displayMedia.start}
>
<MonitorUpIcon className='size-4' />
</button>
<button data-variant='destructive' type='button'>
<PhoneOffIcon className='size-4' />
End
</button>
</div>
</div>
</div>
</section>
);
};
export default Demo;
This hook uses mediaDevices.getDisplayMedia browser api to provide enhanced functionality. Make sure to check for compatibility with different browsers when using this api
Installation
pnpm add @siberiacancode/reactuseUsage
const { stream, sharing, start, stop } = useDisplayMedia(ref);
// or
const { ref, stream, sharing, start, stop } = useDisplayMedia<HTMLVideoElement>();Type Declarations
import type { HookTarget } from '@/utils/helpers';
import type { StateRef } from '../useRefState/useRefState';
export interface UseDisplayMediaReturn {
/** Whether screen sharing is currently active */
sharing: boolean;
/** The media stream object */
stream: MediaStream | null;
/** Whether the display media API is supported */
supported: boolean;
/** Start screen sharing */
start: () => Promise<void>;
/** Stop screen sharing */
stop: () => void;
}
export interface UseDisplayMediaOptions {
/** Whether to enable audio sharing */
audio?: boolean | MediaTrackConstraints;
/** Whether to start immediately */
immediately?: boolean;
/** Whether to enable video sharing */
video?: boolean | MediaTrackConstraints;
}
export interface UseDisplayMedia {
(target: HookTarget, options?: UseDisplayMediaOptions): UseDisplayMediaReturn;
<Target extends HTMLVideoElement>(
options?: UseDisplayMediaOptions,
target?: never
): { ref: StateRef<Target> } & UseDisplayMediaReturn;
}API
Parameters
| Name | Type | Default | Note |
|---|---|---|---|
| target | HookTarget | - | The target video element to display the media stream |
| options.audio | boolean | MediaTrackConstraints | - | Whether to enable audio sharing |
| options.immediately | boolean | false | Whether to start immediately |
| options.video | boolean | MediaTrackConstraints | - | Whether to enable video sharing |
Returns
UseDisplayMediaReturnParameters
| Name | Type | Default | Note |
|---|---|---|---|
| options.audio | boolean | MediaTrackConstraints | - | Whether to enable audio sharing |
| options.immediately | boolean | false | Whether to start immediately |
| options.video | boolean | MediaTrackConstraints | - | Whether to enable video sharing |
Returns
UseDisplayMediaReturn & { ref: StateRef<HTMLVideoElement> }Contributors
ddebabin
Last updated on