@azure/communication-react 1.5.1-alpha-202302250014 → 1.5.1-alpha-202303020021

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 (42) hide show
  1. package/dist/communication-react.d.ts +12 -0
  2. package/dist/dist-cjs/communication-react/index.js +529 -216
  3. package/dist/dist-cjs/communication-react/index.js.map +1 -1
  4. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js +1 -1
  5. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js.map +1 -1
  6. package/dist/dist-esm/communication-react/src/index.d.ts +1 -0
  7. package/dist/dist-esm/communication-react/src/index.js.map +1 -1
  8. package/dist/dist-esm/react-components/src/components/ResponsiveVerticalGallery.d.ts +29 -0
  9. package/dist/dist-esm/react-components/src/components/ResponsiveVerticalGallery.js +77 -0
  10. package/dist/dist-esm/react-components/src/components/ResponsiveVerticalGallery.js.map +1 -0
  11. package/dist/dist-esm/react-components/src/components/VerticalGallery.d.ts +50 -0
  12. package/dist/dist-esm/react-components/src/components/VerticalGallery.js +88 -0
  13. package/dist/dist-esm/react-components/src/components/VerticalGallery.js.map +1 -0
  14. package/dist/dist-esm/react-components/src/components/VideoGallery/DefaultLayout.js +19 -13
  15. package/dist/dist-esm/react-components/src/components/VideoGallery/DefaultLayout.js.map +1 -1
  16. package/dist/dist-esm/react-components/src/components/VideoGallery/FloatingLocalVideo.d.ts +10 -3
  17. package/dist/dist-esm/react-components/src/components/VideoGallery/FloatingLocalVideo.js +6 -8
  18. package/dist/dist-esm/react-components/src/components/VideoGallery/FloatingLocalVideo.js.map +1 -1
  19. package/dist/dist-esm/react-components/src/components/VideoGallery/FloatingLocalVideoLayout.js +32 -16
  20. package/dist/dist-esm/react-components/src/components/VideoGallery/FloatingLocalVideoLayout.js.map +1 -1
  21. package/dist/dist-esm/react-components/src/components/VideoGallery/Layout.d.ts +6 -0
  22. package/dist/dist-esm/react-components/src/components/VideoGallery/Layout.js.map +1 -1
  23. package/dist/dist-esm/react-components/src/components/VideoGallery/{VideoGalleryResponsiveHorizontalGallery.d.ts → OverflowGallery.d.ts} +5 -3
  24. package/dist/dist-esm/react-components/src/components/VideoGallery/OverflowGallery.js +46 -0
  25. package/dist/dist-esm/react-components/src/components/VideoGallery/OverflowGallery.js.map +1 -0
  26. package/dist/dist-esm/react-components/src/components/VideoGallery/styles/FloatingLocalVideo.styles.d.ts +20 -3
  27. package/dist/dist-esm/react-components/src/components/VideoGallery/styles/FloatingLocalVideo.styles.js +11 -6
  28. package/dist/dist-esm/react-components/src/components/VideoGallery/styles/FloatingLocalVideo.styles.js.map +1 -1
  29. package/dist/dist-esm/react-components/src/components/VideoGallery/styles/VideoGalleryResponsiveVerticalGallery.styles.d.ts +40 -0
  30. package/dist/dist-esm/react-components/src/components/VideoGallery/styles/VideoGalleryResponsiveVerticalGallery.styles.js +46 -0
  31. package/dist/dist-esm/react-components/src/components/VideoGallery/styles/VideoGalleryResponsiveVerticalGallery.styles.js.map +1 -0
  32. package/dist/dist-esm/react-components/src/components/VideoGallery.d.ts +11 -0
  33. package/dist/dist-esm/react-components/src/components/VideoGallery.js +7 -3
  34. package/dist/dist-esm/react-components/src/components/VideoGallery.js.map +1 -1
  35. package/dist/dist-esm/react-components/src/components/index.d.ts +1 -0
  36. package/dist/dist-esm/react-components/src/components/index.js.map +1 -1
  37. package/dist/dist-esm/react-components/src/components/styles/VerticalGallery.styles.d.ts +32 -0
  38. package/dist/dist-esm/react-components/src/components/styles/VerticalGallery.styles.js +66 -0
  39. package/dist/dist-esm/react-components/src/components/styles/VerticalGallery.styles.js.map +1 -0
  40. package/package.json +8 -8
  41. package/dist/dist-esm/react-components/src/components/VideoGallery/VideoGalleryResponsiveHorizontalGallery.js +0 -19
  42. package/dist/dist-esm/react-components/src/components/VideoGallery/VideoGalleryResponsiveHorizontalGallery.js.map +0 -1
