communication-react-19
Version:
React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)
64 lines • 4.24 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { DefaultButton, Icon, Stack, mergeStyles } from '@fluentui/react';
import React, { useEffect, useMemo, useState } from 'react';
import { useTheme } from '../theming';
import { rootStyle, childrenContainerStyle, leftRightButtonStyles } from './styles/HorizontalGallery.styles';
import { useIdentifiers } from '../identifiers';
import { bucketize } from './utils/overFlowGalleriesUtils';
/**
* {@link HorizontalGallery} default children per page
*/
const DEFAULT_CHILDREN_PER_PAGE = 5;
/**
* Renders a horizontal gallery that parents children horizontally. Handles pagination based on the childrenPerPage prop.
* @param props - HorizontalGalleryProps {@link @azure/communication-react#HorizontalGalleryProps}
* @returns
*/
export const HorizontalGallery = (props) => {
var _a;
const { children, childrenPerPage = DEFAULT_CHILDREN_PER_PAGE, styles, onFetchTilesToRender } = props;
const ids = useIdentifiers();
const [page, setPage] = useState(0);
const numberOfChildren = React.Children.count(children);
const lastPage = Math.ceil(numberOfChildren / childrenPerPage) - 1;
const indexesArray = useMemo(() => {
return bucketize([...Array(numberOfChildren).keys()], childrenPerPage);
}, [numberOfChildren, childrenPerPage]);
useEffect(() => {
var _a;
if (onFetchTilesToRender && indexesArray) {
onFetchTilesToRender((_a = indexesArray[page]) !== null && _a !== void 0 ? _a : []);
}
}, [indexesArray, onFetchTilesToRender, page]);
const firstIndexOfCurrentPage = page * childrenPerPage;
const clippedPage = firstIndexOfCurrentPage < numberOfChildren - 1 ? page : lastPage;
const childrenOnCurrentPage = useMemo(() => {
const indexes = indexesArray === null || indexesArray === void 0 ? void 0 : indexesArray[clippedPage];
if (!indexes) {
return [];
}
return indexes.map((index) => React.Children.toArray(children)[index]);
}, [indexesArray, clippedPage, children]);
const showButtons = numberOfChildren > childrenPerPage;
const disablePreviousButton = page === 0;
const disableNextButton = page === lastPage;
const childrenStyles = useMemo(() => {
return { root: styles === null || styles === void 0 ? void 0 : styles.children };
}, [styles === null || styles === void 0 ? void 0 : styles.children]);
// If children per page is 0 or less return empty element
if (childrenPerPage <= 0) {
return React.createElement(React.Fragment, null);
}
return (React.createElement(Stack, { horizontal: true, className: mergeStyles(rootStyle, (_a = props.styles) === null || _a === void 0 ? void 0 : _a.root) },
showButtons && (React.createElement(HorizontalGalleryNavigationButton, { key: "previous-nav-button", icon: React.createElement(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.overflowGalleryLeftNavButton })),
React.createElement(Stack, { horizontal: true, className: mergeStyles(childrenContainerStyle) }, childrenOnCurrentPage.map((child, i) => {
return (React.createElement(Stack.Item, { styles: childrenStyles, key: i, "data-ui-id": ids.horizontalGalleryVideoTile }, child));
})),
showButtons && (React.createElement(HorizontalGalleryNavigationButton, { key: "next-nav-button", icon: React.createElement(Icon, { iconName: "HorizontalGalleryRightButton" }), styles: styles === null || styles === void 0 ? void 0 : styles.nextButton, onClick: () => setPage(Math.min(lastPage, page + 1)), disabled: disableNextButton, identifier: ids.overflowGalleryRightNavButton }))));
};
const HorizontalGalleryNavigationButton = (props) => {
const theme = useTheme();
return (React.createElement(DefaultButton, { className: mergeStyles(leftRightButtonStyles(theme), props.styles), onClick: props.onClick, disabled: props.disabled, "data-ui-id": props.identifier }, props.icon));
};
//# sourceMappingURL=HorizontalGallery.js.map