UNPKG

communication-react-19

Version:

React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)

114 lines 7.14 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import { DefaultButton, Icon, mergeStyles, Stack, Text } from '@fluentui/react'; import React, { useEffect, useMemo, useState } from 'react'; import { useLocale } from '../localization'; import { useIdentifiers } from '../identifiers'; import { useTheme } from '../theming'; import { childrenContainerStyle, pageNavigationControlBarContainerStyle, participantPageCounter, leftRightButtonStyles, navIconStyles, rootStyle } from './styles/VerticalGallery.styles'; import { bucketize } from './utils/overFlowGalleriesUtils'; import { _formatString } from "../../../acs-ui-common/src"; /** * VerticalGallery is a overflow gallery for participants in the {@link VideoGallery} component. Stacks * participants on the Y-axis of the VideoGallery for better use of horizontal space. * * @public */ export const VerticalGallery = (props) => { const { children, styles, childrenPerPage, onFetchTilesToRender } = props; const [page, setPage] = useState(1); const [buttonState, setButtonState] = useState({ previous: true, next: true }); const ids = useIdentifiers(); const numberOfChildren = React.Children.count(children); const lastPage = Math.ceil(numberOfChildren / childrenPerPage); const indexesArray = useMemo(() => { return bucketize([...Array(numberOfChildren).keys()], childrenPerPage); }, [numberOfChildren, childrenPerPage]); useEffect(() => { var _a; if (onFetchTilesToRender && indexesArray) { onFetchTilesToRender((_a = indexesArray[page - 1]) !== null && _a !== void 0 ? _a : []); } }, [indexesArray, onFetchTilesToRender, page]); const firstIndexOfCurrentPage = (page - 1) * childrenPerPage; const clippedPage = firstIndexOfCurrentPage < numberOfChildren - 1 ? page : lastPage; const childrenOnCurrentPage = useMemo(() => { var _a; if (indexesArray[0] !== undefined) { return (_a = indexesArray[clippedPage - 1]) === null || _a === void 0 ? void 0 : _a.map((index) => { return React.Children.toArray(children)[index]; }); } return; }, [indexesArray, clippedPage, children]); const showButtons = numberOfChildren > childrenPerPage; const onPreviousButtonClick = () => { setPage(page - 1); }; const onNextButtonClick = () => { setPage(page + 1); }; if (page > lastPage && lastPage > 0) { setPage(lastPage); } useEffect(() => { if (page > 1 && page < lastPage && showButtons) { // we are somewhere in between first and last pages. setButtonState({ previous: false, next: false }); } else if (page === 1 && showButtons) { // we are on the first page. setButtonState({ previous: true, next: false }); } else if (page === lastPage && showButtons) { // we are on the last page. setButtonState({ previous: false, next: true }); } }, [page, numberOfChildren, lastPage, showButtons]); const childContainerStyle = useMemo(() => { return { root: childrenContainerStyle(2) }; }, []); const childrenStyles = useMemo(() => { return { root: styles === null || styles === void 0 ? void 0 : styles.children }; }, [styles === null || styles === void 0 ? void 0 : styles.children]); if (childrenPerPage <= 0) { return React.createElement(React.Fragment, null); } return (React.createElement(Stack, { className: mergeStyles(rootStyle, styles === null || styles === void 0 ? void 0 : styles.root) }, React.createElement(Stack, { styles: childContainerStyle }, childrenOnCurrentPage === null || childrenOnCurrentPage === void 0 ? void 0 : childrenOnCurrentPage.map((child, i) => { return (React.createElement(Stack.Item, { key: i, styles: childrenStyles, "data-ui-id": ids.verticalGalleryVideoTile }, child)); })), showButtons && (React.createElement(VerticalGalleryControlBar, { buttonsDisabled: buttonState, onPreviousButtonClick: onPreviousButtonClick, onNextButtonClick: onNextButtonClick, totalPages: lastPage, currentPage: page })))); }; const VerticalGalleryControlBar = (props) => { const { onNextButtonClick, onPreviousButtonClick, buttonsDisabled, currentPage, totalPages, styles } = props; const theme = useTheme(); const ids = useIdentifiers(); const strings = useLocale().strings.verticalGallery; const pageCounterContainerStyles = useMemo(() => { return mergeStyles(pageNavigationControlBarContainerStyle, styles === null || styles === void 0 ? void 0 : styles.root); }, [styles === null || styles === void 0 ? void 0 : styles.root]); const previousButtonSyles = useMemo(() => { return mergeStyles(leftRightButtonStyles(theme), styles === null || styles === void 0 ? void 0 : styles.previousButton); }, [styles === null || styles === void 0 ? void 0 : styles.previousButton, theme]); const pageCounterStyles = useMemo(() => { return mergeStyles(participantPageCounter, styles === null || styles === void 0 ? void 0 : styles.counter); }, [styles === null || styles === void 0 ? void 0 : styles.counter]); const nextButtonsStyles = useMemo(() => { return mergeStyles(leftRightButtonStyles(theme), styles === null || styles === void 0 ? void 0 : styles.nextButton); }, [styles === null || styles === void 0 ? void 0 : styles.nextButton, theme]); const controlBarSpacing = { childrenGap: '0.5rem' }; const previousButtonAriaLabel = strings.leftNavButtonAriaLabel ? _formatString(strings.leftNavButtonAriaLabel, { current: `${currentPage}`, total: `${totalPages}` }) : undefined; const nextButtonAriaLabel = strings.rightNavButtonAriaLabel ? _formatString(strings.rightNavButtonAriaLabel, { current: `${currentPage}`, total: `${totalPages}` }) : undefined; return (React.createElement(Stack, { horizontalAlign: "center", tokens: controlBarSpacing, horizontal: true, className: pageCounterContainerStyles }, React.createElement(DefaultButton, { className: previousButtonSyles, onClick: onPreviousButtonClick, disabled: buttonsDisabled === null || buttonsDisabled === void 0 ? void 0 : buttonsDisabled.previous, ariaLabel: previousButtonAriaLabel, "data-ui-id": ids.overflowGalleryLeftNavButton }, React.createElement(Icon, { iconName: "VerticalGalleryLeftButton", styles: navIconStyles })), React.createElement(Text, { "data-ui-id": ids.verticalGalleryPageCounter, className: pageCounterStyles }, `${currentPage} / ${totalPages}`), React.createElement(DefaultButton, { className: nextButtonsStyles, onClick: onNextButtonClick, disabled: buttonsDisabled === null || buttonsDisabled === void 0 ? void 0 : buttonsDisabled.next, ariaLabel: nextButtonAriaLabel, "data-ui-id": ids.overflowGalleryRightNavButton }, React.createElement(Icon, { iconName: "VerticalGalleryRightButton", styles: navIconStyles })))); }; //# sourceMappingURL=VerticalGallery.js.map