import type { Context, ReactNode } from 'react';
import React, { createContext, useContext, useEffect, useMemo } from 'react';
import {
AvailabilityStates,
MediaUIEvents,
MediaUIProps,
StreamTypes,
VolumeLevels,
} from '../constants.js';
import createMediaStore, {
type MediaState,
type MediaStore,
} from '../media-store/media-store.js';
import type {
FullScreenElementStateOwner,
MediaStateOwner,
} from '../media-store/state-mediator.js';
import { useSyncExternalStoreWithSelector } from './useSyncExternalStoreWithSelector.js';
export * as timeUtils from '../utils/time.js';
/**
* @description A lookup object for all well-defined action types that can be dispatched
* to the `MediaStore`. As each action type name suggests, these all take the form of
* "state change requests," where e.g. a component will `dispatch()` a request to change
* some bit of media state, typically due to some user interaction.
*
* @example
* import { useDispatch, MediaActionTypes } from 'media-chrome/react/media-store';
*
* const MyComponent = () => {
* const dispatch = useDispatch();
* return (
*
* );
* };
*
* @see {@link useMediaDispatch}
*/
export { MediaState };
export { AvailabilityStates, StreamTypes, VolumeLevels };
const {
REGISTER_MEDIA_STATE_RECEIVER, // eslint-disable-line
UNREGISTER_MEDIA_STATE_RECEIVER, // eslint-disable-line
// NOTE: These generic state change requests are not currently supported (CJP)
MEDIA_SHOW_TEXT_TRACKS_REQUEST, // eslint-disable-line
MEDIA_HIDE_TEXT_TRACKS_REQUEST, // eslint-disable-line
...StateChangeRequests
} = MediaUIEvents;
export const MediaActionTypes = {
...StateChangeRequests,
MEDIA_ELEMENT_CHANGE_REQUEST: 'mediaelementchangerequest',
FULLSCREEN_ELEMENT_CHANGE_REQUEST: 'fullscreenelementchangerequest',
} as const;
export const MediaStateNames = { ...MediaUIProps } as const;
const identity = (x?: any) => x;
/**
* @description The {@link https://react.dev/learn/passing-data-deeply-with-context#context-an-alternative-to-passing-props|React Context}
* used "under the hood" for media ui state updates, state change requests, and the hooks and providers that integrate with this context.
* It is unlikely that you will/should be using `MediaContext` directly.
*
* @see {@link MediaProvider}
* @see {@link useMediaDispatch}
* @see {@link useMediaSelector}
*/
export const MediaContext: Context =
createContext(null);
/**
* @description A {@link https://react.dev/reference/react/createContext#provider|React Context.Provider} for having access
* to media state and state updates. While many other react libraries that rely on `` and its corresponding context/hooks
* are expected to have the context close to the top of the
* {@link https://react.dev/learn/understanding-your-ui-as-a-tree#the-render-tree|React render tree}, `` should
* typically be declared closer to the component (e.g. ``) level, as it manages the media state for a particular
* playback experience (visual and otherwise), typically tightly tied to e.g. an `` or `` component (or similar).
* This state is tied together and managed by using {@link https://react.dev/learn/manipulating-the-dom-with-refs|DOM element Refs} to
* e.g. the corresponding `` element, which is made easy by our specialized hooks such as {@link useMediaRef}.
*
* @example
* import {
* MediaProvider,
* useMediaFullscreenRef,
* useMediaRef
* } from 'media-chrome/react/media-store';
* import MyFancyPlayButton from './MyFancyPlayButton';
*
* const MyFancyVideoPlayerContainer = ({ src }: { src: string }) => {
* const mediaFullscreenRef = useMediaFullscreenRef();
* const mediaRef = useMediaRef();
* return (
*