UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

122 lines (121 loc) 4.87 kB
import * as React from 'react'; import { useRef, useEffect } from 'react'; import join from '../utils/join'; import contains from '../utils/contains'; import captureTabNavigation from '../utils/captureTabNavigation'; import { Box } from 'rebass'; import { Modal } from '../Modal'; import useIsOpen from './useIsOpen'; import useAutoFocus from '../utils/useAutoFocus'; import { Icon } from '../icons'; import { WindowModal } from '../WindowModal'; const baseClassName = 'ab-Dialog'; export const Dialog = React.forwardRef((props, dialogRef) => { let { modal, fixed, focusOnBrowserVisible = false, autoFocus = true, className, children, modalProps, dismissOnClickOutside = false, onDismiss, windowModal, windowModalProps, ...boxProps } = props; modal = props.modal === undefined ? true : props.modal; fixed = props.fixed === undefined ? true : props.fixed; const [isOpen, setIsOpen] = useIsOpen(props); const boxRef = useRef(null); useAutoFocus({ isOpen, autoFocus: props.autoFocus, previous: ({ autoFocus }) => autoFocus && isOpen, shouldFocus: ({ autoFocus }) => autoFocus && isOpen, }, boxRef); const showCloseButton = props.showCloseButton === undefined ? true : props.showCloseButton; const onKeyDown = (e) => { if (props.onKeyDown) { props.onKeyDown(e); } captureTabNavigation(boxRef.current, e); if (e.key === 'Escape') { if (e.nativeEvent.anotherModalClosed) { return; } e.nativeEvent.anotherModalClosed = true; const activeElement = document.activeElement; const ignoreTags = { input: 1, a: 1, button: 1, }; if (activeElement && !!ignoreTags[activeElement.tagName]) { return; } setIsOpen(false); } captureTabNavigation(boxRef.current, event); }; useEffect(() => { if (dismissOnClickOutside && isOpen) { const dismissDialog = (e) => { requestAnimationFrame(() => { if (e.preventDialogDismiss) { return; } setIsOpen(false); }); }; document.documentElement.addEventListener('click', dismissDialog, { passive: true, capture: false, }); return () => { document.documentElement.removeEventListener('click', dismissDialog); }; } }, [isOpen, dismissOnClickOutside]); const bringToFront = React.useCallback(() => { if (boxRef.current && boxRef.current.focus && (!document.activeElement || !contains(boxRef.current, document.activeElement))) { boxRef.current.focus(); } }, [boxRef]); React.useImperativeHandle(dialogRef, () => ({ bringToFront, })); useEffect(() => { let listener; if (focusOnBrowserVisible) { listener = () => { if (document.visibilityState === 'visible' && autoFocus && focusOnBrowserVisible) { bringToFront(); } }; document.addEventListener('visibilitychange', listener); } return () => { if (listener) { document.removeEventListener('visibilitychange', listener); } }; }, [autoFocus, focusOnBrowserVisible]); if (!isOpen) { return null; } const closeButton = showCloseButton ? (React.createElement(Box, { padding: 1, title: "Close dialog", onClick: () => setIsOpen(false), className: `${baseClassName}__close-button` }, React.createElement(Icon, { size: 24, name: "close" }))) : null; const setPreventDismissFlag = (e) => { if (dismissOnClickOutside) { e.nativeEvent.preventDialogDismiss = true; } }; const box = (React.createElement(Box, { ...boxProps, onClick: (e) => { setPreventDismissFlag(e); if (boxProps && boxProps.onClick) { boxProps.onClick(e); } }, onKeyDown: onKeyDown, className: join(baseClassName, modal ? `${baseClassName}--modal` : `${baseClassName}--not-modal`, className), ref: boxRef }, children, closeButton)); const content = fixed ? (React.createElement("div", { onClick: setPreventDismissFlag, className: `${baseClassName}-fixed-wrapper` }, box)) : (box); if (windowModal) { return React.createElement(WindowModal, { ...windowModalProps }, content); } if (modal) { return (React.createElement(Modal, { ...modalProps, isOpen: isOpen, onBringToFront: bringToFront }, box)); } return content; }); export default Dialog;