@adaptabletools/adaptable
Version:
Powerful AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
120 lines (119 loc) • 5.31 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import { cn } from '../../lib/utils';
import { useRef, useEffect } from 'react';
import contains from '../utils/contains';
import captureTabNavigation from '../utils/captureTabNavigation';
import { Modal } from '../Modal';
import useIsOpen from './useIsOpen';
import useAutoFocus from '../utils/useAutoFocus';
import { Icon } from '../icons';
import { WindowModal } from '../WindowModal';
import { Box } from '../Flex';
import { targetOwn } from '../twUtils';
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, showCloseButton = true, isOpen: _isOpenProp, ...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 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 ? (_jsx(Box, { title: "Close dialog", onClick: () => setIsOpen(false), className: cn(`${baseClassName}__close-button twa:p-1`, 'twa:text-accentlight', 'twa:text-shadow-[0_1px_0_#fff]', `twa:text-3 twa:cursor-pointer twa:leading-none twa:font-bold`, 'twa:absolute twa:top-[6px] twa:right-[6px]'), children: _jsx(Icon, { size: 20, name: "close" }) })) : null;
const setPreventDismissFlag = (e) => {
if (dismissOnClickOutside) {
e.nativeEvent.preventDialogDismiss = true;
}
};
const box = (_jsxs(Box, { ...boxProps, onClick: (e) => {
setPreventDismissFlag(e);
if (boxProps && boxProps.onClick) {
boxProps.onClick(e);
}
}, onKeyDown: onKeyDown, className: cn('twa:relative', 'twa:bg-background', 'twa:text-foreground', 'twa:fill-foreground', 'twa:rounded-standard', 'twa:flex twa:flex-col', targetOwn.focusOutline, targetOwn.focusWithinOutline, baseClassName, modal ? `${baseClassName}--modal` : `${baseClassName}--not-modal`, className), ref: boxRef, children: [children, closeButton] }));
const content = fixed ? (_jsx("div", { onClick: setPreventDismissFlag, className: cn(`${baseClassName}-fixed-wrapper`, 'twa:fixed twa:inset-0', 'twa:m-auto', 'twa:flex twa:items-center twa:justify-center'), children: box })) : (box);
if (windowModal) {
return _jsx(WindowModal, { ...windowModalProps, children: content });
}
if (modal) {
return (_jsx(Modal, { ...modalProps, isOpen: isOpen, onBringToFront: bringToFront, children: box }));
}
return content;
});
export default Dialog;