@stream-io/video-react-sdk 0.0.1-alpha.33 → 0.0.1-alpha.35

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/css/styles.css +134 -145
  3. package/dist/css/styles.css.map +1 -1
  4. package/dist/src/components/Button/CompositeButton.js +2 -4
  5. package/dist/src/components/Button/CompositeButton.js.map +1 -1
  6. package/dist/src/components/StreamCall/CallParticipantsScreenView.js +3 -3
  7. package/dist/src/components/StreamCall/CallParticipantsScreenView.js.map +1 -1
  8. package/dist/src/components/StreamCall/CallParticipantsView.js +2 -3
  9. package/dist/src/components/StreamCall/CallParticipantsView.js.map +1 -1
  10. package/dist/src/core/components/CallLayout/PaginatedGridLayout.d.ts +3 -7
  11. package/dist/src/core/components/CallLayout/PaginatedGridLayout.js +7 -11
  12. package/dist/src/core/components/CallLayout/PaginatedGridLayout.js.map +1 -1
  13. package/dist/src/core/components/CallLayout/SpeakerLayout.d.ts +6 -1
  14. package/dist/src/core/components/CallLayout/SpeakerLayout.js +5 -3
  15. package/dist/src/core/components/CallLayout/SpeakerLayout.js.map +1 -1
  16. package/dist/src/core/components/ParticipantView/DefaultParticipantViewUI.d.ts +20 -0
  17. package/dist/src/core/components/ParticipantView/DefaultParticipantViewUI.js +33 -0
  18. package/dist/src/core/components/ParticipantView/DefaultParticipantViewUI.js.map +1 -0
  19. package/dist/src/core/components/ParticipantView/ParticipantView.d.ts +82 -0
  20. package/dist/src/core/components/ParticipantView/ParticipantView.js +28 -0
  21. package/dist/src/core/components/ParticipantView/ParticipantView.js.map +1 -0
  22. package/dist/src/core/components/ParticipantView/index.d.ts +2 -0
  23. package/dist/src/core/components/ParticipantView/index.js +3 -0
  24. package/dist/src/core/components/ParticipantView/index.js.map +1 -0
  25. package/dist/src/core/components/Video/BaseVideo.d.ts +3 -3
  26. package/dist/src/core/components/Video/BaseVideo.js +6 -12
  27. package/dist/src/core/components/Video/BaseVideo.js.map +1 -1
  28. package/dist/src/core/components/Video/Video.d.ts +8 -6
  29. package/dist/src/core/components/Video/Video.js +27 -25
  30. package/dist/src/core/components/Video/Video.js.map +1 -1
  31. package/dist/src/core/components/Video/VideoPlaceholder.d.ts +3 -3
  32. package/dist/src/core/components/Video/VideoPlaceholder.js +2 -5
  33. package/dist/src/core/components/Video/VideoPlaceholder.js.map +1 -1
  34. package/dist/src/core/components/index.d.ts +2 -2
  35. package/dist/src/core/components/index.js +1 -1
  36. package/dist/src/core/components/index.js.map +1 -1
  37. package/dist/src/core/hooks/index.d.ts +1 -0
  38. package/dist/src/core/hooks/index.js +1 -0
  39. package/dist/src/core/hooks/index.js.map +1 -1
  40. package/dist/src/core/hooks/useTrackElementVisibility.d.ts +6 -0
  41. package/dist/src/core/hooks/useTrackElementVisibility.js +24 -0
  42. package/dist/src/core/hooks/useTrackElementVisibility.js.map +1 -0
  43. package/dist/src/utilities/applyElementRef.d.ts +2 -0
  44. package/dist/src/utilities/applyElementRef.js +8 -0
  45. package/dist/src/utilities/applyElementRef.js.map +1 -0
  46. package/dist/src/utilities/chunk.d.ts +1 -0
  47. package/dist/src/utilities/chunk.js +5 -0
  48. package/dist/src/utilities/chunk.js.map +1 -0
  49. package/dist/src/utilities/index.d.ts +3 -0
  50. package/dist/src/utilities/index.js +4 -0
  51. package/dist/src/utilities/index.js.map +1 -0
  52. package/dist/src/utilities/isComponentType.d.ts +2 -0
  53. package/dist/src/utilities/isComponentType.js +7 -0
  54. package/dist/src/utilities/isComponentType.js.map +1 -0
  55. package/package.json +5 -5
  56. package/src/components/Button/CompositeButton.tsx +4 -13
  57. package/src/components/StreamCall/CallParticipantsScreenView.tsx +3 -4
  58. package/src/components/StreamCall/CallParticipantsView.tsx +3 -4
  59. package/src/core/components/CallLayout/PaginatedGridLayout.tsx +21 -40
  60. package/src/core/components/CallLayout/SpeakerLayout.tsx +46 -19
  61. package/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx +165 -0
  62. package/src/core/components/ParticipantView/ParticipantView.tsx +136 -0
  63. package/src/core/components/ParticipantView/index.ts +2 -0
  64. package/src/core/components/Video/BaseVideo.tsx +9 -24
  65. package/src/core/components/Video/Video.tsx +55 -44
  66. package/src/core/components/Video/VideoPlaceholder.tsx +7 -11
  67. package/src/core/components/index.ts +2 -2
  68. package/src/core/hooks/index.ts +1 -0
  69. package/src/core/hooks/useTrackElementVisibility.ts +41 -0
  70. package/src/utilities/applyElementRef.ts +12 -0
  71. package/src/utilities/chunk.ts +8 -0
  72. package/src/utilities/index.ts +3 -0
  73. package/src/utilities/isComponentType.ts +9 -0
  74. package/dist/src/core/components/ParticipantBox/ParticipantBox.d.ts +0 -48
  75. package/dist/src/core/components/ParticipantBox/ParticipantBox.js +0 -58
  76. package/dist/src/core/components/ParticipantBox/ParticipantBox.js.map +0 -1
  77. package/dist/src/core/components/ParticipantBox/index.d.ts +0 -1
  78. package/dist/src/core/components/ParticipantBox/index.js +0 -2
  79. package/dist/src/core/components/ParticipantBox/index.js.map +0 -1
  80. package/src/core/components/ParticipantBox/ParticipantBox.tsx +0 -248
  81. package/src/core/components/ParticipantBox/index.ts +0 -1
