diff --git a/packages/react/react/src/components/FullscreenButton.tsx b/packages/react/react/src/components/FullscreenButton.tsx new file mode 100644 index 00000000..5b51d94e --- /dev/null +++ b/packages/react/react/src/components/FullscreenButton.tsx @@ -0,0 +1,89 @@ +import { + shallowEqual, + useMediaSelector, + useMediaStore, +} from '@vjs-10/react-media-store'; +import * as React from 'react'; +import { toConnectedComponent } from '../utils/component-factory'; +import { fullscreenButtonStateDefinition } from '@vjs-10/media-store'; + +export const useFullscreenButtonState = (_props: any) => { + const mediaStore = useMediaStore(); + /** @TODO Fix type issues with hooks (CJP) */ + const mediaState = useMediaSelector( + fullscreenButtonStateDefinition.stateTransform, + shallowEqual, + ); + + const methods = React.useMemo( + () => fullscreenButtonStateDefinition.createRequestMethods(mediaStore.dispatch), + [mediaStore], + ); + + return { + fullscreen: mediaState.fullscreen, + requestEnterFullscreen: methods.requestEnterFullscreen, + requestExitFullscreen: methods.requestExitFullscreen, + } as const; +}; + +export type useFullscreenButtonState = typeof useFullscreenButtonState; +export type FullscreenButtonState = ReturnType; + +export const useFullscreenButtonProps = ( + props: React.PropsWithChildren<{ [k: string]: any }>, + state: ReturnType, +) => { + const baseProps: Record = { + /** @TODO Need another state provider in core for i18n (CJP) */ + /** aria attributes/props */ + role: 'button', + ['aria-label']: state.fullscreen ? 'exit fullscreen' : 'enter fullscreen', + /** tooltip */ + ['data-tooltip']: state.fullscreen ? 'Exit Fullscreen' : 'Enter Fullscreen', + /** external props spread last to allow for overriding */ + ...props, + }; + + // Handle boolean data attribute: present with empty string when true, absent when false + if (state.fullscreen) { + baseProps['data-fullscreen'] = ''; + } + + return baseProps; +}; + +export type useFullscreenButtonProps = typeof useFullscreenButtonProps; +type FullscreenButtonProps = ReturnType; + +export const renderFullscreenButton = ( + props: FullscreenButtonProps, + state: FullscreenButtonState, +) => { + return ( + + ); +}; + +export type renderFullscreenButton = typeof renderFullscreenButton; + +export const FullscreenButton = toConnectedComponent( + useFullscreenButtonState, + useFullscreenButtonProps, + renderFullscreenButton, + 'FullscreenButton', +); +export default FullscreenButton; \ No newline at end of file diff --git a/packages/react/react/src/index.tsx b/packages/react/react/src/index.tsx index 67a269f6..1c84c0d6 100644 --- a/packages/react/react/src/index.tsx +++ b/packages/react/react/src/index.tsx @@ -7,4 +7,5 @@ export { Video, MediaElementVideo } from './components/Video'; // New hook-style components export { PlayButton } from './components/PlayButton'; export { MuteButton } from './components/MuteButton'; -export { VolumeRange } from './components/VolumeRange'; \ No newline at end of file +export { VolumeRange } from './components/VolumeRange'; +export { FullscreenButton } from './components/FullscreenButton'; \ No newline at end of file