@workday/canvas-kit-react
Version:
The parent module that contains all Workday Canvas Kit React components
52 lines (44 loc) • 1.86 kB
text/typescript
import React from 'react';
import {PopupStack} from '@workday/canvas-kit-popup-stack';
import {createElemPropsHook} from '@workday/canvas-kit-react/common';
import {usePopupModel} from './usePopupModel';
/**
* Registers global listener for all clicks. It will only call the PopupModel's `hide` event if the
* click happened outside the `stackRef` element and its children regardless of the position in the
* stack. This is useful for Tooltips or hierarchical menus. Adds a
* `data-behavior-click-outside-close="always"` attribute to ensure proper functionality.
*
* This should be used with popup elements that should close no matter their position in the stack
* (i.e. Tooltips).
*/
export const useAlwaysCloseOnOutsideClick = createElemPropsHook(usePopupModel)(model => {
const onClick = React.useCallback(
(event: MouseEvent) => {
if (!model.state.stackRef.current) {
return;
}
if (
// Use `PopupStack.contains` instead of `ref.current.contains` so that the application can
// decide if clicking the target should toggle the popup rather than it toggling implicitly
// because the target is outside `ref.current`
document.contains(event.target as HTMLElement) &&
!PopupStack.contains(model.state.stackRef.current, event.target as HTMLElement)
) {
model.events.hide(event);
}
},
[model.events, model.state.stackRef]
);
const visible = model.state.visibility !== 'hidden';
React.useLayoutEffect(() => {
if (!visible) {
return;
}
document.addEventListener('mousedown', onClick);
model.state.stackRef.current?.setAttribute('data-behavior-click-outside-close', 'always');
return () => {
document.removeEventListener('mousedown', onClick);
};
}, [model.state.stackRef, visible, onClick]);
return {};
});