@@ -1,6 +1,6 @@
1
- import { ComponentProps } from 'react';
2
- import { StreamVideoParticipant } from '@stream-io/video-client';
1
+ import { ComponentPropsWithRef } from 'react';
2
+ import type { StreamVideoParticipant } from '@stream-io/video-client';
3
3
  export type VideoPlaceholderProps = {
4
4
  participant: StreamVideoParticipant;
5
- } & ComponentProps<'div'>;
5
+ } & ComponentPropsWithRef<'div'>;
6
6
  export declare const VideoPlaceholder: import("react").ForwardRefExoticComponent<Omit<VideoPlaceholderProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -1,12 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef, useState } from 'react';
3
- import { clsx } from 'clsx';
4
3
  export const VideoPlaceholder = forwardRef(({ participant, style }, ref) => {
5
4
  const [error, setError] = useState(false);
6
5
  const name = (participant === null || participant === void 0 ? void 0 : participant.name) || (participant === null || participant === void 0 ? void 0 : participant.userId);
7
- return (_jsxs("div", Object.assign({ className: "str-video__participant-placeholder", style: style, ref: ref }, { children: [(!participant.image || error) &&
8
- (name ? (_jsx("div", Object.assign({ className: "str-video__participant-placeholder--initials-fallback" }, { children: _jsx("div", { children: name[0] }) }))) : (_jsx("div", { children: "Video is disabled" }))), participant.image && !error && (_jsx("img", { onError: () => setError(true), alt: "participant-placeholder", className: clsx('str-video__participant-placeholder--avatar', {
9
- 'str-video__participant-placeholder--avatar-speaking': participant.isSpeaking,
10
- }), src: participant.image }))] })));
6
+ return (_jsxs("div", Object.assign({ className: "str-video__video-placeholder", style: style, ref: ref }, { children: [(!participant.image || error) &&
7
+ (name ? (_jsx("div", Object.assign({ className: "str-video__video-placeholder__initials-fallback" }, { children: _jsx("div", { children: name[0] }) }))) : (_jsx("div", { children: "Video is disabled" }))), participant.image && !error && (_jsx("img", { onError: () => setError(true), alt: "video-placeholder", className: "str-video__video-placeholder__avatar", src: participant.image }))] })));
11
8
  });
