UNPKG

stream-chat-react

Version:

React components to create chat conversations or livestream style chat

74 lines (73 loc) 2.98 kB
import clsx from 'clsx'; import React, { useEffect, useState } from 'react'; import { FocusScope } from '@react-aria/focus'; import { usePopper } from 'react-popper'; import { DialogPortalEntry } from './DialogPortal'; import { useDialog, useDialogIsOpen } from './hooks'; export function useDialogAnchor({ allowFlip, open, placement, referenceElement, }) { const [popperElement, setPopperElement] = useState(null); const { attributes, styles, update } = usePopper(referenceElement, popperElement, { modifiers: [ { enabled: !!allowFlip, // Prevent flipping name: 'flip', }, { name: 'eventListeners', options: { // It's not safe to update popper position on resize and scroll, since popper's // reference element might not be visible at the time. resize: false, scroll: false, }, }, ], placement, }); 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, popperElement, update]); if (popperElement && !open) { setPopperElement(null); } return { attributes, setPopperElement, styles, }; } export const DialogAnchor = ({ allowFlip = true, children, className, focus = true, id, placement = 'auto', referenceElement = null, tabIndex, trapFocus, ...restDivProps }) => { const dialog = useDialog({ id }); const open = useDialogIsOpen(id); const { attributes, 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 }, React.createElement(FocusScope, { autoFocus: focus, contain: trapFocus, restoreFocus: true }, React.createElement("div", { ...restDivProps, ...attributes.popper, className: clsx('str-chat__dialog-contents', className), "data-testid": 'str-chat__dialog-contents', ref: setPopperElement, style: styles.popper, tabIndex: typeof tabIndex !== 'undefined' ? tabIndex : 0 }, children)))); };