rc-hooks
Version:
React Hooks Library.
65 lines (64 loc) • 2.52 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var react_1 = require("react");
var ut2_1 = require("ut2");
var getRef_1 = tslib_1.__importDefault(require("../utils/getRef"));
var useLatest_1 = tslib_1.__importDefault(require("../useLatest"));
/**
* 管理目标元素外事件的 Hook。
*
* @param {Object} ref Dom 节点或 Ref 对象,支持数组。
* @param {Function} onClickAway 触发事件的函数。
* @param {string | string[]} [events='click'] 监听事件名称,支持数组。默认 `click`。
* @example
* const [count, setCount] = React.useState(0);
* const ref = React.useRef<HTMLSpanElement>(null);
*
* useClickAway(ref, () => {
* setCount((c) => c + 1);
* });
*
* return (
* <div>
* <span ref={ref}>
* <button>box</button>
* </span>
* <p>count: {count}</p>
* </div>
* );
*/
function useClickAway(ref, onClickAway, events) {
if (events === void 0) { events = 'click'; }
var refs = (0, ut2_1.castArray)(ref);
var latestRefs = (0, useLatest_1.default)(refs);
var refsIsFunc = refs.every(function (item) { return typeof item === 'function'; });
var wrapperRefs = refsIsFunc ? latestRefs : refs;
var onClickAwayRef = (0, useLatest_1.default)(onClickAway);
var eventsArr = (0, ut2_1.castArray)(events);
var eventsRef = (0, useLatest_1.default)(eventsArr);
var eventsStr = eventsArr.join('');
(0, react_1.useEffect)(function () {
var handler = function (event) {
var _a;
var targets = refsIsFunc ? wrapperRefs.current : wrapperRefs;
if (!targets.some(function (targetItem) {
var target = (0, getRef_1.default)(targetItem);
return !target || (target === null || target === void 0 ? void 0 : target.contains(event.target));
})) {
(_a = onClickAwayRef.current) === null || _a === void 0 ? void 0 : _a.call(onClickAwayRef, event);
}
};
var eventList = (0, ut2_1.castArray)(eventsRef.current);
eventList.forEach(function (eventName) {
document.addEventListener(eventName, handler);
});
return function () {
eventList.forEach(function (eventName) {
document.removeEventListener(eventName, handler);
});
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [wrapperRefs, refsIsFunc, eventsStr]);
}
exports.default = useClickAway;