12
9
  //# sourceMappingURL=VideoPlaceholder.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VideoPlaceholder.js","sourceRoot":"","sources":["../../../../../src/core/components/Video/VideoPlaceholder.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkB,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAGxC,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IAChC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE1C,MAAM,IAAI,GAAG,CAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,IAAI,MAAI,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,MAAM,CAAA,CAAC;IAEtD,OAAO,CACL,6BAAK,SAAS,EAAC,oCAAoC,EAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,iBACvE,CAAC,CAAC,WAAW,CAAC,KAAK,IAAI,KAAK,CAAC;gBAC5B,CAAC,IAAI,CAAC,CAAC,CAAC,CACN,4BAAK,SAAS,EAAC,uDAAuD,gBACpE,wBAAM,IAAI,CAAC,CAAC,CAAC,GAAO,IAChB,CACP,CAAC,CAAC,CAAC,CACF,8CAA4B,CAC7B,CAAC,EACH,WAAW,CAAC,KAAK,IAAI,CAAC,KAAK,IAAI,CAC9B,cACE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAC7B,GAAG,EAAC,yBAAyB,EAC7B,SAAS,EAAE,IAAI,CAAC,4CAA4C,EAAE;oBAC5D,qDAAqD,EACnD,WAAW,CAAC,UAAU;iBACzB,CAAC,EACF,GAAG,EAAE,WAAW,CAAC,KAAK,GACtB,CACH,KACG,CACP,CAAC;AACJ,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"VideoPlaceholder.js","sourceRoot":"","sources":["../../../../../src/core/components/Video/VideoPlaceholder.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAyB,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAOpE,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAGxC,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IAChC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE1C,MAAM,IAAI,GAAG,CAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,IAAI,MAAI,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,MAAM,CAAA,CAAC;IAEtD,OAAO,CACL,6BAAK,SAAS,EAAC,8BAA8B,EAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,iBACjE,CAAC,CAAC,WAAW,CAAC,KAAK,IAAI,KAAK,CAAC;gBAC5B,CAAC,IAAI,CAAC,CAAC,CAAC,CACN,4BAAK,SAAS,EAAC,iDAAiD,gBAC9D,wBAAM,IAAI,CAAC,CAAC,CAAC,GAAO,IAChB,CACP,CAAC,CAAC,CAAC,CACF,8CAA4B,CAC7B,CAAC,EACH,WAAW,CAAC,KAAK,IAAI,CAAC,KAAK,IAAI,CAC9B,cACE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAC7B,GAAG,EAAC,mBAAmB,EACvB,SAAS,EAAC,sCAAsC,EAChD,GAAG,EAAE,WAAW,CAAC,KAAK,GACtB,CACH,KACG,CACP,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,5 +1,5 @@
1
1
  export * from './Audio';
2
- export * from './ParticipantBox';
2
+ export * from './ParticipantView';
3
3
  export { Video } from './Video';
4
- export type { VideoProps } from './Video';
4
+ export type { BaseVideoProps, VideoProps } from './Video';
5
5
  export * from './CallLayout';
@@ -1,5 +1,5 @@
1
1
  export * from './Audio';
2
- export * from './ParticipantBox';
2
+ export * from './ParticipantView';
3
3
  export { Video } from './Video';
4
4
  export * from './CallLayout';
5
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AAEjC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,cAAc,cAAc,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export * from './useAudioPublisher';
2
2
  export * from './useVideoPublisher';
3
+ export * from './useTrackElementVisibility';
@@ -1,3 +1,4 @@
1
1
  export * from './useAudioPublisher';
2
2
  export * from './useVideoPublisher';
