@stream-io/video-react-sdk 1.30.0 → 1.31.0

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.
package/dist/index.es.js CHANGED
@@ -722,8 +722,8 @@ const useMenuContext = () => {
722
722
  return useContext(MenuContext);
723
723
  };
724
724
  const MenuPortal = ({ children, refs, }) => {
725
- const portalId = useMemo(() => `str-video-portal-${Math.random().toString(36).substring(2, 9)}`, []);
726
- return (jsxs(Fragment, { children: [jsx("div", { id: portalId, className: "str-video__portal" }), jsx(FloatingOverlay, { children: jsx(FloatingPortal, { id: portalId, children: jsx("div", { className: "str-video__portal-content", ref: refs.setFloating, children: children }) }) })] }));
725
+ const [portalRoot, setPortalRoot] = useState(null);
726
+ return (jsxs(Fragment, { children: [jsx("div", { ref: setPortalRoot, className: "str-video__portal" }), jsx(FloatingOverlay, { children: jsx(FloatingPortal, { root: portalRoot, children: jsx("div", { className: "str-video__portal-content", ref: refs.setFloating, children: children }) }) })] }));
727
727
  };
728
728
  const MenuToggle = ({ ToggleButton, placement = 'top-start', strategy = 'absolute', offset, visualType = MenuVisualType.MENU, children, onToggle, }) => {
729
729
  const [menuShown, setMenuShown] = useState(false);
@@ -1564,7 +1564,7 @@ const SpeakerTest = (props) => {
1564
1564
  const audioElementRef = useRef(null);
1565
1565
  const [isPlaying, setIsPlaying] = useState(false);
1566
1566
  const { t } = useI18n();
1567
- const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.30.0"}/assets/piano.mp3`, } = props;
1567
+ const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.31.0"}/assets/piano.mp3`, } = props;
1568
1568
  // Update audio output device when selection changes
1569
1569
  useEffect(() => {
1570
1570
  const audio = audioElementRef.current;
@@ -3145,12 +3145,60 @@ const Pip = (props) => {
3145
3145
  (screenSharingParticipant.isLocalParticipant ? (jsxs("div", { className: "str-video__pip-screen-share-local", children: [jsx(Icon, { icon: "screen-share-off" }), jsx("span", { className: "str-video__pip-screen-share-local__title", children: t('You are presenting your screen') })] })) : (jsx(ParticipantView, { participant: screenSharingParticipant, trackType: "screenShareTrack", muteAudio: true, mirror: false, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }))), participants.map((participant) => (jsx(ParticipantView, { participant: participant, muteAudio: true, mirror: mirror, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }, participant.sessionId)))] }));
3146
3146
  };
3147
3147
  Pip.displayName = 'PipLayout.Pip';
3148
+
3148
3149
  const Host = () => {
3149
3150
  const remoteParticipants = useRawRemoteParticipants();
3150
3151
  return jsx(ParticipantsAudio, { participants: remoteParticipants });
3151
3152
  };
3152
3153
  Host.displayName = 'PipLayout.Host';
3153
- const PipLayout = { Pip, Host };
3154
+
3155
+ const getGridDensity = (count) => {
3156
+ if (count === 1)
3157
+ return 'single';
3158
+ if (count <= 5)
3159
+ return 'small';
3160
+ if (count <= 9)
3161
+ return 'medium';
3162
+ if (count <= 16)
3163
+ return 'large';
3164
+ return 'overflow';
3165
+ };
3166
+ /**
3167
+ * A grid-based PIP layout with pagination support.
3168
+ * Use this when you need a more structured grid view in PIP mode.
3169
+ */
3170
+ const Grid = (props) => {
3171
+ const { t } = useI18n();
3172
+ const { excludeLocalParticipant = false, filterParticipants, mirrorLocalParticipantVideo = true, groupSize = 9, pageArrowsVisible = true, VideoPlaceholder, ParticipantViewUI = DefaultParticipantViewUI, } = props;
3173
+ const [page, setPage] = useState(0);
3174
+ const [wrapperElement, setWrapperElement] = useState(null);
3175
+ const call = useCall();
3176
+ const participants = useFilteredParticipants({
3177
+ excludeLocalParticipant,
3178
+ filterParticipants,
3179
+ });
3180
+ const screenSharingParticipant = participants.find((p) => hasScreenShare(p));
3181
+ usePaginatedLayoutSortPreset(call);
3182
+ useEffect(() => {
3183
+ if (!wrapperElement || !call)
3184
+ return;
3185
+ return call.setViewport(wrapperElement);
3186
+ }, [wrapperElement, call]);
3187
+ const participantGroups = useMemo(() => chunk(participants, groupSize), [participants, groupSize]);
3188
+ const pageCount = participantGroups.length;
3189
+ if (page > pageCount - 1) {
3190
+ setPage(Math.max(0, pageCount - 1));
3191
+ }
3192
+ const selectedGroup = participantGroups[page];
3193
+ const mirror = mirrorLocalParticipantVideo ? undefined : false;
3194
+ if (!call)
3195
+ return null;
3196
+ return (jsxs("div", { className: "str-video__pip-layout str-video__pip-layout--grid", ref: setWrapperElement, children: [screenSharingParticipant &&
3197
+ (screenSharingParticipant.isLocalParticipant ? (jsxs("div", { className: "str-video__pip-screen-share-local", children: [jsx(Icon, { icon: "screen-share-off" }), jsx("span", { className: "str-video__pip-screen-share-local__title", children: t('You are presenting your screen') })] })) : (jsx(ParticipantView, { participant: screenSharingParticipant, trackType: "screenShareTrack", muteAudio: true, mirror: false, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }))), jsxs("div", { className: "str-video__pip-layout__grid-container", children: [pageArrowsVisible && page > 0 && (jsx(IconButton, { icon: "caret-left", onClick: () => setPage((currentPage) => Math.max(0, currentPage - 1)), className: "str-video__pip-layout__pagination-button str-video__pip-layout__pagination-button--left" })), selectedGroup && (jsx("div", { className: clsx('str-video__pip-layout__grid', `str-video__pip-layout__grid--${getGridDensity(selectedGroup.length)}`), children: selectedGroup.map((participant) => (jsx(ParticipantView, { participant: participant, muteAudio: true, mirror: mirror, VideoPlaceholder: VideoPlaceholder, ParticipantViewUI: ParticipantViewUI }, participant.sessionId))) })), pageArrowsVisible && page < pageCount - 1 && (jsx(IconButton, { icon: "caret-right", onClick: () => setPage((currentPage) => Math.min(pageCount - 1, currentPage + 1)), className: "str-video__pip-layout__pagination-button str-video__pip-layout__pagination-button--right" }))] })] }));
3198
+ };
3199
+ Grid.displayName = 'PipLayout.Grid';
3200
+
3201
+ const PipLayout = { Pip, Host, Grid };
3154
3202
 
3155
3203
  const LivestreamPlayer = (props) => {
3156
3204
  const { callType, callId, children, ...restProps } = props;
@@ -3233,7 +3281,7 @@ const checkCanJoinEarly = (startsAt, joinAheadTimeSeconds) => {
3233
3281
  return Date.now() >= +startsAt - (joinAheadTimeSeconds ?? 0) * 1000;
3234
3282
  };
3235
3283
 
3236
- const [major, minor, patch] = ("1.30.0").split('.');
3284
+ const [major, minor, patch] = ("1.31.0").split('.');
3237
3285
  setSdkInfo({
3238
3286
  type: SfuModels.SdkType.REACT,
3239
3287
  major,