UNPKG

fixed-react-data-grid-custom

Version:

Excel-like grid component built with React, with editors, keyboard navigation, copy & paste, and the like

56 lines (55 loc) 2.51 kB
import React from 'react'; /** * Detecting outside click on a react component is surprisingly hard. * A general approach is to have a global click handler on the document * which checks if the click target is inside the editor container or * not using editorContainer.contains(e.target). This approach works well * until portals are used for editors. Portals render children into a DOM * node that exists outside the DOM hierarchy of the parent component so * editorContainer.contains(e.target) does not work. Here are some examples * of the DOM structure with different types of editors * * * SimpleEditor for example Texbox (No Portals) * <div react-data-grid>..<div> * <div portal-created-by-the-grid-for-editors> * <div editor-container> * <div simple-editor>..</div> * </div> * <div> * * ComplexEditor for example Modals (using Portals) * <div react-data-grid>..<div> * <div portal-created-by-the-grid-for-editors> * <div editor-container> * // Nothing here * </div> * <div> * <div portal-created-by-the-editor> * <div complex-editor>..</div> * </div> * * * One approach to detect outside click is to use event bubbling through * portals. An event fired from inside a portal will propagate to ancestors * in the containing React tree, even if those elements are not ancestors * in the DOM tree. This means a click handler can be attached on the document * and on the editor container. The editor container can set a flag to notify * that the click was inside the editor and the document click handler can use * this flag to call onClickOutside. This approach however has a few caveats * - Click handler on the document is set using document.addEventListener * - Click handler on the editor container is set using onClick prop * * This means if a child component inside the editor calls e.stopPropagation * then the click handler on the editor container will not be called whereas * document click handler will be called. * https://github.com/facebook/react/issues/12518 * * To solve this issue onClickCapture event is used. */ interface Props { children: React.ReactElement; onClickOutside(): void; } export default function ClickOutside({ onClickOutside, children }: Props): React.ReactElement<any, string | ((props: any) => React.ReactElement<any, string | any | (new (props: any) => React.Component<any, any, any>)> | null) | (new (props: any) => React.Component<any, any, any>)>; export {};