3
+ export * from './useTrackElementVisibility';
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { ViewportTracker } from '@stream-io/video-client';
2
+ export declare const useTrackElementVisibility: <T extends HTMLElement>({ trackedElement, viewportTracker: propsViewportTracker, sessionId, }: {
3
+ trackedElement: T | null;
4
+ sessionId: string;
5
+ viewportTracker?: ViewportTracker | undefined;
6
+ }) => void;
@@ -0,0 +1,24 @@
1
+ import { useEffect } from 'react';
2
+ import { VisibilityState } from '@stream-io/video-client';
3
+ import { useCall } from '@stream-io/video-react-bindings';
4
+ export const useTrackElementVisibility = ({ trackedElement, viewportTracker: propsViewportTracker, sessionId, }) => {
5
+ const call = useCall();
6
+ const viewportTracker = propsViewportTracker !== null && propsViewportTracker !== void 0 ? propsViewportTracker : call === null || call === void 0 ? void 0 : call.viewportTracker;
7
+ useEffect(() => {
8
+ if (!trackedElement || !viewportTracker || !call)
9
+ return;
10
+ const unobserve = viewportTracker.observe(trackedElement, (entry) => {
11
+ call.state.updateParticipant(sessionId, (p) => (Object.assign(Object.assign({}, p), { viewportVisibilityState: entry.isIntersecting
12
+ ? VisibilityState.VISIBLE
13
+ : VisibilityState.INVISIBLE })));
14
+ });
15
+ return () => {
16
+ unobserve();
17
+ // reset visibility state to UNKNOWN upon cleanup
18
+ // so that the layouts that are not actively observed
19
+ // can still function normally (runtime layout switching)
20
+ call.state.updateParticipant(sessionId, (p) => (Object.assign(Object.assign({}, p), { viewportVisibilityState: VisibilityState.UNKNOWN })));
21
+ };
22
+ }, [trackedElement, viewportTracker, call, sessionId]);
23
+ };
24
+ //# sourceMappingURL=useTrackElementVisibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTrackElementVisibility.js","sourceRoot":"","sources":["../../../../src/core/hooks/useTrackElementVisibility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAmB,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAE1D,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAwB,EAC/D,cAAc,EACd,eAAe,EAAE,oBAAoB,EACrC,SAAS,GAKV,EAAE,EAAE;IACH,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,MAAM,eAAe,GAAG,oBAAoB,aAApB,oBAAoB,cAApB,oBAAoB,GAAI,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,eAAe,CAAC;IAEtE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,cAAc,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI;YAAE,OAAO;QAEzD,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,EAAE;YAClE,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,iCAC1C,CAAC,KACJ,uBAAuB,EAAE,KAAK,CAAC,cAAc;oBAC3C,CAAC,CAAC,eAAe,CAAC,OAAO;oBACzB,CAAC,CAAC,eAAe,CAAC,SAAS,IAC7B,CAAC,CAAC;QACN,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,SAAS,EAAE,CAAC;YACZ,iDAAiD;YACjD,qDAAqD;YACrD,yDAAyD;YACzD,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,iCAC1C,CAAC,KACJ,uBAAuB,EAAE,eAAe,CAAC,OAAO,IAChD,CAAC,CAAC;QACN,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,cAAc,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;AACzD,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ForwardedRef } from 'react';
2
+ export declare const applyElementRef: <T extends HTMLElement | null>(ref: ForwardedRef<T>, element: T) => void;
@@ -0,0 +1,8 @@
1
+ export const applyElementRef = (ref, element) => {
2
+ if (!ref)
3
+ return;
4
+ if (typeof ref === 'function')
5
+ return ref(element);
6
+ ref.current = element;
7
+ };
8
+ //# sourceMappingURL=applyElementRef.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applyElementRef.js","sourceRoot":"","sources":["../../../src/utilities/applyElementRef.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,GAAoB,EACpB,OAAU,EACV,EAAE;IACF,IAAI,CAAC,GAAG;QAAE,OAAO;IAEjB,IAAI,OAAO,GAAG,KAAK,UAAU;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;IAEnD,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC;AACxB,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const chunk: <T extends unknown[]>(array: T, size: number) => T[];
@@ -0,0 +1,5 @@
1
+ export const chunk = (array, size) => {
2
+ const chunkCount = Math.ceil(array.length / size);
3
+ return Array.from({ length: chunkCount }, (_, index) => array.slice(size * index, size * index + size));
4
+ };
5
+ //# sourceMappingURL=chunk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk.js","sourceRoot":"","sources":["../../../src/utilities/chunk.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,CAAsB,KAAQ,EAAE,IAAY,EAAE,EAAE;IACnE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAElD,OAAO,KAAK,CAAC,IAAI,CACf,EAAE,MAAM,EAAE,UAAU,EAAE,EACtB,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,GAAG,IAAI,CAAM,CAClE,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './isComponentType';
2
+ export * from './chunk';
3
+ export * from './applyElementRef';
@@ -0,0 +1,4 @@
1
+ export * from './isComponentType';
2
+ export * from './chunk';
3
+ export * from './applyElementRef';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utilities/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { ComponentType, ReactElement } from 'react';
2
+ export declare const isComponentType: <T extends {}>(elementOrComponent?: ReactElement<any, string | import("react").JSXElementConstructor<any>> | ComponentType<T> | null | undefined) => elementOrComponent is ComponentType<T>;
@@ -0,0 +1,7 @@
1
+ import { isValidElement } from 'react';
2
+ export const isComponentType = (elementOrComponent) => {
3
+ return elementOrComponent === null
4
+ ? false
5
+ : !isValidElement(elementOrComponent);
6
+ };
7
+ //# sourceMappingURL=isComponentType.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isComponentType.js","sourceRoot":"","sources":["../../../src/utilities/isComponentType.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,cAAc,EAAgB,MAAM,OAAO,CAAC;AAEpE,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,kBAA2D,EACnB,EAAE;IAC1C,OAAO,kBAAkB,KAAK,IAAI;QAChC,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;AAC1C,CAAC,CAAC"}
package/package.json CHANGED
@@ -25,9 +25,9 @@
25
25
  "@floating-ui/react": "^0.22.0",
