const traps = { mousemoveoutside: /* @__PURE__ */ new WeakMap(), clickoutside: /* @__PURE__ */ new WeakMap() }; function createTrapHandler(name, el, originalHandler) { if (name === "mousemoveoutside") { const moveHandler = (e) => { if (el.contains(e.target)) return; originalHandler(e); }; return { mousemove: moveHandler, touchstart: moveHandler }; } else if (name === "clickoutside") { let mouseDownOutside = false; const downHandler = (e) => { mouseDownOutside = !el.contains(e.target); }; const upHanlder = (e) => { if (!mouseDownOutside) return; if (el.contains(e.target)) return; originalHandler(e); }; return { mousedown: downHandler, mouseup: upHanlder, touchstart: downHandler, touchend: upHanlder }; } console.error(`[evtd/create-trap-handler]: name \`${name}\` is invalid. This could be a bug of evtd.`); return {}; } function ensureTrapHandlers(name, el, handler) { const handlers = traps[name]; let elHandlers = handlers.get(el); if (elHandlers === void 0) { handlers.set(el, elHandlers = /* @__PURE__ */ new WeakMap()); } let trapHandler = elHandlers.get(handler); if (trapHandler === void 0) { elHandlers.set(handler, trapHandler = createTrapHandler(name, el, handler)); } return trapHandler; } function trapOn(name, el, handler, options) { if (name === "mousemoveoutside" || name === "clickoutside") { const trapHandlers = ensureTrapHandlers(name, el, handler); Object.keys(trapHandlers).forEach((key) => { on(key, document, trapHandlers[key], options); }); return true; } return false; } function trapOff(name, el, handler, options) { if (name === "mousemoveoutside" || name === "clickoutside") { const trapHandlers = ensureTrapHandlers(name, el, handler); Object.keys(trapHandlers).forEach((key) => { off(key, document, trapHandlers[key], options); }); return true; } return false; } function createDelegate() { if (typeof window === "undefined") { return { on: () => { }, off: () => { } }; } const propagationStopped = /* @__PURE__ */ new WeakMap(); const immediatePropagationStopped = /* @__PURE__ */ new WeakMap(); function trackPropagation() { propagationStopped.set(this, true); } function trackImmediate() { propagationStopped.set(this, true); immediatePropagationStopped.set(this, true); } function spy(event, propName, fn) { const source = event[propName]; event[propName] = function() { fn.apply(event, arguments); return source.apply(event, arguments); }; return event; } function unspy(event, propName) { event[propName] = Event.prototype[propName]; } const currentTargets = /* @__PURE__ */ new WeakMap(); const currentTargetDescriptor = Object.getOwnPropertyDescriptor(Event.prototype, "currentTarget"); function getCurrentTarget() { var _a; return (_a = currentTargets.get(this)) !== null && _a !== void 0 ? _a : null; } function defineCurrentTarget(event, getter) { if (currentTargetDescriptor === void 0) return; Object.defineProperty(event, "currentTarget", { configurable: true, enumerable: true, get: getter !== null && getter !== void 0 ? getter : currentTargetDescriptor.get }); } const phaseToTypeToElToHandlers = { bubble: {}, capture: {} }; const typeToWindowEventHandlers = {}; function createUnifiedHandler() { const delegeteHandler = function(e) { const { type, eventPhase, target, bubbles } = e; if (eventPhase === 2) return; const phase = eventPhase === 1 ? "capture" : "bubble"; let cursor = target; const path = []; while (true) { if (cursor === null) cursor = window; path.push(cursor); if (cursor === window) { break; } cursor = cursor.parentNode || null; } const captureElToHandlers = phaseToTypeToElToHandlers.capture[type]; const bubbleElToHandlers = phaseToTypeToElToHandlers.bubble[type]; spy(e, "stopPropagation", trackPropagation); spy(e, "stopImmediatePropagation", trackImmediate); defineCurrentTarget(e, getCurrentTarget); if (phase === "capture") { if (captureElToHandlers === void 0) return; for (let i = path.length - 1; i >= 0; --i) { if (propagationStopped.has(e)) break; const target2 = path[i]; const handlers = captureElToHandlers.get(target2); if (handlers !== void 0) { currentTargets.set(e, target2); for (const handler of handlers) { if (immediatePropagationStopped.has(e)) break; handler(e); } } if (i === 0 && !bubbles && bubbleElToHandlers !== void 0) { const bubbleHandlers = bubbleElToHandlers.get(target2); if (bubbleHandlers !== void 0) { for (const handler of bubbleHandlers) { if (immediatePropagationStopped.has(e)) break; handler(e); } } } } } else if (phase === "bubble") { if (bubbleElToHandlers === void 0) return; for (let i = 0; i < path.length; ++i) { if (propagationStopped.has(e)) break; const target2 = path[i]; const handlers = bubbleElToHandlers.get(target2); if (handlers !== void 0) { currentTargets.set(e, target2); for (const handler of handlers) { if (immediatePropagationStopped.has(e)) break; handler(e); } } } } unspy(e, "stopPropagation"); unspy(e, "stopImmediatePropagation"); defineCurrentTarget(e); }; delegeteHandler.displayName = "evtdUnifiedHandler"; return delegeteHandler; } function createUnifiedWindowEventHandler() { const delegateHandler = function(e) { const { type, eventPhase } = e; if (eventPhase !== 2) return; const handlers = typeToWindowEventHandlers[type]; if (handlers === void 0) return; handlers.forEach((handler) => handler(e)); }; delegateHandler.displayName = "evtdUnifiedWindowEventHandler"; return delegateHandler; } const unifiedHandler = createUnifiedHandler(); const unfiendWindowEventHandler = createUnifiedWindowEventHandler(); function ensureElToHandlers(phase, type) { const phaseHandlers = phaseToTypeToElToHandlers[phase]; if (phaseHandlers[type] === void 0) { phaseHandlers[type] = /* @__PURE__ */ new Map(); window.addEventListener(type, unifiedHandler, phase === "capture"); } return phaseHandlers[type]; } function ensureWindowEventHandlers(type) { const windowEventHandlers = typeToWindowEventHandlers[type]; if (windowEventHandlers === void 0) { typeToWindowEventHandlers[type] = /* @__PURE__ */ new Set(); window.addEventListener(type, unfiendWindowEventHandler); } return typeToWindowEventHandlers[type]; } function ensureHandlers(elToHandlers, el) { let elHandlers = elToHandlers.get(el); if (elHandlers === void 0) { elToHandlers.set(el, elHandlers = /* @__PURE__ */ new Set()); } return elHandlers; } function handlerExist(el, phase, type, handler) { const elToHandlers = phaseToTypeToElToHandlers[phase][type]; if (elToHandlers !== void 0) { const handlers = elToHandlers.get(el); if (handlers !== void 0) { if (handlers.has(handler)) return true; } } return false; } function windowEventHandlerExist(type, handler) { const handlers = typeToWindowEventHandlers[type]; if (handlers !== void 0) { if (handlers.has(handler)) { return true; } } return false; } function on2(type, el, handler, options) { let mergedHandler; if (typeof options === "object" && options.once === true) { mergedHandler = (e) => { off2(type, el, mergedHandler, options); handler(e); }; } else { mergedHandler = handler; } const trapped = trapOn(type, el, mergedHandler, options); if (trapped) return; const phase = options === true || typeof options === "object" && options.capture === true ? "capture" : "bubble"; const elToHandlers = ensureElToHandlers(phase, type); const handlers = ensureHandlers(elToHandlers, el); if (!handlers.has(mergedHandler)) handlers.add(mergedHandler); if (el === window) { const windowEventHandlers = ensureWindowEventHandlers(type); if (!windowEventHandlers.has(mergedHandler)) { windowEventHandlers.add(mergedHandler); } } } function off2(type, el, handler, options) { const trapped = trapOff(type, el, handler, options); if (trapped) return; const capture = options === true || typeof options === "object" && options.capture === true; const phase = capture ? "capture" : "bubble"; const elToHandlers = ensureElToHandlers(phase, type); const handlers = ensureHandlers(elToHandlers, el); if (el === window) { const mirrorPhase = capture ? "bubble" : "capture"; if (!handlerExist(el, mirrorPhase, type, handler) && windowEventHandlerExist(type, handler)) { const windowEventHandlers = typeToWindowEventHandlers[type]; windowEventHandlers.delete(handler); if (windowEventHandlers.size === 0) { window.removeEventListener(type, unfiendWindowEventHandler); typeToWindowEventHandlers[type] = void 0; } } } if (handlers.has(handler)) handlers.delete(handler); if (handlers.size === 0) { elToHandlers.delete(el); } if (elToHandlers.size === 0) { window.removeEventListener(type, unifiedHandler, phase === "capture"); phaseToTypeToElToHandlers[phase][type] = void 0; } } return { on: on2, off: off2 }; } const { on, off } = createDelegate(); export { off as a, on as o };