UNPKG

stream-chat-react

Version:

React components to create chat conversations or livestream style chat

70 lines (69 loc) 2.84 kB
import clsx from 'clsx'; import React, { useEffect, useState } from 'react'; import { FocusScope } from '@react-aria/focus'; import { DialogPortalEntry } from './DialogPortal'; import { useDialog, useDialogIsOpen } from './hooks'; import { usePopoverPosition } from './hooks/usePopoverPosition'; export function useDialogAnchor({ allowFlip, open, placement, referenceElement, }) { const [popperElement, setPopperElement] = useState(null); const { refs, strategy, update, x, y } = usePopoverPosition({ allowFlip, freeze: true, placement, }); useEffect(() => { refs.setReference(referenceElement); }, [referenceElement, refs]); useEffect(() => { refs.setFloating(popperElement); }, [popperElement, refs]); useEffect(() => { if (open && popperElement) { // Since the popper's reference element might not be (and usually is not) visible // all the time, it's safer to force popper update before showing it. // update is non-null only if popperElement is non-null update?.(); } }, [open, placement, popperElement, update]); if (popperElement && !open) { setPopperElement(null); } return { setPopperElement, styles: { left: x ?? 0, position: strategy, top: y ?? 0, }, }; } export const DialogAnchor = ({ allowFlip = true, children, className, dialogManagerId, focus = true, id, placement = 'auto', referenceElement = null, tabIndex, trapFocus, ...restDivProps }) => { const dialog = useDialog({ dialogManagerId, id }); const open = useDialogIsOpen(id, dialogManagerId); const { setPopperElement, styles } = useDialogAnchor({ allowFlip, open, placement, referenceElement, }); useEffect(() => { if (!open) return; const hideOnEscape = (event) => { if (event.key !== 'Escape') return; dialog?.close(); }; document.addEventListener('keyup', hideOnEscape); return () => { document.removeEventListener('keyup', hideOnEscape); }; }, [dialog, open]); // prevent rendering the dialog contents if the dialog should not be open / shown if (!open) { return null; } return (React.createElement(DialogPortalEntry, { dialogId: id, dialogManagerId: dialogManagerId }, React.createElement(FocusScope, { autoFocus: focus, contain: trapFocus, restoreFocus: true }, React.createElement("div", { ...restDivProps, className: clsx('str-chat__dialog-contents', className), "data-testid": 'str-chat__dialog-contents', ref: setPopperElement, style: styles, tabIndex: typeof tabIndex !== 'undefined' ? tabIndex : 0 }, children)))); };