26
26
  "@nivo/core": "^0.80.0",
27
27
  "@nivo/line": "^0.80.0",
28
- "@stream-io/i18n": "^0.0.1-alpha.18",
29
- "@stream-io/video-client": "^0.0.1-alpha.141",
30
- "@stream-io/video-react-bindings": "^0.0.1-alpha.29",
28
+ "@stream-io/i18n": "^0.0.1-alpha.20",
29
+ "@stream-io/video-client": "^0.0.1-alpha.143",
30
+ "@stream-io/video-react-bindings": "^0.0.1-alpha.31",
31
31
  "clsx": "^1.2.1",
32
32
  "rxjs": "~7.8.1"
33
33
  },
@@ -36,7 +36,7 @@
36
36
  "react-dom": "^18.0.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@stream-io/video-styling": "^0.0.1-alpha.11",
39
+ "@stream-io/video-styling": "^0.0.1-alpha.13",
40
40
  "@types/rimraf": "^3.0.2",
41
41
  "react": "^18.2.0",
42
42
  "react-dom": "^18.2.0",
@@ -45,5 +45,5 @@
45
45
  "typedoc": "^0.24.7",
46
46
  "typescript": "^4.9.5"
47
47
  },
48
- "version": "0.0.1-alpha.33"
48
+ "version": "0.0.1-alpha.35"
49
49
  }
@@ -1,14 +1,11 @@
1
1
  import clsx from 'clsx';
2
2
  import { MenuToggle, ToggleMenuButtonProps } from '../Menu';
3
- import {
4
- ComponentType,
5
- forwardRef,
6
- isValidElement,
7
- PropsWithChildren,
8
- } from 'react';
9
- import { IconButton } from './IconButton';
3
+ import { ComponentType, forwardRef, PropsWithChildren } from 'react';
10
4
  import { Placement } from '@floating-ui/react';
11
5
 
