UNPKG

@ducor/react

Version:

admin template ui interface

97 lines (96 loc) 3.67 kB
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; import { useCallback, useEffect, useRef } from "react"; export function useCallbackRef(callback, deps) { if (deps === void 0) { deps = []; } var callbackRef = useRef(callback); useEffect(function () { callbackRef.current = callback; }); return useCallback((function () { var _a; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return (_a = callbackRef.current) === null || _a === void 0 ? void 0 : _a.call.apply(_a, __spreadArray([callbackRef], args, false)); }), // eslint-disable-next-line react-hooks/exhaustive-deps deps); } function isElement(el) { return (el != null && typeof el == "object" && "nodeType" in el && el.nodeType === Node.ELEMENT_NODE); } function getOwnerDocument(el) { return isElement(el) ? el.ownerDocument : document; } /** * `useOutsideClick` is a custom hook that detects click events outside of an element. * * @see Docs https://ui.ducor.net/hooks/use-outside-click */ var useOutsideClick = function (_a) { var ref = _a.ref, _b = _a.enabled, enabled = _b === void 0 ? true : _b, handler = _a.handler; var handlerRef = useCallbackRef(handler); var state = useRef({ ignoreEmulatedMouseEvents: false, isPointerDown: false, }); useEffect(function () { if (!enabled) return; var onPointerDown = function (ev) { if (isValidEvent(ev, ref)) state.current.isPointerDown = true; }; var onMouseUp = function (ev) { if (state.current.ignoreEmulatedMouseEvents) { state.current.ignoreEmulatedMouseEvents = false; return; } if (state.current.isPointerDown && handler && isValidEvent(ev, ref)) { state.current.isPointerDown = false; handlerRef(ev); } }; var onTouchEnd = function (ev) { state.current.ignoreEmulatedMouseEvents = true; if (handler && state.current.isPointerDown && isValidEvent(ev, ref)) { state.current.isPointerDown = false; handlerRef(ev); } }; var doc = getOwnerDocument(ref.current); doc.addEventListener("mousedown", onPointerDown, true); doc.addEventListener("mouseup", onMouseUp, true); doc.addEventListener("touchstart", onPointerDown, true); doc.addEventListener("touchend", onTouchEnd, true); return function () { doc.removeEventListener("mousedown", onPointerDown, true); doc.removeEventListener("mouseup", onMouseUp, true); doc.removeEventListener("touchstart", onPointerDown, true); doc.removeEventListener("touchend", onTouchEnd, true); }; }, [handler, ref, handlerRef, state, enabled]); }; var isValidEvent = function (ev, ref) { var _a; var target = ev.target; if ("button" in ev && ev.button > 0) return false; if (target) if (!getOwnerDocument(target).contains(target)) return false; return !((_a = ref.current) === null || _a === void 0 ? void 0 : _a.contains(target)); }; export default useOutsideClick;