@@ -161,7 +161,7 @@ const _toCommunicationIdentifier = (id) => {
161
161
  // Copyright (c) Microsoft Corporation.
162
162
  // Licensed under the MIT license.
163
163
  // GENERATED FILE. DO NOT EDIT MANUALLY.
164
- var telemetryVersion = '1.5.1-alpha-202302250014';
164
+ var telemetryVersion = '1.5.1-alpha-202303020021';
165
165
 
166
166
  // Copyright (c) Microsoft Corporation.
167
167
  /**
@@ -9203,176 +9203,6 @@ const FloatingLocalCameraCycleButton = (props) => {
9203
9203
  (localVideoCameraCycleButtonProps === null || localVideoCameraCycleButtonProps === void 0 ? void 0 : localVideoCameraCycleButtonProps.onSelectCamera) !== undefined && (React__default['default'].createElement(LocalVideoCameraCycleButton, { cameras: localVideoCameraCycleButtonProps.cameras, selectedCamera: localVideoCameraCycleButtonProps.selectedCamera, onSelectCamera: localVideoCameraCycleButtonProps.onSelectCamera, label: localVideoCameraSwitcherLabel, ariaDescription: ariaDescription }))));
9204
9204
  };
9205
9205
 
9206
- // Copyright (c) Microsoft Corporation.
9207
- /**
9208
- * @private
9209
- */
9210
- react.mergeStyles({ position: 'relative', width: '100%', height: '100%' });
9211
- /**
9212
- * Small floating modal width and height in rem for small screen
9213
- */
9214
- const SMALL_FLOATING_MODAL_SIZE_PX = { width: 58, height: 104 };
9215
- /**
9216
- * Large floating modal width and height in rem for large screen
9217
- * Aspect ratio: 16:9
9218
- */
9219
- const LARGE_FLOATING_MODAL_SIZE_PX = { width: 215, height: 120 };
9220
- /**
9221
- * @private
9222
- * z-index to ensure that the local video tile is above the video gallery.
9223
- */
9224
- const LOCAL_VIDEO_TILE_ZINDEX = 2;
9225
- /**
9226
- * @private
9227
- */
9228
- const localVideoTileContainerStyle = (theme, isNarrow) => {
9229
- return Object.assign({ minWidth: isNarrow ? _pxToRem(SMALL_FLOATING_MODAL_SIZE_PX.width) : _pxToRem(LARGE_FLOATING_MODAL_SIZE_PX.width), minHeight: isNarrow ? _pxToRem(SMALL_FLOATING_MODAL_SIZE_PX.height) : _pxToRem(LARGE_FLOATING_MODAL_SIZE_PX.height), position: 'absolute', bottom: _pxToRem(localVideoTileOuterPaddingPX), borderRadius: theme.effects.roundedCorner4, overflow: 'hidden' }, (theme.rtl
9230
- ? { left: _pxToRem(localVideoTileOuterPaddingPX) }
9231
- : { right: _pxToRem(localVideoTileOuterPaddingPX) }));
9232
- };
9233
- /**
9234
- * @private
9235
- */
9236
- const localVideoTileWithControlsContainerStyle = (theme, isNarrow) => {
9237
- return react.concatStyleSets(localVideoTileContainerStyle(theme, isNarrow), {
9238
- root: { boxShadow: theme.effects.elevation8 }
9239
- });
9240
- };
9241
- /**
9242
- * @private
9243
- */
9244
- const floatingLocalVideoModalStyle = (theme, isNarrow) => {
9245
- return react.concatStyleSets({
9246
- main: localVideoTileContainerStyle(theme, isNarrow)
9247
- }, {
9248
- main: {
9249
- boxShadow: theme.effects.elevation8,
9250
- ':focus-within': {
9251
- boxShadow: theme.effects.elevation16,
9252
- border: `${_pxToRem(2)} solid ${theme.palette.neutralPrimary}`
9253
- }
9254
- }
9255
- }, localVideoModalStyles);
9256
- };
9257
- /**
9258
- * Padding equal to the amount the modal should stay inside the bounds of the container.
9259
- * i.e. if this is 8px, the modal should always be at least 8px inside the container at all times on all sides.
9260
- * @private
9261
- */
9262
- const localVideoTileOuterPaddingPX = 8;
9263
- /**
9264
- * @private
9265
- */
9266
- const floatingLocalVideoTileStyle = {
9267
- root: {
9268
- position: 'absolute',
9269
- zIndex: LOCAL_VIDEO_TILE_ZINDEX,
9270
- height: '100%',
9271
- width: '100%'
9272
- }
9273
- };
9274
- /**
9275
- * Styles for the local video tile modal when it is focused, will cause keyboard move icon to appear over video
9276
- * @private
9277
- */
9278
- const localVideoModalStyles = {
9279
- keyboardMoveIconContainer: {
9280
- zIndex: LOCAL_VIDEO_TILE_ZINDEX + 1 // zIndex to set the keyboard movement Icon above the other layers in the video tile.
9281
- }
9282
- };
9283
-
9284
- // Copyright (c) Microsoft Corporation.
9285
- /**
9286
- * @private
9287
- */
9288
- const horizontalGalleryContainerStyle = (shouldFloatLocalVideo, isNarrow) => {
9289
- return {
9290
- minHeight: isNarrow
9291
- ? `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`
9292
- : `${LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9293
- width: shouldFloatLocalVideo
9294
- ? isNarrow
9295
- ? `calc(100% - ${_pxToRem(SMALL_FLOATING_MODAL_SIZE_PX.width)})`
9296
- : `calc(100% - ${_pxToRem(LARGE_FLOATING_MODAL_SIZE_PX.width)})`
9297
- : '100%',
9298
- paddingRight: '0.5rem'
9299
- };
9300
- };
9301
- /**
9302
- * @private
9303
- */
9304
- const horizontalGalleryStyle = (isNarrow) => {
9305
- return {
9306
- children: isNarrow ? SMALL_HORIZONTAL_GALLERY_TILE_STYLE : LARGE_HORIZONTAL_GALLERY_TILE_STYLE
9307
- };
9308
- };
9309
- /**
9310
- * Small horizontal gallery tile size in rem
9311
- * @private
9312
- */
9313
- const SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM = { height: 6.5, width: 6.5 };
9314
- /**
9315
- * Large horizontal gallery tile size in rem
9316
- * @private
9317
- */
9318
- const LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM = { height: 7.5, width: 10 };
9319
- /**
9320
- * @private
9321
- */
9322
- const SMALL_HORIZONTAL_GALLERY_TILE_STYLE = {
9323
- minHeight: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9324
- minWidth: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.width}rem`,
9325
- maxHeight: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9326
- maxWidth: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.width}rem`
9327
- };
9328
- /**
9329
- * @private
9330
- */
9331
- const LARGE_HORIZONTAL_GALLERY_TILE_STYLE = {
9332
- minHeight: `${LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9333
- minWidth: `${LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.width}rem`,
9334
- maxHeight: `${LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9335
- maxWidth: `${LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.width}rem`
9336
- };
9337
-
9338
- // Copyright (c) Microsoft Corporation.
9339
- /**
9340
- * @private
9341
- */
9342
- const scrollableHorizontalGalleryStyles = {
9343
- root: {
9344
- width: '100%',
9345
- minHeight: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9346
- paddingRight: '0.5rem',
9347
- '> *': SMALL_HORIZONTAL_GALLERY_TILE_STYLE
9348
- }
9349
- };
9350
- /**
9351
- * @private
9352
- */
9353
- const scrollableHorizontalGalleryContainerStyles = react.mergeStyles({
9354
- display: 'flex',
9355
- width: `calc(100% - ${SMALL_FLOATING_MODAL_SIZE_PX.width}px)`,
9356
- minHeight: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9357
- overflow: 'scroll',
9358
- '-ms-overflow-style': 'none',
9359
- 'scrollbar-width': 'none',
9360
- '::-webkit-scrollbar': { display: 'none' }
9361
- });
9362
-
9363
- // Copyright (c) Microsoft Corporation.
9364
- /**
9365
- * Component to display elements horizontally in a scrollable container
9366
- * @private
9367
- */
9368
- const ScrollableHorizontalGallery = (props) => {
9369
- const { horizontalGalleryElements } = props;
9370
- const ref = React.useRef();
9371
- const { events: dragabbleEvents } = reactUseDraggableScroll.useDraggable(ref);
9372
- return (React__default['default'].createElement("div", Object.assign({ ref: ref }, dragabbleEvents, { className: scrollableHorizontalGalleryContainerStyles }),
9373
- React__default['default'].createElement(react.Stack, { "data-ui-id": "scrollable-horizontal-gallery", horizontal: true, styles: scrollableHorizontalGalleryStyles, tokens: { childrenGap: '0.5rem' } }, horizontalGalleryElements)));
9374
- };
9375
-
9376
9206
  // Copyright (c) Microsoft Corporation.
9377
9207
  // Licensed under the MIT license.
9378
9208
  /**
@@ -9562,7 +9392,7 @@ const HORIZONTAL_GALLERY_BUTTON_WIDTH = 1.75;
9562
9392
  /**
9563
9393
  * @private
9564
9394
  */
9565
- const leftRightButtonStyles = (theme) => {
9395
+ const leftRightButtonStyles$1 = (theme) => {
9566
9396
  return {
9567
9397
  background: 'none',
9568
9398
  padding: 0,
@@ -9580,7 +9410,7 @@ const HORIZONTAL_GALLERY_GAP = 0.5;
9580
9410
  /**
9581
9411
  * @private
9582
9412
  */
9583
- const rootStyle = {
9413
+ const rootStyle$1 = {
9584
9414
  height: '100%',
9585
9415
  width: '100%',
9586
9416
  gap: `${HORIZONTAL_GALLERY_GAP}rem`
@@ -9588,7 +9418,7 @@ const rootStyle = {
9588
9418
  /**
9589
9419
  * @private
9590
9420
  */
9591
- const childrenContainerStyle = {
9421
+ const childrenContainerStyle$1 = {
9592
9422
  height: '100%',
9593
9423
  gap: `${HORIZONTAL_GALLERY_GAP}rem`
9594
9424
  };
@@ -9645,14 +9475,14 @@ const HorizontalGallery = (props) => {
9645
9475
  const showButtons = numberOfChildren > childrenPerPage;
9646
9476
  const disablePreviousButton = page === 0;
9647
9477
  const disableNextButton = page === lastPage;
9648
- return (React__default['default'].createElement(react.Stack, { horizontal: true, className: react.mergeStyles(rootStyle, (_a = props.styles) === null || _a === void 0 ? void 0 : _a.root) },
9478
+ return (React__default['default'].createElement(react.Stack, { horizontal: true, className: react.mergeStyles(rootStyle$1, (_a = props.styles) === null || _a === void 0 ? void 0 : _a.root) },
9649
9479
  showButtons && (React__default['default'].createElement(HorizontalGalleryNavigationButton, { key: "previous-nav-button", icon: React__default['default'].createElement(react.Icon, { iconName: "HorizontalGalleryLeftButton" }), styles: styles === null || styles === void 0 ? void 0 : styles.previousButton, onClick: () => setPage(Math.max(0, Math.min(lastPage, page - 1))), disabled: disablePreviousButton, identifier: ids.horizontalGalleryLeftNavButton })),
9650
- React__default['default'].createElement(react.Stack, { horizontal: true, className: react.mergeStyles(childrenContainerStyle, { '> *': (_b = props.styles) === null || _b === void 0 ? void 0 : _b.children }) }, childrenOnCurrentPage),
9480
+ React__default['default'].createElement(react.Stack, { horizontal: true, className: react.mergeStyles(childrenContainerStyle$1, { '> *': (_b = props.styles) === null || _b === void 0 ? void 0 : _b.children }) }, childrenOnCurrentPage),
9651
9481
  showButtons && (React__default['default'].createElement(HorizontalGalleryNavigationButton, { key: "next-nav-button", icon: React__default['default'].createElement(react.Icon, { iconName: "HorizontalGalleryRightButton" }), styles: styles === null || styles === void 0 ? void 0 : styles.nextButton, onClick: () => setPage(Math.min(lastPage, page + 1)), disabled: disableNextButton, identifier: ids.horizontalGalleryRightNavButton }))));
9652
9482
  };
9653
9483
  const HorizontalGalleryNavigationButton = (props) => {
9654
9484
  const theme = useTheme();
9655
- return (React__default['default'].createElement(react.DefaultButton, { className: react.mergeStyles(leftRightButtonStyles(theme), props.styles), onClick: props.onClick, disabled: props.disabled, "data-ui-id": props.identifier }, props.icon));
9485
+ return (React__default['default'].createElement(react.DefaultButton, { className: react.mergeStyles(leftRightButtonStyles$1(theme), props.styles), onClick: props.onClick, disabled: props.disabled, "data-ui-id": props.identifier }, props.icon));
9656
9486
  };
9657
9487
 
9658
9488
  // Copyright (c) Microsoft Corporation.
@@ -9666,7 +9496,7 @@ const ResponsiveHorizontalGallery = (props) => {
9666
9496
  const containerWidth = _useContainerWidth(containerRef);
9667
9497
  const leftPadding = containerRef.current ? parseFloat(getComputedStyle(containerRef.current).paddingLeft) : 0;
9668
9498
  const rightPadding = containerRef.current ? parseFloat(getComputedStyle(containerRef.current).paddingRight) : 0;
9669
- const childrenPerPage = calculateChildrenPerPage({
9499
+ const childrenPerPage = calculateChildrenPerPage$1({
9670
9500
  numberOfChildren: React__default['default'].Children.count(props.children),
9671
9501
  containerWidth: (containerWidth !== null && containerWidth !== void 0 ? containerWidth : 0) - leftPadding - rightPadding,
9672
9502
  childWidthRem,
@@ -9680,7 +9510,7 @@ const ResponsiveHorizontalGallery = (props) => {
9680
9510
  * Helper function to calculate children per page for HorizontalGallery based on width of container, child, buttons, and
9681
9511
  * gaps in between
9682
9512
  */
9683
- const calculateChildrenPerPage = (args) => {
9513
+ const calculateChildrenPerPage$1 = (args) => {
9684
9514
  const { numberOfChildren, containerWidth, buttonWidthRem, childWidthRem, gapWidthRem } = args;
9685
9515
  const childWidth = _convertRemToPx(childWidthRem);
9686
9516
  const gapWidth = _convertRemToPx(gapWidthRem);
@@ -9713,17 +9543,474 @@ const calculateChildrenPerPage = (args) => {
9713
9543
  return Math.floor((childrenSpace + gapWidth) / (childWidth + gapWidth));
9714
9544
  };
9715
9545
 
9546
+ // Copyright (c) Microsoft Corporation.
9547
+ // Licensed under the MIT license.
9548
+ /**
9549
+ * Vertical Gallery gap size in rem between tiles and buttons
9550
+ *
9551
+ * @private
9552
+ */
9553
+ const VERTICAL_GALLERY_GAP = 0.5;
9554
+ /**
9555
+ * @private
9556
+ */
9557
+ const childrenContainerStyle = (pageControlBarHeight) => {
9558
+ return {
9559
+ width: '100%',
9560
+ height: `calc(100% - ${pageControlBarHeight + VERTICAL_GALLERY_GAP}rem)`,
9561
+ gap: `${VERTICAL_GALLERY_GAP}rem`
9562
+ };
9563
+ };
9564
+ /**
9565
+ * @private
9566
+ */
9567
+ const rootStyle = {
9568
+ height: '100%',
9569
+ width: '100%',
9570
+ gap: `${VERTICAL_GALLERY_GAP}rem`,
9571
+ position: 'relative'
9572
+ };
9573
+ /**
9574
+ * @private
9575
+ */
9576
+ const pageNavigationControlBarContainerStyle = {
9577
+ height: '2rem',
9578
+ width: '100%',
9579
+ position: 'absolute',
9580
+ bottom: '0'
9581
+ };
9582
+ /**
9583
+ * @private
9584
+ */
9585
+ const leftRightButtonStyles = (theme) => {
9586
+ return {
9587
+ background: 'none',
9588
+ padding: 0,
9589
+ height: 'auto',
9590
+ borderRadius: theme.effects.roundedCorner4,
9591
+ border: 'none',
9592
+ minWidth: '2rem'
9593
+ };
9594
+ };
9595
+ /**
9596
+ * @private
9597
+ */
9598
+ const participantPageCounter = {
9599
+ lineHeight: '2rem',
9600
+ width: '100%',
9601
+ textAlign: 'center'
9602
+ };
9603
+ /**
9604
+ * @private
9605
+ */
9606
+ const navIconStyles = {
9607
+ root: {
9608
+ lineHeight: '0'
9609
+ }
9610
+ };
9611
+
9612
+ // Copyright (c) Microsoft Corporation.
9613
+ /**
9614
+ * VerticalGallery is a overflow gallery for participants in the {@link VideoGallery} component. Stacks
9615
+ * participants on the Y-axis of the VideoGallery for better use of horizontal space.
9616
+ *
9617
+ * @beta
9618
+ */
9619
+ const VerticalGallery = (props) => {
9620
+ const { children, styles, childrenPerPage } = props;
9621
+ const [page, setPage] = React.useState(1);
9622
+ const [buttonState, setButtonState] = React.useState({ previous: true, next: true });
9623
+ const numberOfChildren = React__default['default'].Children.count(children);
9624
+ const lastPage = Math.ceil(numberOfChildren / childrenPerPage);
9625
+ const paginatedChildren = React.useMemo(() => {
9626
+ return bucketize(React__default['default'].Children.toArray(children), childrenPerPage);
9627
+ }, [children, childrenPerPage]);
9628
+ const firstIndexOfCurrentPage = (page - 1) * childrenPerPage;
9629
+ const clippedPage = firstIndexOfCurrentPage < numberOfChildren - 1 ? page : lastPage;
9630
+ const childrenOnCurrentPage = paginatedChildren[clippedPage - 1];
9631
+ const showButtons = numberOfChildren > childrenPerPage;
9632
+ const onPreviousButtonClick = () => {
9633
+ setPage(page - 1);
9634
+ };
9635
+ const onNextButtonClick = () => {
9636
+ setPage(page + 1);
9637
+ };
9638
+ if (page > lastPage && lastPage > 0) {
9639
+ setPage(lastPage);
9640
+ }
9641
+ React.useEffect(() => {
9642
+ if (page > 1 && page < lastPage && showButtons) {
9643
+ // we are somewhere in between first and last pages.
9644
+ setButtonState({ previous: false, next: false });
9645
+ }
9646
+ else if (page === 1 && showButtons) {
9647
+ // we are on the first page.
9648
+ setButtonState({ previous: true, next: false });
9649
+ }
9650
+ else if (page === lastPage && showButtons) {
9651
+ // we are on the last page.
9652
+ setButtonState({ previous: false, next: true });
9653
+ }
9654
+ }, [page, numberOfChildren, lastPage, showButtons]);
9655
+ const childContainerStyle = React.useMemo(() => {
9656
+ return { root: childrenContainerStyle(2) };
9657
+ }, []);
9658
+ const childrenStyles = React.useMemo(() => {
9659
+ return { root: styles === null || styles === void 0 ? void 0 : styles.children };
9660
+ }, [styles === null || styles === void 0 ? void 0 : styles.children]);
9661
+ if (childrenPerPage <= 0) {
9662
+ return React__default['default'].createElement(React__default['default'].Fragment, null);
9663
+ }
9664
+ return (React__default['default'].createElement(react.Stack, { className: react.mergeStyles(rootStyle, styles === null || styles === void 0 ? void 0 : styles.root) },
9665
+ React__default['default'].createElement(react.Stack, { styles: childContainerStyle }, childrenOnCurrentPage.map((child, i) => {
9666
+ return (React__default['default'].createElement(react.Stack.Item, { key: i, styles: childrenStyles }, child));
9667
+ })),
9668
+ showButtons && (React__default['default'].createElement(VerticalGalleryControlBar, { buttonsDisabled: buttonState, onPreviousButtonClick: onPreviousButtonClick, onNextButtonClick: onNextButtonClick, totalPages: lastPage, currentPage: page }))));
9669
+ };
9670
+ const VerticalGalleryControlBar = (props) => {
9671
+ const { onNextButtonClick, onPreviousButtonClick, buttonsDisabled, currentPage, totalPages, styles } = props;
9672
+ const theme = useTheme();
9673
+ const pageCounterContainerStyles = React.useMemo(() => {
9674
+ return react.mergeStyles(pageNavigationControlBarContainerStyle, styles === null || styles === void 0 ? void 0 : styles.root);
9675
+ }, [styles === null || styles === void 0 ? void 0 : styles.root]);
9676
+ const previousButtonSyles = React.useMemo(() => {
9677
+ return react.mergeStyles(leftRightButtonStyles(theme), styles === null || styles === void 0 ? void 0 : styles.previousButton);
9678
+ }, [styles === null || styles === void 0 ? void 0 : styles.previousButton, theme]);
9679
+ const pageCounterStyles = React.useMemo(() => {
9680
+ return react.mergeStyles(participantPageCounter, styles === null || styles === void 0 ? void 0 : styles.counter);
9681
+ }, [styles === null || styles === void 0 ? void 0 : styles.counter]);
9682
+ const nextButtonsStyles = React.useMemo(() => {
9683
+ return react.mergeStyles(leftRightButtonStyles(theme), styles === null || styles === void 0 ? void 0 : styles.nextButton);
9684
+ }, [styles === null || styles === void 0 ? void 0 : styles.nextButton, theme]);
9685
+ const controlBarSpacing = { childrenGap: '0.5rem' };
9686
+ return (React__default['default'].createElement(react.Stack, { horizontalAlign: "center", tokens: controlBarSpacing, horizontal: true, className: pageCounterContainerStyles },
9687
+ React__default['default'].createElement(react.DefaultButton, { className: previousButtonSyles, onClick: onPreviousButtonClick, disabled: buttonsDisabled === null || buttonsDisabled === void 0 ? void 0 : buttonsDisabled.previous },
9688
+ React__default['default'].createElement(react.Icon, { iconName: "VerticalGalleryLeftButton", styles: navIconStyles })),
9689
+ React__default['default'].createElement(react.Text, { className: pageCounterStyles }, `${currentPage} / ${totalPages}`),
9690
+ React__default['default'].createElement(react.DefaultButton, { className: nextButtonsStyles, onClick: onNextButtonClick, disabled: buttonsDisabled === null || buttonsDisabled === void 0 ? void 0 : buttonsDisabled.next },
9691
+ React__default['default'].createElement(react.Icon, { iconName: "VerticalGalleryRightButton", styles: navIconStyles }))));
9692
+ };
9693
+
9694
+ // Copyright (c) Microsoft Corporation.
9695
+ /**
9696
+ * @private
9697
+ */
9698
+ react.mergeStyles({ position: 'relative', width: '100%', height: '100%' });
9699
+ /**
9700
+ * Small floating modal width and height in rem for small screen
9701
+ */
9702
+ const SMALL_FLOATING_MODAL_SIZE_PX = { width: 58, height: 104 };
9703
+ /**
9704
+ * Large floating modal width and height in rem for large screen
9705
+ * Aspect ratio: 16:9
9706
+ */
9707
+ const LARGE_FLOATING_MODAL_SIZE_PX = { width: 215, height: 120 };
9708
+ /**
9709
+ * Vertical gallery floating modal width and height in rem
9710
+ * Aspect ratio: 16:9
9711
+ */
9712
+ const VERTICAL_GALLERY_FLOATING_MODAL_SIZE_PX = { width: 144, height: 81 };
9713
+ /**
9714
+ * @private
9715
+ * z-index to ensure that the local video tile is above the video gallery.
9716
+ */
9717
+ const LOCAL_VIDEO_TILE_ZINDEX = 2;
9718
+ /**
9719
+ * @private
9720
+ */
9721
+ const localVideoTileContainerStyle = (theme, localVideoTileSize) => {
9722
+ return Object.assign({ minWidth: _pxToRem(localVideoTileSize.width), minHeight: _pxToRem(localVideoTileSize.height), position: 'absolute', bottom: _pxToRem(localVideoTileOuterPaddingPX), borderRadius: theme.effects.roundedCorner4, overflow: 'hidden' }, (theme.rtl
9723
+ ? { left: _pxToRem(localVideoTileOuterPaddingPX) }
9724
+ : { right: _pxToRem(localVideoTileOuterPaddingPX) }));
9725
+ };
9726
+ /**
9727
+ * @private
9728
+ */
9729
+ const localVideoTileWithControlsContainerStyle = (theme, localVideoTileSize) => {
9730
+ return react.concatStyleSets(localVideoTileContainerStyle(theme, localVideoTileSize), {
9731
+ root: { boxShadow: theme.effects.elevation8 }
9732
+ });
9733
+ };
9734
+ /**
9735
+ * @private
9736
+ */
9737
+ const floatingLocalVideoModalStyle = (theme, modalSize) => {
9738
+ return react.concatStyleSets({
9739
+ main: localVideoTileContainerStyle(theme, modalSize)
9740
+ }, {
9741
+ main: {
9742
+ boxShadow: theme.effects.elevation8,
9743
+ ':focus-within': {
9744
+ boxShadow: theme.effects.elevation16,
9745
+ border: `${_pxToRem(2)} solid ${theme.palette.neutralPrimary}`
9746
+ }
9747
+ }
9748
+ }, localVideoModalStyles);
9749
+ };
9750
+ /**
9751
+ * Padding equal to the amount the modal should stay inside the bounds of the container.
9752
+ * i.e. if this is 8px, the modal should always be at least 8px inside the container at all times on all sides.
9753
+ * @private
9754
+ */
9755
+ const localVideoTileOuterPaddingPX = 8;
9756
+ /**
9757
+ * @private
9758
+ */
9759
+ const floatingLocalVideoTileStyle = {
9760
+ root: {
9761
+ position: 'absolute',
9762
+ zIndex: LOCAL_VIDEO_TILE_ZINDEX,
9763
+ height: '100%',
9764
+ width: '100%'
9765
+ }
9766
+ };
9767
+ /**
9768
+ * Styles for the local video tile modal when it is focused, will cause keyboard move icon to appear over video
9769
+ * @private
9770
+ */
9771
+ const localVideoModalStyles = {
9772
+ keyboardMoveIconContainer: {
9773
+ zIndex: LOCAL_VIDEO_TILE_ZINDEX + 1 // zIndex to set the keyboard movement Icon above the other layers in the video tile.
9774
+ }
9775
+ };
9776
+
9777
+ // Copyright (c) Microsoft Corporation.
9778
+ /**
9779
+ * VerticalGallery tile size in rem:
9780
+ *
9781
+ * min - smallest possible size of the tile (90px)
9782
+ * max - Largest size we want the vertical tiles (144px)
9783
+ *
9784
+ * @private
9785
+ */
9786
+ const VERTICAL_GALLERY_TILE_SIZE_REM = { minHeight: 5.625, maxHeight: 9, width: 9 };
9787
+ /**
9788
+ * Styles for the VerticalGallery's container set in parent.
9789
+ *
9790
+ * width is being increased by 1rem to account for the gap width desired for the VerticalGallery.
9791
+ *
9792
+ * @param shouldFloatLocalVideo whether rendered in floating layout or not
9793
+ * @returns Style set for VerticalGallery container.
9794
+ */
9795
+ const verticalGalleryContainerStyle = (shouldFloatLocalVideo) => {
9796
+ return {
9797
+ width: `${VERTICAL_GALLERY_TILE_SIZE_REM.width}rem`,
9798
+ height: shouldFloatLocalVideo ? `calc(100% - ${_pxToRem(VERTICAL_GALLERY_FLOATING_MODAL_SIZE_PX.height)})` : '100%',
9799
+ paddingBottom: '0.5rem'
9800
+ };
9801
+ };
9802
+ /**
9803
+ * @private
9804
+ */
9805
+ const VERTICAL_GALLERY_TILE_STYLE = {
9806
+ minHeight: `${VERTICAL_GALLERY_TILE_SIZE_REM.minHeight}rem`,
9807
+ minWidth: `${VERTICAL_GALLERY_TILE_SIZE_REM.width}rem`,
9808
+ maxHeight: `${VERTICAL_GALLERY_TILE_SIZE_REM.maxHeight}rem`,
9809
+ maxWidth: `${VERTICAL_GALLERY_TILE_SIZE_REM.width}rem`,
9810
+ width: '100%',
9811
+ height: '100%'
9812
+ };
9813
+ /**
9814
+ * @private
9815
+ */
9816
+ const verticalGalleryStyle = {
9817
+ children: VERTICAL_GALLERY_TILE_STYLE
9818
+ };
9819
+
9820
+ // Copyright (c) Microsoft Corporation.
9821
+ /**
9822
+ * Responsive container for the VerticalGallery Component. Performs calculations for number of children
9823
+ * for the VerticalGallery
9824
+ * @param props
9825
+ *
9826
+ * @beta
9827
+ */
9828
+ const ResponsiveVerticalGallery = (props) => {
9829
+ const { children, containerStyles, verticalGalleryStyles, gapHeightRem, controlBarHeightRem } = props;
9830
+ const containerRef = React.useRef(null);
9831
+ const containerHeight = _useContainerHeight(containerRef);
9832
+ const topPadding = containerRef.current ? parseFloat(getComputedStyle(containerRef.current).paddingTop) : 0;
9833
+ const bottomPadding = containerRef.current ? parseFloat(getComputedStyle(containerRef.current).paddingBottom) : 0;
9834
+ const childrenPerPage = calculateChildrenPerPage({
9835
+ numberOfChildren: React__default['default'].Children.count(children),
9836
+ containerHeight: (containerHeight !== null && containerHeight !== void 0 ? containerHeight : 0) - topPadding - bottomPadding,
9837
+ gapHeightRem,
9838
+ controlBarHeight: controlBarHeightRem !== null && controlBarHeightRem !== void 0 ? controlBarHeightRem : 2
9839
+ });
9840
+ return (React__default['default'].createElement("div", { ref: containerRef, className: react.mergeStyles(containerStyles) },
9841
+ React__default['default'].createElement(VerticalGallery, { childrenPerPage: childrenPerPage, styles: verticalGalleryStyles }, children)));
9842
+ };
9843
+ /**
9844
+ * Helper function to find the number of children for the VerticalGallery on each page.
9845
+ */
9846
+ const calculateChildrenPerPage = (args) => {
9847
+ const { numberOfChildren, containerHeight, gapHeightRem, controlBarHeight } = args;
9848
+ const childMinHeightPx = _convertRemToPx(VERTICAL_GALLERY_TILE_SIZE_REM.minHeight);
9849
+ const gapHeightPx = _convertRemToPx(gapHeightRem);
9850
+ const controlBarHeightPx = _convertRemToPx(controlBarHeight);
9851
+ /** First check how many children can fit in containerHeight.
9852
+ *
9853
+ * _________________
9854
+ * | |
9855
+ * | |
9856
+ * |________________|
9857
+ * _________________
9858
+ * | |
9859
+ * | |
9860
+ * |________________|
9861
+ *
9862
+ * < n/m >
9863
+ *
9864
+ * number of children = container height - (2* gap height + button height) / childMinHeight
9865
+ *
9866
+ * we want to find the maximum number of children at the smallest size we can fit in the gallery and then resize them
9867
+ * to fill in the space as much as possible
9868
+ *
9869
+ * First we will find the max number of children without any controls we can fit.
9870
+ */
9871
+ const maxNumberOfChildrenInContainer = Math.floor((containerHeight + gapHeightPx) / (childMinHeightPx + gapHeightPx));
9872
+ // if all of the children fit in the container just return the number of children
9873
+ if (numberOfChildren <= maxNumberOfChildrenInContainer) {
9874
+ return maxNumberOfChildrenInContainer;
9875
+ }
9876
+ /**
9877
+ * For the pagination we know the container height, the height of the button bar and the 2 times the gap
9878
+ * height, top tile and bottom tile above control bar. So the child space is calculated as:
9879
+ *
9880
+ * space = height - controlbar - (2 * gap)
9881
+ */
9882
+ const childSpace = containerHeight - controlBarHeightPx - 2 * gapHeightPx;
9883
+ /**
9884
+ * Now that we have the childrenSpace height we can figure out how many Children can fir in the childrenSpace.
9885
+ * childrenSpace = n * childHeightMin + (n - 1) * gapHeight. isolate n and take the floor.
9886
+ */
9887
+ return Math.floor((childSpace + gapHeightPx) / (childMinHeightPx + gapHeightPx));
9888
+ };
9889
+
9890
+ // Copyright (c) Microsoft Corporation.
9891
+ /**
9892
+ * @private
9893
+ */
9894
+ const horizontalGalleryContainerStyle = (shouldFloatLocalVideo, isNarrow) => {
9895
+ return {
9896
+ minHeight: isNarrow
9897
+ ? `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`
9898
+ : `${LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9899
+ width: shouldFloatLocalVideo
9900
+ ? isNarrow
9901
+ ? `calc(100% - ${_pxToRem(SMALL_FLOATING_MODAL_SIZE_PX.width)})`
9902
+ : `calc(100% - ${_pxToRem(LARGE_FLOATING_MODAL_SIZE_PX.width)})`
9903
+ : '100%',
9904
+ paddingRight: '0.5rem'
9905
+ };
9906
+ };
9907
+ /**
9908
+ * @private
9909
+ */
9910
+ const horizontalGalleryStyle = (isNarrow) => {
9911
+ return {
9912
+ children: isNarrow ? SMALL_HORIZONTAL_GALLERY_TILE_STYLE : LARGE_HORIZONTAL_GALLERY_TILE_STYLE
9913
+ };
9914
+ };
9915
+ /**
9916
+ * Small horizontal gallery tile size in rem
9917
+ * @private
9918
+ */
9919
+ const SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM = { height: 6.5, width: 6.5 };
9920
+ /**
9921
+ * Large horizontal gallery tile size in rem
9922
+ * @private
9923
+ */
9924
+ const LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM = { height: 7.5, width: 10 };
9925
+ /**
9926
+ * @private
9927
+ */
9928
+ const SMALL_HORIZONTAL_GALLERY_TILE_STYLE = {
9929
+ minHeight: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9930
+ minWidth: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.width}rem`,
9931
+ maxHeight: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9932
+ maxWidth: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.width}rem`
9933
+ };
9934
+ /**
9935
+ * @private
9936
+ */
9937
+ const LARGE_HORIZONTAL_GALLERY_TILE_STYLE = {
9938
+ minHeight: `${LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9939
+ minWidth: `${LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.width}rem`,
9940
+ maxHeight: `${LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9941
+ maxWidth: `${LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.width}rem`
9942
+ };
9943
+
9944
+ // Copyright (c) Microsoft Corporation.
9945
+ /**
9946
+ * @private
9947
+ */
9948
+ const scrollableHorizontalGalleryStyles = {
9949
+ root: {
9950
+ width: '100%',
9951
+ minHeight: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9952
+ paddingRight: '0.5rem',
9953
+ '> *': SMALL_HORIZONTAL_GALLERY_TILE_STYLE
9954
+ }
9955
+ };
9956
+ /**
9957
+ * @private
9958
+ */
9959
+ const scrollableHorizontalGalleryContainerStyles = react.mergeStyles({
9960
+ display: 'flex',
9961
+ width: `calc(100% - ${SMALL_FLOATING_MODAL_SIZE_PX.width}px)`,
9962
+ minHeight: `${SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.height}rem`,
9963
+ overflow: 'scroll',
9964
+ '-ms-overflow-style': 'none',
9965
+ 'scrollbar-width': 'none',
9966
+ '::-webkit-scrollbar': { display: 'none' }
9967
+ });
9968
+
9969
+ // Copyright (c) Microsoft Corporation.
9970
+ /**
9971
+ * Component to display elements horizontally in a scrollable container
9972
+ * @private
9973
+ */
9974
+ const ScrollableHorizontalGallery = (props) => {
9975
+ const { horizontalGalleryElements } = props;
9976
+ const ref = React.useRef();
9977
+ const { events: dragabbleEvents } = reactUseDraggableScroll.useDraggable(ref);
9978
+ return (React__default['default'].createElement("div", Object.assign({ ref: ref }, dragabbleEvents, { className: scrollableHorizontalGalleryContainerStyles }),
9979
+ React__default['default'].createElement(react.Stack, { "data-ui-id": "scrollable-horizontal-gallery", horizontal: true, styles: scrollableHorizontalGalleryStyles, tokens: { childrenGap: '0.5rem' } }, horizontalGalleryElements)));
9980
+ };
9981
+
9716
9982
  // Copyright (c) Microsoft Corporation.
9717
9983
  /**
9718
9984
  * A ResponsiveHorizontalGallery styled for the {@link VideoGallery}
9719
9985
  *
9720
9986
  * @private
9721
9987
  */
9722
- const VideoGalleryResponsiveHorizontalGallery = (props) => {
9723
- const { shouldFloatLocalVideo = false, isNarrow = false, horizontalGalleryElements, styles } = props;
9724
- const containerStyles = React.useMemo(() => horizontalGalleryContainerStyle(shouldFloatLocalVideo, isNarrow), [shouldFloatLocalVideo, isNarrow]);
9725
- const galleryStyles = React.useMemo(() => react.concatStyleSets(horizontalGalleryStyle(isNarrow), styles), [isNarrow, styles]);
9726
- return (React__default['default'].createElement(ResponsiveHorizontalGallery, { key: "responsive-horizontal-gallery", containerStyles: containerStyles, horizontalGalleryStyles: galleryStyles, childWidthRem: isNarrow ? SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.width : LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.width, buttonWidthRem: HORIZONTAL_GALLERY_BUTTON_WIDTH, gapWidthRem: HORIZONTAL_GALLERY_GAP }, horizontalGalleryElements));
9988
+ const OverflowGallery = (props) => {
9989
+ const { shouldFloatLocalVideo = false, isNarrow = false, overflowGalleryElements, styles,
9990
+ /* @conditional-compile-remove(vertical-gallery) */ overflowGalleryLayout = 'HorizontalBottom' } = props;
9991
+ const containerStyles = React.useMemo(() => {
9992
+ /* @conditional-compile-remove(vertical-gallery) */
9993
+ if (overflowGalleryLayout === 'VerticalRight') {
9994
+ return verticalGalleryContainerStyle(shouldFloatLocalVideo);
9995
+ }
9996
+ return horizontalGalleryContainerStyle(shouldFloatLocalVideo, isNarrow);
9997
+ }, [shouldFloatLocalVideo, isNarrow, /* @conditional-compile-remove(vertical-gallery) */ overflowGalleryLayout]);
9998
+ const galleryStyles = React.useMemo(() => {
9999
+ /* @conditional-compile-remove(vertical-gallery) */
10000
+ if (overflowGalleryLayout === 'VerticalRight') {
10001
+ return react.concatStyleSets(verticalGalleryStyle, styles);
10002
+ }
10003
+ return react.concatStyleSets(horizontalGalleryStyle(isNarrow), styles);
10004
+ }, [isNarrow, styles, /* @conditional-compile-remove(vertical-gallery) */ overflowGalleryLayout]);
10005
+ /* @conditional-compile-remove(vertical-gallery) */
10006
+ if (overflowGalleryLayout === 'VerticalRight') {
10007
+ return (React__default['default'].createElement(ResponsiveVerticalGallery, { key: "responsive-vertical-gallery", containerStyles: containerStyles, verticalGalleryStyles: galleryStyles, controlBarHeightRem: HORIZONTAL_GALLERY_BUTTON_WIDTH, gapHeightRem: HORIZONTAL_GALLERY_GAP }, overflowGalleryElements));
10008
+ }
10009
+ /* @conditional-compile-remove(pinned-participants) */
10010
+ if (isNarrow) {
10011
+ return React__default['default'].createElement(ScrollableHorizontalGallery, { horizontalGalleryElements: overflowGalleryElements });
10012
+ }
10013
+ return (React__default['default'].createElement(ResponsiveHorizontalGallery, { key: "responsive-horizontal-gallery", containerStyles: containerStyles, horizontalGalleryStyles: galleryStyles, childWidthRem: isNarrow ? SMALL_HORIZONTAL_GALLERY_TILE_SIZE_REM.width : LARGE_HORIZONTAL_GALLERY_TILE_SIZE_REM.width, buttonWidthRem: HORIZONTAL_GALLERY_BUTTON_WIDTH, gapWidthRem: HORIZONTAL_GALLERY_GAP }, overflowGalleryElements));
9727
10014
  };
9728
10015
 
9729
10016
  // Copyright (c) Microsoft Corporation.
@@ -9735,7 +10022,8 @@ const VideoGalleryResponsiveHorizontalGallery = (props) => {
9735
10022
  */
9736
10023
  const DefaultLayout = (props) => {
9737
10024
  const { remoteParticipants = [], dominantSpeakers, localVideoComponent, screenShareComponent, onRenderRemoteParticipant, styles, maxRemoteVideoStreams, parentWidth,
9738
- /* @conditional-compile-remove(pinned-participants) */ pinnedParticipantUserIds } = props;
10025
+ /* @conditional-compile-remove(pinned-participants) */ pinnedParticipantUserIds,
10026
+ /* @conditional-compile-remove(vertical-gallery) */ overflowGalleryLayout = 'HorizontalBottom' } = props;
9739
10027
  const isNarrow = parentWidth ? isNarrowWidth(parentWidth) : false;
9740
10028
  const { gridParticipants, horizontalGalleryParticipants } = useOrganizedParticipants({
9741
10029
  remoteParticipants,
@@ -9760,19 +10048,26 @@ const DefaultLayout = (props) => {
9760
10048
  if (localVideoComponent) {
9761
10049
  gridTiles.push(localVideoComponent);
9762
10050
  }
9763
- const horizontalGallery = React.useMemo(() => {
10051
+ const overflowGallery = React.useMemo(() => {
9764
10052
  if (horizontalGalleryTiles.length === 0) {
9765
10053
  return null;
9766
10054
  }
9767
- /* @conditional-compile-remove(pinned-participants) */
9768
- if (isNarrow) {
9769
- return React__default['default'].createElement(ScrollableHorizontalGallery, { horizontalGalleryElements: horizontalGalleryTiles });
9770
- }
9771
- return (React__default['default'].createElement(VideoGalleryResponsiveHorizontalGallery, { isNarrow: isNarrow, shouldFloatLocalVideo: true, horizontalGalleryElements: horizontalGalleryTiles, styles: styles === null || styles === void 0 ? void 0 : styles.horizontalGallery }));
9772
- }, [isNarrow, horizontalGalleryTiles, styles === null || styles === void 0 ? void 0 : styles.horizontalGallery]);
9773
- return (React__default['default'].createElement(react.Stack, { horizontal: false, styles: rootLayoutStyle$1, tokens: videoGalleryLayoutGap },
10055
+ return (React__default['default'].createElement(OverflowGallery, { isNarrow: isNarrow, shouldFloatLocalVideo: false, overflowGalleryElements: horizontalGalleryTiles, styles: styles === null || styles === void 0 ? void 0 : styles.horizontalGallery,
10056
+ /* @conditional-compile-remove(pinned-participants) */
10057
+ overflowGalleryLayout: overflowGalleryLayout }));
10058
+ }, [
10059
+ isNarrow,
10060
+ horizontalGalleryTiles,
10061
+ styles === null || styles === void 0 ? void 0 : styles.horizontalGallery,
10062
+ /* @conditional-compile-remove(vertical-gallery) */ overflowGalleryLayout
10063
+ ]);
10064
+ return (React__default['default'].createElement(react.Stack
10065
+ /* @conditional-compile-remove(vertical-gallery) */
10066
+ , {
10067
+ /* @conditional-compile-remove(vertical-gallery) */
10068
+ horizontal: overflowGalleryLayout === 'VerticalRight', styles: rootLayoutStyle$1, tokens: videoGalleryLayoutGap },
9774
10069
  screenShareComponent ? (screenShareComponent) : (React__default['default'].createElement(GridLayout, { key: "grid-layout", styles: styles === null || styles === void 0 ? void 0 : styles.gridLayout }, gridTiles)),
9775
- horizontalGallery));
10070
+ overflowGallery));
9776
10071
  };
9777
10072
 
9778
10073
  // Copyright (c) Microsoft Corporation.
@@ -10463,21 +10758,19 @@ const modalMaxDragPosition = { x: localVideoTileOuterPaddingPX, y: localVideoTil
10463
10758
  * @private
10464
10759
  */
10465
10760
  const FloatingLocalVideo = (props) => {
10466
- const { localVideoComponent, layerHostId, isNarrow, parentWidth, parentHeight } = props;
10761
+ const { localVideoComponent, layerHostId, localVideoSize, parentWidth, parentHeight } = props;
10467
10762
  const theme = useTheme();
10468
- const modalWidth = isNarrow ? SMALL_FLOATING_MODAL_SIZE_PX.width : LARGE_FLOATING_MODAL_SIZE_PX.width;
10469
- const modalHeight = isNarrow ? SMALL_FLOATING_MODAL_SIZE_PX.height : LARGE_FLOATING_MODAL_SIZE_PX.height;
10470
10763
  // The minimum drag position is the top left of the video gallery. i.e. the modal (PiP) should not be able
10471
10764
  // to be dragged offscreen and these are the top and left bounds of that calculation.
10472
10765
  const modalMinDragPosition = React.useMemo(() => parentWidth && parentHeight
10473
10766
  ? {
10474
10767
  // We use -parentWidth/Height because our modal is positioned to start in the bottom right,
10475
10768
  // hence (0,0) is the bottom right of the video gallery.
10476
- x: -parentWidth + modalWidth + localVideoTileOuterPaddingPX,
10477
- y: -parentHeight + modalHeight + localVideoTileOuterPaddingPX
10769
+ x: -parentWidth + localVideoSize.width + localVideoTileOuterPaddingPX,
10770
+ y: -parentHeight + localVideoSize.height + localVideoTileOuterPaddingPX
10478
10771
  }
10479
- : undefined, [parentHeight, parentWidth, modalHeight, modalWidth]);
10480
- const modalStyles = React.useMemo(() => floatingLocalVideoModalStyle(theme, isNarrow), [theme, isNarrow]);
10772
+ : undefined, [parentHeight, parentWidth, localVideoSize.width, localVideoSize.height]);
10773
+ const modalStyles = React.useMemo(() => floatingLocalVideoModalStyle(theme, localVideoSize), [theme, localVideoSize]);
10481
10774
  const layerProps = React.useMemo(() => ({ hostId: layerHostId }), [layerHostId]);
10482
10775
  return (React__default['default'].createElement(_ModalClone, { isOpen: true, isModeless: true, dragOptions: DRAG_OPTIONS$1, styles: modalStyles, layerProps: layerProps, maxDragPosition: modalMaxDragPosition, minDragPosition: modalMinDragPosition }, localVideoComponent));
10483
10776
  };
@@ -10519,7 +10812,8 @@ const layerHostStyle = {
10519
10812
  */
10520
10813
  const FloatingLocalVideoLayout = (props) => {
10521
10814
  const { remoteParticipants = [], dominantSpeakers, localVideoComponent, screenShareComponent, onRenderRemoteParticipant, styles, maxRemoteVideoStreams, showCameraSwitcherInLocalPreview, parentWidth, parentHeight,
10522
- /* @conditional-compile-remove(pinned-participants) */ pinnedParticipantUserIds } = props;
10815
+ /* @conditional-compile-remove(pinned-participants) */ pinnedParticipantUserIds,
10816
+ /* @conditional-compile-remove(vertical-gallery) */ overflowGalleryLayout = 'HorizontalBottom' } = props;
10523
10817
  const theme = useTheme();
10524
10818
  const isNarrow = parentWidth ? isNarrowWidth(parentWidth) : false;
10525
10819
  const { gridParticipants, horizontalGalleryParticipants } = useOrganizedParticipants({
@@ -10547,28 +10841,43 @@ const FloatingLocalVideoLayout = (props) => {
10547
10841
  : (_b = p.videoStream) === null || _b === void 0 ? void 0 : _b.isAvailable);
10548
10842
  });
10549
10843
  const layerHostId = reactHooks.useId('layerhost');
10844
+ let localVideoSize = LARGE_FLOATING_MODAL_SIZE_PX;
10845
+ if (isNarrow) {
10846
+ localVideoSize = SMALL_FLOATING_MODAL_SIZE_PX;
10847
+ }
10848
+ /* @conditional-compile-remove(vertical-gallery) */
10849
+ if (overflowGalleryLayout === 'VerticalRight') {
10850
+ localVideoSize = VERTICAL_GALLERY_FLOATING_MODAL_SIZE_PX;
10851
+ }
10550
10852
  const wrappedLocalVideoComponent = localVideoComponent && shouldFloatLocalVideo ? (
10551
10853
  // When we use showCameraSwitcherInLocalPreview it disables dragging to allow keyboard navigation.
10552
- showCameraSwitcherInLocalPreview ? (React__default['default'].createElement(react.Stack, { className: react.mergeStyles(localVideoTileWithControlsContainerStyle(theme, isNarrow), {
10854
+ showCameraSwitcherInLocalPreview ? (React__default['default'].createElement(react.Stack, { className: react.mergeStyles(localVideoTileWithControlsContainerStyle(theme, localVideoSize), {
10553
10855
  boxShadow: theme.effects.elevation8,
10554
10856
  zIndex: LOCAL_VIDEO_TILE_ZINDEX
10555
- }) }, localVideoComponent)) : horizontalGalleryTiles.length > 0 ? (React__default['default'].createElement(react.Stack, { className: react.mergeStyles(localVideoTileContainerStyle(theme, isNarrow)) }, localVideoComponent)) : (React__default['default'].createElement(FloatingLocalVideo, { localVideoComponent: localVideoComponent, layerHostId: layerHostId, isNarrow: isNarrow, parentWidth: parentWidth, parentHeight: parentHeight }))) : undefined;
10556
- const horizontalGallery = React.useMemo(() => {
10857
+ }) }, localVideoComponent)) : horizontalGalleryTiles.length > 0 ? (React__default['default'].createElement(react.Stack, { className: react.mergeStyles(localVideoTileContainerStyle(theme, localVideoSize)) }, localVideoComponent)) : (React__default['default'].createElement(FloatingLocalVideo, { localVideoComponent: localVideoComponent, layerHostId: layerHostId, localVideoSize: localVideoSize, parentWidth: parentWidth, parentHeight: parentHeight }))) : undefined;
10858
+ const overflowGallery = React.useMemo(() => {
10557
10859
  if (horizontalGalleryTiles.length === 0) {
10558
10860
  return null;
10559
10861
  }
10560
- /* @conditional-compile-remove(pinned-participants) */
10561
- if (isNarrow) {
10562
- return React__default['default'].createElement(ScrollableHorizontalGallery, { horizontalGalleryElements: horizontalGalleryTiles });
10563
- }
10564
- return (React__default['default'].createElement(VideoGalleryResponsiveHorizontalGallery, { isNarrow: isNarrow, shouldFloatLocalVideo: true, horizontalGalleryElements: horizontalGalleryTiles, styles: styles === null || styles === void 0 ? void 0 : styles.horizontalGallery }));
10565
- }, [isNarrow, horizontalGalleryTiles, styles === null || styles === void 0 ? void 0 : styles.horizontalGallery]);
10862
+ return (React__default['default'].createElement(OverflowGallery, { isNarrow: isNarrow, shouldFloatLocalVideo: true, overflowGalleryElements: horizontalGalleryTiles, styles: styles === null || styles === void 0 ? void 0 : styles.horizontalGallery,
10863
+ /* @conditional-compile-remove(vertical-gallery) */
10864
+ overflowGalleryLayout: overflowGalleryLayout }));
10865
+ }, [
10866
+ isNarrow,
10867
+ horizontalGalleryTiles,
10868
+ styles === null || styles === void 0 ? void 0 : styles.horizontalGallery,
10869
+ /* @conditional-compile-remove(vertical-gallery) */ overflowGalleryLayout
10870
+ ]);
10566
10871
  return (React__default['default'].createElement(react.Stack, { styles: rootLayoutStyle },
10567
10872
  wrappedLocalVideoComponent,
10568
10873
  React__default['default'].createElement(react.LayerHost, { id: layerHostId, className: react.mergeStyles(layerHostStyle) }),
10569
- React__default['default'].createElement(react.Stack, { horizontal: false, styles: innerLayoutStyle, tokens: videoGalleryLayoutGap },
10874
+ React__default['default'].createElement(react.Stack
10875
+ /* @conditional-compile-remove(vertical-gallery) */
10876
+ , {
10877
+ /* @conditional-compile-remove(vertical-gallery) */
10878
+ horizontal: overflowGalleryLayout === 'VerticalRight', styles: innerLayoutStyle, tokens: videoGalleryLayoutGap },
10570
10879
  screenShareComponent ? (screenShareComponent) : (React__default['default'].createElement(GridLayout, { key: "grid-layout", styles: styles === null || styles === void 0 ? void 0 : styles.gridLayout }, gridTiles)),
10571
- horizontalGallery)));
10880
+ overflowGallery)));
10572
10881
  };
10573
10882
 
10574
10883
  // Copyright (c) Microsoft Corporation.
@@ -10604,7 +10913,9 @@ const VideoGallery = (props) => {
10604
10913
  /* @conditional-compile-remove(pinned-participants) */
10605
10914
  onUnpinParticipant: onUnpinParticipantHandler,
10606
10915
  /* @conditional-compile-remove(pinned-participants) */
10607
- remoteVideoTileMenuOptions = DEFAULT_REMOTE_VIDEO_TILE_MENU_OPTIONS } = props;
10916
+ remoteVideoTileMenuOptions = DEFAULT_REMOTE_VIDEO_TILE_MENU_OPTIONS,
10917
+ /* @conditional-compile-remove(vertical-gallery) */
10918
+ overflowGalleryLayout = 'HorizontalBottom' } = props;
10608
10919
  const ids = useIdentifiers();
10609
10920
  const theme = useTheme();
10610
10921
  const localeStrings = useLocale$1().strings.videoGallery;
@@ -10764,7 +11075,8 @@ const VideoGallery = (props) => {
10764
11075
  localVideoComponent: localVideoTile,
10765
11076
  parentWidth: containerWidth,
10766
11077
  parentHeight: containerHeight,
10767
- /* @conditional-compile-remove(pinned-participants) */ pinnedParticipantUserIds: pinnedParticipants
11078
+ /* @conditional-compile-remove(pinned-participants) */ pinnedParticipantUserIds: pinnedParticipants,
11079
+ /* @conditional-compile-remove(vertical-gallery) */ overflowGalleryLayout
10768
11080
  }), [
10769
11081
  remoteParticipants,
10770
11082
  screenShareComponent,
@@ -10777,7 +11089,8 @@ const VideoGallery = (props) => {
10777
11089
  containerHeight,
10778
11090
  onRenderRemoteVideoTile,
10779
11091
  defaultOnRenderVideoTile,
10780
- /* @conditional-compile-remove(pinned-participants) */ pinnedParticipants
11092
+ /* @conditional-compile-remove(pinned-participants) */ pinnedParticipants,
11093
+ /* @conditional-compile-remove(vertical-gallery) */ overflowGalleryLayout
10781
11094
  ]);
10782
11095
  const videoGalleryLayout = React.useMemo(() => {
10783
11096
  if (layout === 'floatingLocalVideo') {