6
+ import { IconButton } from './IconButton';
7
+ import { isComponentType } from '../../utilities';
8
+
12
9
  export type IconButtonWithMenuProps = PropsWithChildren<{
13
10
  active?: boolean;
14
11
  Menu?: ComponentType | JSX.Element;
@@ -16,12 +13,6 @@ export type IconButtonWithMenuProps = PropsWithChildren<{
16
13
  menuPlacement?: Placement;
17
14
  }>;
18
15
 
19
- const isComponentType = (
20
- elementOrComponent: ComponentType | JSX.Element,
21
- ): elementOrComponent is ComponentType => {
22
- return !isValidElement(elementOrComponent);
23
- };
24
-
25
16
  export const CompositeButton = forwardRef<
26
17
  HTMLDivElement,
27
18
  IconButtonWithMenuProps
@@ -5,7 +5,7 @@ import {
5
5
  useLocalParticipant,
6
6
  useParticipants,
7
7
  } from '@stream-io/video-react-bindings';
8
- import { ParticipantBox } from '../../core/components/ParticipantBox/ParticipantBox';
8
+ import { ParticipantView, DefaultParticipantViewUI } from '../../core';
9
9
  import { Video } from '../Video';
10
10
 
11
11
  import { useVerticalScrollPosition } from './hooks';
@@ -60,7 +60,6 @@ export const CallParticipantsScreenView = (props: { call: Call }) => {
60
60
  <Video
61
61
  className="str-video__screen-share"
62
62
  participant={firstScreenSharingParticipant}
63
- call={call}
64
63
  kind="screen"
65
64
  autoPlay
66
65
  muted
@@ -104,11 +103,11 @@ export const CallParticipantsScreenView = (props: { call: Call }) => {
104
103
  >
105
104
  <div className="str-video__call-participants-screen-view__participants">
106
105
  {allParticipants.map((participant) => (
107
- <ParticipantBox
106
+ <ParticipantView
108
107
  key={participant.sessionId}
109
108
  participant={participant}
110
- call={call}
111
109
  sinkId={localParticipant?.audioOutputDeviceId}
110
+ ParticipantViewUI={DefaultParticipantViewUI}
112
111
  />
113
112
  ))}
114
113
  </div>
@@ -1,23 +1,22 @@
1
1
  import { Call } from '@stream-io/video-client';
2
- import { ParticipantBox } from '../../core/components/ParticipantBox/ParticipantBox';
2
+ import { DefaultParticipantViewUI, ParticipantView } from '../../core';
3
3
  import {
4
4
  useLocalParticipant,
5
5
  useParticipants,
6
6
  } from '@stream-io/video-react-bindings';
7
7
 
8
8
  export const CallParticipantsView = (props: { call: Call }) => {
9
- const { call } = props;
10
9
  const localParticipant = useLocalParticipant();
11
10
  const participants = useParticipants();
12
11
  const grid = `str-video__grid-${participants.length || 1}`;
13
12
  return (
14
13
  <div className={`str-video__call-participants-view ${grid}`}>
15
14
  {participants.map((participant) => (
16
- <ParticipantBox
15
+ <ParticipantView
17
16
  key={participant.sessionId}
18
17
  participant={participant}
19
- call={call}
20
18
  sinkId={localParticipant?.audioOutputDeviceId}
19
+ ParticipantViewUI={DefaultParticipantViewUI}
21
20
  />
22
21
  ))}
23
22
  </div>
@@ -6,43 +6,38 @@ import {
6
6
  useRemoteParticipants,
7
7
  } from '@stream-io/video-react-bindings';
8
8
  import {
9
- Call,
10
9
  StreamVideoLocalParticipant,
11
10
  StreamVideoParticipant,
12
11
  } from '@stream-io/video-client';
13
12
  import clsx from 'clsx';
14
13
 
15
- import { ParticipantBox } from '../ParticipantBox';
14
+ import {
15
+ ParticipantView,
16
+ DefaultParticipantViewUI,
17
+ ParticipantViewProps,
18
+ } from '../ParticipantView';
16
19
  import { Audio } from '../Audio';
17
20
  import { IconButton } from '../../../components';
21
+ import { chunk } from '../../../utilities';
18
22
 
19
23
  const GROUP_SIZE = 16;
20
24
 
21
25
  type PaginatedGridLayoutGroupProps = {
22
- /**
23
- * The call object.
24
- */
25
- call: Call;
26
-
27
26
  /**
28
27
  * The group of participants to render.
29
28
  */
30
29
  group: Array<StreamVideoParticipant | StreamVideoLocalParticipant>;
30
+ } & Pick<ParticipantViewProps, 'VideoPlaceholder'> &
31
+ Required<Pick<ParticipantViewProps, 'ParticipantViewUI'>>;
31
32
 
32
- /**
33
- * Turns on/off the status indicator icons (mute, connection quality, etc...)
34
- * on the participant boxes.
35
- */
36
- indicatorsVisible?: boolean;
37
- };
38
33
  const PaginatedGridLayoutGroup = ({
39
- call,
40
34
  group,
41
- indicatorsVisible = true,
35
+ VideoPlaceholder,
36
+ ParticipantViewUI,
42
37
  }: PaginatedGridLayoutGroupProps) => {
43
38
  return (
44
39
  <div
45
- className={clsx('str-video__paginated-grid-layout--group', {
40
+ className={clsx('str-video__paginated-grid-layout__group', {
46
41
  'str-video__paginated-grid-layout--one': group.length === 1,
47
42
  'str-video__paginated-grid-layout--two-four':
48
43
  group.length >= 2 && group.length <= 4,
@@ -51,12 +46,12 @@ const PaginatedGridLayoutGroup = ({
51
46
  })}
52
47
  >
53
48
  {group.map((participant) => (
54
- <ParticipantBox
49
+ <ParticipantView
55
50
  key={participant.sessionId}
56
51
  participant={participant}
57
- call={call}
58
- indicatorsVisible={indicatorsVisible}
59
52
  muteAudio
53
+ VideoPlaceholder={VideoPlaceholder}
54
+ ParticipantViewUI={ParticipantViewUI}
60
55
  />
61
56
  ))}
62
57
  </div>
@@ -74,23 +69,18 @@ export type PaginatedGridLayoutProps = {
74
69
  */
75
70
  excludeLocalParticipant?: boolean;
76
71
 
77
- /**
78
- * Turns on/off the status indicator icons (mute, connection quality, etc...)
79
- * on the participant boxes.
80
- */
81
- indicatorsVisible?: boolean;
82
-
83
72
  /**
84
73
  * Turns on/off the pagination arrows.
85
74
  */
86
75
  pageArrowsVisible?: boolean;
87
- };
76
+ } & Pick<ParticipantViewProps, 'ParticipantViewUI' | 'VideoPlaceholder'>;
88
77
 
89
78
  export const PaginatedGridLayout = ({
90
79
  groupSize = GROUP_SIZE,
91
80
  excludeLocalParticipant = false,
92
- indicatorsVisible = true,
93
81
  pageArrowsVisible = true,
82
+ VideoPlaceholder,
83
+ ParticipantViewUI = DefaultParticipantViewUI,
94
84
  }: PaginatedGridLayoutProps) => {
95
85
  const [page, setPage] = useState(0);
96
86
 
@@ -122,6 +112,7 @@ export const PaginatedGridLayout = ({
122
112
  const selectedGroup = participantGroups[page];
123
113
 
124
114
  if (!call) return null;
115
+
125
116
  return (
126
117
  <>
127
118
  {remoteParticipants.map((participant) => (
@@ -132,7 +123,7 @@ export const PaginatedGridLayout = ({
132
123
  sinkId={localParticipant?.audioOutputDeviceId}
133
124
  />
134
125
  ))}
135
- <div className="str-video__paginated-grid-layout--wrapper">
126
+ <div className="str-video__paginated-grid-layout__wrapper">
136
127
  <div className="str-video__paginated-grid-layout">
137
128
  {pageArrowsVisible && pageCount > 1 && (
138
129
  <IconButton
@@ -145,9 +136,9 @@ export const PaginatedGridLayout = ({
145
136
  )}
146
137
  {selectedGroup && (
147
138
  <PaginatedGridLayoutGroup
148
- call={call}
149
139
  group={participantGroups[page]}
150
- indicatorsVisible={indicatorsVisible}
140
+ VideoPlaceholder={VideoPlaceholder}
141
+ ParticipantViewUI={ParticipantViewUI}
151
142
  />
152
143
  )}
153
144
  {pageArrowsVisible && pageCount > 1 && (
@@ -166,13 +157,3 @@ export const PaginatedGridLayout = ({
166
157
  </>
167
158
  );
168
159
  };
169
-
170
- // TODO: move to utilities
171
- const chunk = <T extends unknown[]>(array: T, size = GROUP_SIZE) => {
172
- const chunkCount = Math.ceil(array.length / size);
173
-
174
- return Array.from(
175
- { length: chunkCount },
176
- (_, index) => array.slice(size * index, size * index + size) as T,
177
- );
178
- };
@@ -16,11 +16,37 @@ import {
16
16
  useParticipants,
17
17
  } from '@stream-io/video-react-bindings';
18
18
 
19
- import { ParticipantBox } from '../ParticipantBox';
19
+ import {
20
+ ParticipantView,
21
+ DefaultParticipantViewUI,
22
+ ParticipantViewProps,
23
+ ParticipantViewUIProps,
24
+ } from '../ParticipantView';
20
25
  import { IconButton } from '../../../components';
21
26
  import { useHorizontalScrollPosition } from '../../../components/StreamCall/hooks';
22
27
 
23
- export const SpeakerLayout = () => {
28
+ export type SpeakerLayoutProps = {
29
+ ParticipantViewUISpotlight?: ParticipantViewProps['ParticipantViewUI'];
30
+ ParticipantViewUIBar?: ParticipantViewProps['ParticipantViewUI'];
31
+ } & Pick<ParticipantViewProps, 'VideoPlaceholder'>;
32
+
33
+ const DefaultParticipantViewUIBar = ({
34
+ participant,
35
+ }: ParticipantViewUIProps) => (
36
+ <DefaultParticipantViewUI participant={participant} menuPlacement="top-end" />
37
+ );
38
+
39
+ const DefaultParticipantViewUISpotlight = ({
40
+ participant,
41
+ }: ParticipantViewUIProps) => (
42
+ <DefaultParticipantViewUI participant={participant} />
43
+ );
44
+
45
+ export const SpeakerLayout = ({
46
+ ParticipantViewUIBar = DefaultParticipantViewUIBar,
47
+ ParticipantViewUISpotlight = DefaultParticipantViewUISpotlight,
48
+ VideoPlaceholder,
49
+ }: SpeakerLayoutProps) => {
24
50
  const call = useCall();
25
51
  const [participantInSpotlight, ...otherParticipants] = useParticipants();
26
52
  const [scrollWrapper, setScrollWrapper] = useState<HTMLDivElement | null>(
@@ -69,56 +95,57 @@ export const SpeakerLayout = () => {
69
95
 
70
96
  const isSpeakerScreenSharing = hasScreenShare(participantInSpotlight);
71
97
  return (
72
- <div className="str-video__speaker-layout--wrapper">
98
+ <div className="str-video__speaker-layout__wrapper">
73
99
  <div className="str-video__speaker-layout">
74
- <div className="str-video__speaker-layout--spotlight">
100
+ <div className="str-video__speaker-layout__spotlight">
75
101
  {participantInSpotlight && (
76
- <ParticipantBox
102
+ <ParticipantView
77
103
  participant={participantInSpotlight}
78
- call={call}
79
104
  muteAudio={isSpeakerScreenSharing}
80
105
  videoKind={isSpeakerScreenSharing ? 'screen' : 'video'}
81
106
  sinkId={localParticipant?.audioOutputDeviceId}
107
+ ParticipantViewUI={ParticipantViewUISpotlight}
108
+ VideoPlaceholder={VideoPlaceholder}
82
109
  />
83
110
  )}
84
111
  </div>
85
112
  {otherParticipants.length > 0 && (
86
- <div className="str-video__speaker-layout--participants-bar-buttons-wrapper">
113
+ <div className="str-video__speaker-layout__participants-bar-buttons-wrapper">
87
114
  {scrollPosition && scrollPosition !== 'start' && (
88
115
  <IconButton
89
116
  onClick={scrollStartClickHandler}
90
117
  icon="caret-left"
91
- className="str-video__speaker-layout--participants-bar-button-left"
118
+ className="str-video__speaker-layout__participants-bar--button-left"
92
119
  />
93
120
  )}
94
121
  <div
95
- className="str-video__speaker-layout--participants-bar-wrapper"
122
+ className="str-video__speaker-layout__participants-bar-wrapper"
96
123
  ref={setScrollWrapper}
97
124
  >
98
- <div className="str-video__speaker-layout--participants-bar">
125
+ <div className="str-video__speaker-layout__participants-bar">
99
126
  {isSpeakerScreenSharing && (
100
127
  <div
101
- className="str-video__speaker-layout--participant-tile"
128
+ className="str-video__speaker-layout__participant-tile"
102
129
  key={participantInSpotlight.sessionId}
103
130
  >
104
- <ParticipantBox
131
+ <ParticipantView
105
132
  participant={participantInSpotlight}
106
- call={call}
107
133
  sinkId={localParticipant?.audioOutputDeviceId}
108
- toggleMenuPosition="top"
134
+ ParticipantViewUI={ParticipantViewUIBar}
135
+ VideoPlaceholder={VideoPlaceholder}
109
136
  />
110
137
  </div>
111
138
  )}
112
139
  {otherParticipants.map((participant) => (
113
140
  <div
114
- className="str-video__speaker-layout--participant-tile"
141
+ className="str-video__speaker-layout__participant-tile"
115
142
  key={participant.sessionId}
116
143
  >
117
- <ParticipantBox
144
+ <ParticipantView
118
145
  participant={participant}
119
- call={call}
120
146
  sinkId={localParticipant?.audioOutputDeviceId}
121
- toggleMenuPosition="top"
147
+ ParticipantViewUI={ParticipantViewUIBar}
148
+ VideoPlaceholder={VideoPlaceholder}
122
149
  />
123
150
  </div>
124
151
  ))}
@@ -128,7 +155,7 @@ export const SpeakerLayout = () => {
128
155
  <IconButton
129
156
  onClick={scrollEndClickHandler}
130
157
  icon="caret-right"
131
- className="str-video__speaker-layout--participants-bar-button-right"
158
+ className="str-video__speaker-layout__participants-bar--button-right"
132
159
  />
133
160
  )}
134
161
  </div>