UNPKG

@workday/canvas-kit-react

Version:

The parent module that contains all Workday Canvas Kit React components

49 lines (48 loc) 2.45 kB
import React from 'react'; import { PopupStack } from '@workday/canvas-kit-popup-stack'; import { createElemPropsHook, useModalityType } from '@workday/canvas-kit-react/common'; import { usePopupModel } from '@workday/canvas-kit-react/popup'; /** * Registers global listener for all clicks. It will only call the PopupModel's `hide` event if the * click happened outside the `[role=dialog]` of an overlay component. The difference between `useCloseOnOutsideClick` * and `useCloseOnOverlayClick` is the Overlay is a child of a `stackRef` element and has a different */ export const useCloseOnOverlayClick = createElemPropsHook(usePopupModel)(model => { const modality = useModalityType(); const onClick = React.useCallback((event) => { if (!model.state.stackRef.current) { return; } const elements = PopupStack.getElements() .filter(e => e.getAttribute('data-behavior-click-outside-close') === 'topmost') .sort((a, b) => Number(a.style.zIndex) - Number(b.style.zIndex)); const dialog = model.state.stackRef.current.querySelector('[role=dialog]'); // Create a list of parent elements of the dialog to detect overlay clicks const elementsBetweenDialogAnBody = []; let element = dialog; while (element === null || element === void 0 ? void 0 : element.parentElement) { elementsBetweenDialogAnBody.push(element.parentElement); element = (element === null || element === void 0 ? void 0 : element.parentElement) || null; } if (dialog && modality !== 'touch' && elements.length && elements[elements.length - 1] === model.state.stackRef.current && elementsBetweenDialogAnBody.some(element => element === event.target)) { model.events.hide(event); } }, [model.state.stackRef, model.events, modality]); const visible = model.state.visibility !== 'hidden'; React.useLayoutEffect(() => { var _a; if (!visible) { return; } document.addEventListener('mousedown', onClick); (_a = model.state.stackRef.current) === null || _a === void 0 ? void 0 : _a.setAttribute('data-behavior-click-outside-close', 'topmost'); return () => { document.removeEventListener('mousedown', onClick); }; }, [model.state.stackRef, visible, onClick]); return {}; });