diff --git a/packages/html/html/src/components/media-mute-button.ts b/packages/html/html/src/components/media-mute-button.ts
index caf0761d..35bbbb12 100644
--- a/packages/html/html/src/components/media-mute-button.ts
+++ b/packages/html/html/src/components/media-mute-button.ts
@@ -5,21 +5,21 @@ import {
} from '../utils/component-factory';
import { MediaChromeButton } from './media-chrome-button';
-export class MediaMuteButton extends MediaChromeButton {
+export class MuteButtonBase extends MediaChromeButton {
_state:
| {
muted: boolean;
volumeLevel: string;
- requestUnmute: () => void;
requestMute: () => void;
+ requestUnmute: () => void;
}
| undefined;
handleEvent(event: Event) {
const { type } = event;
- if (type === 'click') {
- const state = this._state;
- if (state) {
+ const state = this._state;
+ if (state) {
+ if (type === 'click') {
if (state.muted) {
state.requestUnmute();
} else {
@@ -39,6 +39,7 @@ export class MediaMuteButton extends MediaChromeButton {
_update(props: any, state: any) {
this._state = state;
+ /** @TODO Follow up with React vs. W.C. data-* attributes discrepancies (CJP) */
// Make generic
this.toggleAttribute('data-muted', props['data-muted']);
this.setAttribute('data-volume-level', props['data-volume-level']);
@@ -102,7 +103,7 @@ export const useMuteButtonProps: PropsHook<{
* Equivalent to React's MuteButton = toConnectedComponent(...)
*/
export const MuteButton = toConnectedHTMLComponent(
- MediaMuteButton,
+ MuteButtonBase,
useMuteButtonState,
useMuteButtonProps,
'MuteButton',
diff --git a/packages/react/react/src/components/MuteButton.tsx b/packages/react/react/src/components/MuteButton.tsx
index 07e92688..0db7a677 100644
--- a/packages/react/react/src/components/MuteButton.tsx
+++ b/packages/react/react/src/components/MuteButton.tsx
@@ -1,27 +1,58 @@
-import { useMediaDispatch, useMediaSelector } from '@vjs-10/react-media-store';
+import {
+ shallowEqual,
+ // useMediaDispatch,
+ useMediaSelector,
+ useMediaStore,
+} from '@vjs-10/react-media-store';
import * as React from 'react';
import { toConnectedComponent } from '../utils/component-factory';
-export const useMuteButtonState = (_props: any) => {
- /** @TODO Fix type issues with hooks (CJP) */
- const volumeLevel = useMediaSelector(
- (state: any) => state.volumeLevel,
- ) as string;
- const muted = useMediaSelector((state: any) => state.muted) as boolean;
+/**
+ * MuteButton state hook - equivalent to React's useMuteButtonState
+ * Handles media store state subscription and transformation
+ */
+export const muteButtonStateDef = {
+ keys: ['muted', 'volumeLevel'],
+ stateTransform: (rawState: any) => ({
+ muted: rawState.muted ?? false,
+ volumeLevel: rawState.volumeLevel ?? 'off',
+ }),
+ /** @TODO Consider "promoting" this up to state-mediator defs + media store (CJP) */
+ requestMethods: (mediaStore: ReturnType) => {
+ return {
+ requestMute() {
+ const type = 'muterequest';
+ mediaStore.dispatch({ type });
+ },
+ requestUnmute() {
+ const type = 'unmuterequest';
+ mediaStore.dispatch({ type });
+ },
+ };
+ },
+} as const;
- const dispatch = useMediaDispatch();
- const requestMute = React.useCallback(() => {
- dispatch({ type: 'muterequest' });
- }, [dispatch]);
- const requestUnmute = React.useCallback(() => {
- dispatch({ type: 'unmuterequest' });
- }, [dispatch]);
+export const useMuteButtonState = (_props: any) => {
+ const mediaStore = useMediaStore();
+ /** @TODO Fix type issues with hooks (CJP) */
+ const mediaState = useMediaSelector(
+ muteButtonStateDef.stateTransform,
+ shallowEqual,
+ );
+
+ const [methods, setMethods] = React.useState(
+ muteButtonStateDef.requestMethods(mediaStore),
+ );
+
+ React.useEffect(() => {
+ setMethods(muteButtonStateDef.requestMethods(mediaStore));
+ }, [mediaStore]);
return {
- volumeLevel,
- muted,
- requestMute,
- requestUnmute,
+ volumeLevel: mediaState.volumeLevel,
+ muted: mediaState.muted,
+ requestMute: methods.requestMute,
+ requestUnmute: methods.requestUnmute,
} as const;
};