diff --git a/packages/react/react/src/components/MuteButton.tsx b/packages/react/react/src/components/MuteButton.tsx index d1523333..fd33b78b 100644 --- a/packages/react/react/src/components/MuteButton.tsx +++ b/packages/react/react/src/components/MuteButton.tsx @@ -1,17 +1,5 @@ import { useMediaDispatch, useMediaSelector } from '@vjs-10/react-media-store'; import * as React from 'react'; -import type { ElementType, PropsWithChildren } from 'react'; - -type DefaultMuteButtonState = { volumeLevel: string; muted: boolean }; -type DefaultMuteButtonEventCallbacks = { - onmediamuterequest: (event: Pick) => void; - onmediaunmuterequest: (event: Pick) => void; -}; -type ComponentType = ElementType< - PropsWithChildren< - Partial - > ->; export const useMuteButtonState = (_props: any) => { /** @TODO Fix type issues with hooks (CJP) */ diff --git a/packages/react/react/src/components/PlayButton.tsx b/packages/react/react/src/components/PlayButton.tsx new file mode 100644 index 00000000..85121bb5 --- /dev/null +++ b/packages/react/react/src/components/PlayButton.tsx @@ -0,0 +1,98 @@ +import { useMediaDispatch, useMediaSelector } from '@vjs-10/react-media-store'; +import * as React from 'react'; + +export const usePlayButtonState = (_props: any) => { + /** @TODO Fix type issues with hooks (CJP) */ + const paused = useMediaSelector( + (state: any) => typeof state.mediaPaused !== 'boolean' || state.mediaPaused, + ) as boolean; + + const dispatch = useMediaDispatch(); + const requestPlay = React.useCallback(() => { + dispatch({ type: 'mediaplayrequest' }); + }, [dispatch]); + const requestPause = React.useCallback(() => { + dispatch({ type: 'mediapauserequest' }); + }, [dispatch]); + + return { + paused, + requestPlay, + requestPause, + } as const; +}; + +export type usePlayButtonState = typeof usePlayButtonState; +export type PlayButtonState = ReturnType; + +export const usePlayButtonProps = ( + props: React.PropsWithChildren<{ [k: string]: any }>, + state: ReturnType, +) => { + return { + /** data attributes/props */ + ['data-paused']: state.paused, + /** @TODO Need another state provider in core for i18n (CJP) */ + /** aria attributes/props */ + role: 'button', + ['aria-label']: state.paused ? 'play' : 'pause', + /** tooltip */ + ['data-tooltip']: state.paused ? 'Play' : 'Pause', + /** external props spread last to allow for overriding */ + ...props, + }; +}; + +export type usePlayButtonProps = typeof usePlayButtonProps; +type PlayButtonProps = ReturnType; + +export const renderPlayButton = ( + props: PlayButtonProps, + state: PlayButtonState, +) => { + return ( + + ); +}; + +export type renderPlayButton = typeof renderPlayButton; + +export const toConnectedComponent = ( + useStateHook: usePlayButtonState, + usePropsHook: usePlayButtonProps, + defaultRender: renderPlayButton, + displayName: string, +) => { + const ConnectedComponent = ({ + render = defaultRender, + ...props + }: PlayButtonProps & { render?: renderPlayButton }) => { + const connectedState = useStateHook(props); + const connectedProps = usePropsHook(props, connectedState); + return render(connectedProps, connectedState); + }; + + ConnectedComponent.displayName = displayName; + return ConnectedComponent; +}; + +export const PlayButton = toConnectedComponent( + usePlayButtonState, + usePlayButtonProps, + renderPlayButton, + 'PlayButton', +); +export default PlayButton; \ No newline at end of file diff --git a/packages/react/react/src/components/connected-with-defaults/PlayButton.tsx b/packages/react/react/src/components/connected-with-defaults/PlayButton.tsx deleted file mode 100644 index 0a55cd86..00000000 --- a/packages/react/react/src/components/connected-with-defaults/PlayButton.tsx +++ /dev/null @@ -1,31 +0,0 @@ -// NOTE: This is just a thin wrapper around the "skeletal" connected component that also applies a default (but overridable) definition of the -// "BaseComponent" that defines the actual UI. -// NOTE: Definitions like this should be able to be autogenerated via codegen, defined via a factory function (HoC or higher order component), or both. - -import * as React from 'react'; -// import { MediaPlayButton as BaseComponent } from 'media-chrome/react'; -import BaseComponent from '../ui/PlayButton'; -import ConnectedComponent from '../connected/PlayButton'; - -// NOTE: Assuming FC or "functional component" here for type expediency (though may be fine for our use cases). -type ConnectedComponentProps = Parameters[0]; -type ConnectedComponentReturnType = ReturnType; -type DefaultedProps = 'component'; -type ConnectedComponentWithDefaults = ( - props: Omit & - Partial> -) => ConnectedComponentReturnType; - -const Component: ConnectedComponentWithDefaults = ({ - component = BaseComponent, - children, - ...props -}) => { - return ( - - {children} - - ); -}; - -export default Component; diff --git a/packages/react/react/src/components/connected/PlayButton.tsx b/packages/react/react/src/components/connected/PlayButton.tsx deleted file mode 100644 index 9f938667..00000000 --- a/packages/react/react/src/components/connected/PlayButton.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import * as React from 'react'; -import { useMediaDispatch, useMediaSelector } from '@vjs-10/react-media-store'; -import type { CSSProperties, ElementType, PropsWithChildren } from 'react'; - -/** @TODO Export more types. Define more contracts (CJP) */ -type MediaCallbackType = ReturnType; - -type DefaultPlayButtonState = { mediaPaused: boolean }; -/** @TODO Support camel case deeply for callbacks. Define these as consts and types in core lib with clear relationships to event types (CJP) */ -type DefaultPlayButtonEventCallbacks = { - onmediaplayrequest: MediaCallbackType; - onmediapauserequest: MediaCallbackType; -}; -type ComponentType = ElementType< - PropsWithChildren< - Partial< - DefaultPlayButtonState & - DefaultPlayButtonEventCallbacks & { - className: string | undefined; - style: CSSProperties | undefined; - } - > - > ->; - -const PlayButton = ({ - component, - children, - ...props -}: PropsWithChildren<{ - component: ComponentType; - className?: string | undefined; - style?: CSSProperties | undefined; -}>) => { - const Component = component; - const dispatch = useMediaDispatch(); - const mediaPaused = useMediaSelector( - // @ts-ignore - State type issues - (state) => typeof state.mediaPaused !== 'boolean' || state.mediaPaused, - ); - console.log('mediaPaused', mediaPaused); - return ( - - {children} - - ); -}; - -export default PlayButton; diff --git a/packages/react/react/src/components/ui/PlayButton.tsx b/packages/react/react/src/components/ui/PlayButton.tsx deleted file mode 100644 index a46504a1..00000000 --- a/packages/react/react/src/components/ui/PlayButton.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import * as React from 'react'; -import type { ElementType, PropsWithChildren } from 'react'; - -type DefaultPlayButtonState = { mediaPaused: boolean }; -type DefaultPlayButtonEventCallbacks = { - onmediaplayrequest: (event: Pick) => void; - onmediapauserequest: (event: Pick) => void; -}; -type ComponentType = ElementType< - Partial< - PropsWithChildren - > ->; - -const PlayButton: ComponentType = ({ - mediaPaused, - onmediaplayrequest, - onmediapauserequest, - children, - ...props -}) => { - return ( - - ); -}; - -export default PlayButton; diff --git a/packages/react/react/src/skins/MediaSkinDefault.tsx b/packages/react/react/src/skins/MediaSkinDefault.tsx index b36e12c6..534d0840 100644 --- a/packages/react/react/src/skins/MediaSkinDefault.tsx +++ b/packages/react/react/src/skins/MediaSkinDefault.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { PauseIcon, PlayIcon } from '@vjs-10/react-icons'; -import PlayButton from '../components/connected-with-defaults/PlayButton'; +import PlayButton from '../components/PlayButton'; import MuteButton from '../components/MuteButton'; import { VolumeHighIcon, @@ -18,6 +18,7 @@ export const MediaSkinDefault: React.FC<{ children: React.ReactNode }> = ({
+ {/* @ts-ignore */}