@azure/communication-react
Version:
React library for building modern communication user experiences utilizing Azure Communication Services
56 lines • 3.88 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { Stack, FocusZone, Spinner, useTheme } from '@fluentui/react';
import React, { useEffect, useRef, useState, useCallback } from 'react';
import { _Caption } from './Caption';
import { captionContainerClassName, captionsBannerClassName, captionsBannerFullHeightClassName, captionsContainerClassName, loadingBannerFullHeightStyles, loadingBannerStyles } from './styles/Captions.style';
import { useLocale } from '../localization';
const SCROLL_OFFSET_ALLOWANCE = 20;
/**
* @public
* A component for displaying a CaptionsBanner with user icon, displayName and captions text.
*/
export const CaptionsBanner = (props) => {
const { captions, isCaptionsOn, startCaptionsInProgress, onRenderAvatar, formFactor = 'default', captionsOptions } = props;
const localeStrings = useLocale().strings.captionsBanner;
const strings = Object.assign(Object.assign({}, localeStrings), props.strings);
const captionsScrollDivRef = useRef(null);
const [isAtBottomOfScroll, setIsAtBottomOfScroll] = useState(true);
const theme = useTheme();
const scrollToBottom = () => {
if (captionsScrollDivRef.current) {
captionsScrollDivRef.current.scrollTop = captionsScrollDivRef.current.scrollHeight;
}
};
const handleScrollToTheBottom = useCallback(() => {
if (!captionsScrollDivRef.current) {
return;
}
const atBottom = Math.ceil(captionsScrollDivRef.current.scrollTop) >= captionsScrollDivRef.current.scrollHeight - captionsScrollDivRef.current.clientHeight - SCROLL_OFFSET_ALLOWANCE;
setIsAtBottomOfScroll(atBottom);
}, []);
useEffect(() => {
const captionsScrollDiv = captionsScrollDivRef.current;
captionsScrollDiv === null || captionsScrollDiv === void 0 ? void 0 : captionsScrollDiv.addEventListener('scroll', handleScrollToTheBottom);
return () => {
captionsScrollDiv === null || captionsScrollDiv === void 0 ? void 0 : captionsScrollDiv.removeEventListener('scroll', handleScrollToTheBottom);
};
}, [handleScrollToTheBottom, isCaptionsOn]);
useEffect(() => {
// only auto scroll to bottom is already is at bottom of scroll before new caption comes in
if (isAtBottomOfScroll) {
scrollToBottom();
}
}, [captions, isAtBottomOfScroll]);
const captionsTrampoline = () => {
return React.createElement(React.Fragment, null, captions.map(caption => {
return React.createElement("li", { key: caption.id, className: captionContainerClassName, "data-is-focusable": true },
React.createElement(_Caption, Object.assign({}, caption, { onRenderAvatar: onRenderAvatar })));
}));
};
return React.createElement(React.Fragment, null, (startCaptionsInProgress || isCaptionsOn) && React.createElement(FocusZone, { shouldFocusOnMount: true, className: captionsContainerClassName, "data-ui-id": "captions-banner" },
isCaptionsOn && React.createElement("ul", { ref: captionsScrollDivRef, className: (captionsOptions === null || captionsOptions === void 0 ? void 0 : captionsOptions.height) === 'full' ? captionsBannerFullHeightClassName(theme) : captionsBannerClassName(formFactor), "data-ui-id": "captions-banner-inner" }, captionsTrampoline()),
!isCaptionsOn && React.createElement(Stack, { verticalAlign: "center", styles: (captionsOptions === null || captionsOptions === void 0 ? void 0 : captionsOptions.height) === 'full' ? loadingBannerFullHeightStyles(theme) : loadingBannerStyles(formFactor), "data-is-focusable": true },
React.createElement(Spinner, { label: strings === null || strings === void 0 ? void 0 : strings.captionsBannerSpinnerText, ariaLive: "assertive", labelPosition: "right" }))));
};
//# sourceMappingURL=CaptionsBanner.js.map