@clockworkdog/cogs-client-react 3.0.0-alpha.2 → 3.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,10 @@
1
+ import { CogsVideoPlayer } from '@clockworkdog/cogs-client';
2
+ import React, { ReactNode } from 'react';
3
+ export default function VideoContainer({ className, style, videoPlayer: customVideoPlayer, fullscreen, }: {
4
+ className?: string;
5
+ style?: React.CSSProperties;
6
+ videoPlayer?: CogsVideoPlayer | null;
7
+ fullscreen?: boolean | {
8
+ style: React.CSSProperties;
9
+ };
10
+ }): ReactNode;
@@ -0,0 +1,16 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+ import { useVideoPlayer } from '../providers/CogsConnectionProvider';
3
+ export default function VideoContainer({ className, style, videoPlayer: customVideoPlayer, fullscreen, }) {
4
+ const containerRef = useRef(null);
5
+ const videoPlayer = useVideoPlayer(customVideoPlayer ?? undefined);
6
+ useEffect(() => {
7
+ if (videoPlayer && containerRef.current) {
8
+ videoPlayer.setParentElement(containerRef.current);
9
+ return () => videoPlayer.resetParentElement();
10
+ }
11
+ }, [videoPlayer]);
12
+ const fullscreenCustomStyle = typeof fullscreen === 'object' ? fullscreen.style : style;
13
+ return (React.createElement("div", { ref: containerRef, className: className, style: fullscreen
14
+ ? { position: 'absolute', zIndex: 1, top: 0, left: 0, width: '100vw', height: '100vh', ...fullscreenCustomStyle }
15
+ : { position: 'relative', ...style } }));
16
+ }
@@ -0,0 +1,4 @@
1
+ import { AudioClip, CogsAudioPlayer } from '@clockworkdog/cogs-client';
2
+ export default function useAudioClips(audioPlayer: CogsAudioPlayer | null): {
3
+ [path: string]: AudioClip;
4
+ };
@@ -0,0 +1,10 @@
1
+ import { useEffect, useState } from 'react';
2
+ export default function useAudioClips(audioPlayer) {
3
+ const [audioClips, setAudioClips] = useState({});
4
+ useEffect(() => {
5
+ const listener = (event) => setAudioClips(event.detail.clips);
6
+ audioPlayer?.addEventListener('state', listener);
7
+ return () => audioPlayer?.removeEventListener('state', listener);
8
+ }, [audioPlayer]);
9
+ return audioClips;
10
+ }
@@ -0,0 +1,2 @@
1
+ import { CogsAudioPlayer } from '@clockworkdog/cogs-client';
2
+ export default function useIsAudioPlaying(customAudioPlayer?: CogsAudioPlayer | null): boolean;
@@ -0,0 +1,12 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useAudioPlayer } from '../providers/CogsConnectionProvider';
3
+ export default function useIsAudioPlaying(customAudioPlayer) {
4
+ const [isAudioPlaying, setAudioPlaying] = useState(false);
5
+ const audioPlayer = useAudioPlayer(customAudioPlayer ?? undefined);
6
+ useEffect(() => {
7
+ const listener = (event) => setAudioPlaying(event.detail.isPlaying);
8
+ audioPlayer?.addEventListener('state', listener);
9
+ return () => audioPlayer?.removeEventListener('state', listener);
10
+ }, [audioPlayer]);
11
+ return isAudioPlaying;
12
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { default as CogsConnectionProvider, useCogsConnection } from './providers/CogsConnectionProvider';
1
+ export { default as CogsConnectionProvider, useCogsConnection, useAudioPlayer, useVideoPlayer } from './providers/CogsConnectionProvider';
2
2
  export { default as useIsConnected } from './hooks/useIsConnected';
3
3
  export { default as useCogsConfig } from './hooks/useCogsConfig';
4
4
  export { default as useCogsEvent } from './hooks/useCogsEvent';
@@ -11,6 +11,9 @@ export { default as usePreloadedUrl } from './hooks/usePreloadedUrl';
11
11
  export { default as useShowPhase } from './hooks/useShowPhase';
12
12
  export { default as useWhenShowReset } from './hooks/useWhenShowReset';
13
13
  export * from './utils/types';
14
+ export { default as useAudioClips } from './hooks/useAudioClips';
15
+ export { default as useIsAudioPlaying } from './hooks/useIsAudioPlaying';
16
+ export { default as VideoContainer } from './components/VideoContainer';
14
17
  export { default as useHint } from './hooks/useHint';
15
18
  export { default as Hint } from './components/Hint';
16
19
  export { default as Timer } from './components/Timer';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Utilities
2
- export { default as CogsConnectionProvider, useCogsConnection } from './providers/CogsConnectionProvider';
2
+ export { default as CogsConnectionProvider, useCogsConnection, useAudioPlayer, useVideoPlayer } from './providers/CogsConnectionProvider';
3
3
  export { default as useIsConnected } from './hooks/useIsConnected';
4
4
  export { default as useCogsConfig } from './hooks/useCogsConfig';
5
5
  export { default as useCogsEvent } from './hooks/useCogsEvent';
@@ -12,6 +12,11 @@ export { default as usePreloadedUrl } from './hooks/usePreloadedUrl';
12
12
  export { default as useShowPhase } from './hooks/useShowPhase';
13
13
  export { default as useWhenShowReset } from './hooks/useWhenShowReset';
14
14
  export * from './utils/types';
15
+ // Audio
16
+ export { default as useAudioClips } from './hooks/useAudioClips';
17
+ export { default as useIsAudioPlaying } from './hooks/useIsAudioPlaying';
18
+ // Video
19
+ export { default as VideoContainer } from './components/VideoContainer';
15
20
  // Hints
16
21
  export { default as useHint } from './hooks/useHint';
17
22
  export { default as Hint } from './components/Hint';
@@ -1,14 +1,64 @@
1
- import { CogsConnection, CogsPluginManifest, ManifestTypes } from '@clockworkdog/cogs-client';
1
+ import { CogsAudioPlayer, CogsConnection, CogsPluginManifest, CogsVideoPlayer, ManifestTypes } from '@clockworkdog/cogs-client';
2
2
  import React, { ReactNode } from 'react';
3
+ /**
4
+ * Create a persistent connection to COGS which can be accessed with `useCogsConnection()`
5
+ * @param audioPlayer Creates a `CogsAudioPlayer` than can be accessed with `useAudioPlayer()`
6
+ *
7
+ * Note: If unset, the audio player will remain active.
8
+ *
9
+ * @param videoPlayer Creates a `CogsVideoPlayer` than can be accessed with `useVideoPlayer()`
10
+ *
11
+ * Note: If unset, the video player will remain active.
12
+ *
13
+ * *Example:*
14
+ *
15
+ * ```jsx
16
+ * import manifest from './cogs-plugin-manifest.js';
17
+ *
18
+ * function MyComponent() {
19
+ * const cogsConnection = useCogsConnection();
20
+ * const numberOfPlayers = useCogsConfig(cogsConnection)['Number of players'];
21
+ *
22
+ * return <div>Players: {numberOfPlayers}</div>;
23
+ * }
24
+ *
25
+ * function App() {
26
+ * return <CogsConnectionProvider manifest={manifest} audioPlayer videoPlayer>
27
+ * <MyComponent />
28
+ * <CogsConnectionProvider/>;
29
+ * }
30
+ * ```
31
+ *
32
+ * or with Typescript:
33
+ *
34
+ * ```tsx
35
+ * import manifest from './cogs-plugin-manifest.js'; // Requires `"allowJs": true` in `tsconfig.json`
36
+ *
37
+ * function MyComponent() {
38
+ * const cogsConnection = useCogsConnection<typeof manifest>();
39
+ * const numberOfPlayers = useCogsConfig(cogsConnection)['Number of players'];
40
+ *
41
+ * return <div>Players: {numberOfPlayers}</div>;
42
+ * }
43
+ *
44
+ * function App() {
45
+ * return <CogsConnectionProvider manifest={manifest} audioPlayer videoPlayer>
46
+ * <MyComponent />
47
+ * <CogsConnectionProvider/>;
48
+ * }
49
+ * ```
50
+ */
3
51
  export default function CogsConnectionProvider<Manifest extends CogsPluginManifest, DataT extends {
4
52
  [key: string]: unknown;
5
53
  } = {
6
54
  [key: string]: unknown;
7
- }>({ manifest, hostname, port, children, initialClientState, initialDataStoreData, }: {
55
+ }>({ manifest, hostname, port, children, audioPlayer, videoPlayer, initialClientState, initialDataStoreData, }: {
8
56
  manifest: Manifest;
9
57
  hostname?: string;
10
58
  port?: number;
11
59
  children: React.ReactNode;
60
+ audioPlayer?: boolean;
61
+ videoPlayer?: boolean;
12
62
  initialClientState?: Partial<ManifestTypes.StateAsObject<Manifest, {
13
63
  writableFromClient: true;
14
64
  }>>;
@@ -18,3 +68,11 @@ export default function CogsConnectionProvider<Manifest extends CogsPluginManife
18
68
  * Get the connection from `<CogsConnectionProvider>`
19
69
  */
20
70
  export declare function useCogsConnection<Manifest extends CogsPluginManifest>(customConnection?: CogsConnection<Manifest>): CogsConnection<Manifest>;
71
+ /**
72
+ * Get the audio player from `<CogsConnectionProvider audioPlayer>`
73
+ */
74
+ export declare function useAudioPlayer<Manifest extends CogsPluginManifest>(customAudioPlayer?: CogsAudioPlayer): CogsAudioPlayer | null;
75
+ /**
76
+ * Get the video player from `<CogsConnectionProvider videoPlayer>`
77
+ */
78
+ export declare function useVideoPlayer<Manifest extends CogsPluginManifest>(customVideoPlayer?: CogsVideoPlayer): CogsVideoPlayer | null;
@@ -1,4 +1,4 @@
1
- import { CogsConnection } from '@clockworkdog/cogs-client';
1
+ import { CogsAudioPlayer, CogsConnection, CogsVideoPlayer } from '@clockworkdog/cogs-client';
2
2
  import React, { useContext, useEffect, useRef, useState } from 'react';
3
3
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
4
  const CogsConnectionContext = React.createContext({
@@ -8,8 +8,68 @@ const CogsConnectionContext = React.createContext({
8
8
  }
9
9
  return customConnection;
10
10
  },
11
+ useAudioPlayer: (customAudioPlayer) => {
12
+ if (!customAudioPlayer) {
13
+ throw new Error('Ensure <CogsConnectionProvider> has been added to your React app');
14
+ }
15
+ return customAudioPlayer;
16
+ },
17
+ useVideoPlayer: (customVideoPlayer) => {
18
+ if (!customVideoPlayer) {
19
+ throw new Error('Ensure <CogsConnectionProvider> has been added to your React app');
20
+ }
21
+ return customVideoPlayer;
22
+ },
11
23
  });
12
- export default function CogsConnectionProvider({ manifest, hostname, port, children, initialClientState, initialDataStoreData, }) {
24
+ /**
25
+ * Create a persistent connection to COGS which can be accessed with `useCogsConnection()`
26
+ * @param audioPlayer Creates a `CogsAudioPlayer` than can be accessed with `useAudioPlayer()`
27
+ *
28
+ * Note: If unset, the audio player will remain active.
29
+ *
30
+ * @param videoPlayer Creates a `CogsVideoPlayer` than can be accessed with `useVideoPlayer()`
31
+ *
32
+ * Note: If unset, the video player will remain active.
33
+ *
34
+ * *Example:*
35
+ *
36
+ * ```jsx
37
+ * import manifest from './cogs-plugin-manifest.js';
38
+ *
39
+ * function MyComponent() {
40
+ * const cogsConnection = useCogsConnection();
41
+ * const numberOfPlayers = useCogsConfig(cogsConnection)['Number of players'];
42
+ *
43
+ * return <div>Players: {numberOfPlayers}</div>;
44
+ * }
45
+ *
46
+ * function App() {
47
+ * return <CogsConnectionProvider manifest={manifest} audioPlayer videoPlayer>
48
+ * <MyComponent />
49
+ * <CogsConnectionProvider/>;
50
+ * }
51
+ * ```
52
+ *
53
+ * or with Typescript:
54
+ *
55
+ * ```tsx
56
+ * import manifest from './cogs-plugin-manifest.js'; // Requires `"allowJs": true` in `tsconfig.json`
57
+ *
58
+ * function MyComponent() {
59
+ * const cogsConnection = useCogsConnection<typeof manifest>();
60
+ * const numberOfPlayers = useCogsConfig(cogsConnection)['Number of players'];
61
+ *
62
+ * return <div>Players: {numberOfPlayers}</div>;
63
+ * }
64
+ *
65
+ * function App() {
66
+ * return <CogsConnectionProvider manifest={manifest} audioPlayer videoPlayer>
67
+ * <MyComponent />
68
+ * <CogsConnectionProvider/>;
69
+ * }
70
+ * ```
71
+ */
72
+ export default function CogsConnectionProvider({ manifest, hostname, port, children, audioPlayer, videoPlayer, initialClientState, initialDataStoreData, }) {
13
73
  const connectionRef = useRef(undefined);
14
74
  const [, forceRender] = useState({});
15
75
  useEffect(() => {
@@ -21,12 +81,26 @@ export default function CogsConnectionProvider({ manifest, hostname, port, child
21
81
  connection.close();
22
82
  };
23
83
  }, [manifest, hostname, port, initialClientState, initialDataStoreData]);
84
+ const audioPlayerRef = useRef(undefined);
85
+ useEffect(() => {
86
+ if (audioPlayer && !audioPlayerRef.current && connectionRef.current) {
87
+ audioPlayerRef.current = new CogsAudioPlayer(connectionRef.current);
88
+ }
89
+ }, [audioPlayer]);
90
+ const videoPlayerRef = useRef(undefined);
91
+ useEffect(() => {
92
+ if (videoPlayer && !videoPlayerRef.current && connectionRef.current) {
93
+ videoPlayerRef.current = new CogsVideoPlayer(connectionRef.current);
94
+ }
95
+ }, [videoPlayer]);
24
96
  if (!connectionRef.current) {
25
97
  // Do not render if the `useEffect`s above have not run
26
98
  return null;
27
99
  }
28
100
  const value = {
29
101
  useCogsConnection: (customConnection) => customConnection ?? connectionRef.current,
102
+ useAudioPlayer: (customAudioPlayer) => customAudioPlayer ?? audioPlayerRef.current ?? null,
103
+ useVideoPlayer: (customVideoPlayer) => customVideoPlayer ?? videoPlayerRef.current ?? null,
30
104
  };
31
105
  return React.createElement(CogsConnectionContext.Provider, { value: value }, children);
32
106
  }
@@ -36,3 +110,15 @@ export default function CogsConnectionProvider({ manifest, hostname, port, child
36
110
  export function useCogsConnection(customConnection) {
37
111
  return useContext(CogsConnectionContext).useCogsConnection(customConnection);
38
112
  }
113
+ /**
114
+ * Get the audio player from `<CogsConnectionProvider audioPlayer>`
115
+ */
116
+ export function useAudioPlayer(customAudioPlayer) {
117
+ return useContext(CogsConnectionContext).useAudioPlayer(customAudioPlayer);
118
+ }
119
+ /**
120
+ * Get the video player from `<CogsConnectionProvider videoPlayer>`
121
+ */
122
+ export function useVideoPlayer(customVideoPlayer) {
123
+ return useContext(CogsConnectionContext).useVideoPlayer(customVideoPlayer);
124
+ }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "React components and hooks to connect to COGS to build a custom Media Master",
4
4
  "author": "Clockwork Dog <info@clockwork.dog>",
5
5
  "homepage": "https://github.com/clockwork-dog/cogs-sdk/tree/main/packages/react",
6
- "version": "3.0.0-alpha.2",
6
+ "version": "3.0.0-alpha.3",
7
7
  "keywords": [],
8
8
  "license": "MIT",
9
9
  "repository": {
@@ -28,7 +28,7 @@
28
28
  "prerelease": "yarn npm publish --access public --tag=next"
29
29
  },
30
30
  "dependencies": {
31
- "@clockworkdog/cogs-client": "^3.0.0-alpha.2"
31
+ "@clockworkdog/cogs-client": "^3.0.0-alpha.3"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "react": "^18.0.0 || ^19.0.0",