UNPKG

@itwin/core-react

Version:

A react component library of iTwin.js UI general purpose components

110 lines 5.18 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Common */ import * as React from "react"; /** withOnOutsideClick is a React higher-order component that adds outside click support. * @public * @deprecated in 4.15.0. Used internally. */ export const withOnOutsideClick = (Component, defaultOnOutsideClick, useCapture = true, usePointerEvents = true) => { return class WithOnOutsideClick extends React.PureComponent { constructor() { super(...arguments); /** @internal */ this.outsideClickContainerDiv = null; /** @internal */ this.isDownOutside = false; /** @internal */ this.handleDocumentClick = (e) => { if (!this.outsideClickContainerDiv || !(e.target instanceof Node) || this.outsideClickContainerDiv.contains(e.target)) return; return this.onOutsideClick(e); }; /** @internal */ this.handleDocumentPointerDown = (e) => { this.isDownOutside = true; if (this.outsideClickContainerDiv) { // typically e.target test for instance of Node, but this is not working from pop out windows this.isDownOutside = !!e.target && !this.outsideClickContainerDiv.contains(e.target); } }; /** @internal */ this.handleDocumentPointerUp = (e) => { let isUpOutside = true; if (this.outsideClickContainerDiv) { // typically e.target test for instance of Node, but this is not working from pop out windows isUpOutside = !!e.target && !this.outsideClickContainerDiv.contains(e.target); } const isOutsideClick = isUpOutside && this.isDownOutside; this.isDownOutside = false; isOutsideClick && this.onOutsideClick(e); }; this.handleOutsideClickContainerDivSet = (outsideClickContainerDiv) => { this.outsideClickContainerDiv = outsideClickContainerDiv; }; } /** @internal */ isInCorePopup(element) { if (element.nodeName === "DIV") { if (element.classList && element.classList.contains("core-popup")) return true; if (element.parentElement && this.isInCorePopup(element.parentElement)) return true; } else { if (element.parentElement && this.isInCorePopup(element.parentElement)) return true; } return false; } /** @internal */ onOutsideClick(e) { if (e.target instanceof Node && e.target.nodeType === Node.ELEMENT_NODE) { if (!this.props.closeOnNestedPopupOutsideClick && this.isInCorePopup(e.target)) return; } if (this.props.onOutsideClick) return this.props.onOutsideClick(e); else if (defaultOnOutsideClick) return defaultOnOutsideClick(e); } getParentDocument() { return this.outsideClickContainerDiv?.ownerDocument ?? document; } componentDidMount() { const outsideClickParentDocument = this.getParentDocument(); if (usePointerEvents) { outsideClickParentDocument.addEventListener("pointerdown", this.handleDocumentPointerDown, useCapture); outsideClickParentDocument.addEventListener("pointerup", this.handleDocumentPointerUp, useCapture); } else outsideClickParentDocument.addEventListener("click", this.handleDocumentClick, useCapture); } componentWillUnmount() { const outsideClickParentDocument = this.getParentDocument(); if (usePointerEvents) { outsideClickParentDocument.removeEventListener("pointerdown", this.handleDocumentPointerDown, useCapture); outsideClickParentDocument.removeEventListener("pointerup", this.handleDocumentPointerUp, useCapture); } else outsideClickParentDocument.removeEventListener("click", this.handleDocumentClick, useCapture); } render() { const { onOutsideClick, closeOnNestedPopupOutsideClick, ...props } = this.props; return (React.createElement("div", { ref: this.handleOutsideClickContainerDivSet }, React.createElement(Component, { ...props }))); } }; }; //# sourceMappingURL=withOnOutsideClick.js.map