/** @internal */ const delegatedEvents = [];
/**
 * Creates the delegated event handler that will run all the callbacks once an
 * event happens. The callbacks' invocation can also be throttled for event
 * types that trigger rapidly for additional performance.
 *
 * The `<K extends keyof WindowEventMap` is a nice thing I found while looking
 * through the `lib.d.ts` implementation of `addEventListener` that will allow
 * you to get the "correct" event type when using the `add` and `remove`
 * functions once you have created this event handler. Otherwise there'd be ts
 * errors trying to do `MouseEvent` or `KeyboardEvent` in your listeners.
 */ function createEventHandler(throttle, callbacks) {
    let running = false;
    const runCallbacks = (event)=>()=>{
            for(let i = 0; i < callbacks.length; i += 1){
                callbacks[i](event);
            }
            running = false;
        };
    return function eventHandler(event) {
        if (!throttle) {
            runCallbacks(event)();
            return;
        }
        if (running) {
            return;
        }
        running = true;
        window.requestAnimationFrame(runCallbacks(event));
    };
}
/**
 * Creates a throttled event handler for the provided event type and event
 * target.
 */ function createDelegatedEventHandler(eventType, eventTarget = window, throttle = false, options) {
    const callbacks = [];
    const handler = createEventHandler(throttle, callbacks);
    return {
        /**
     * Attempts to add the provided callback to the list of callbacks for the
     * throttled event. If this is the first callback to be added, the throttled
     * event will also be started.
     */ add: (callback)=>{
            if (!callbacks.length) {
                eventTarget.addEventListener(eventType, handler, options);
            }
            if (callbacks.indexOf(callback) === -1) {
                callbacks.push(callback);
            }
        },
        /**
     * Attempts to remove the provided callback from the list of callbacks for
     * the throttled event. If this is the last callback that was removed, the
     * throttled event will also be stopped.
     */ remove: (callback)=>{
            const i = callbacks.indexOf(callback);
            if (i >= 0) {
                callbacks.splice(i, 1);
                if (!callbacks.length) {
                    eventTarget.removeEventListener(eventType, handler, options);
                }
            }
        }
    };
}
/**
 * Creates a delegated event listener using custom events. Most of this code
 * comes from the MDN about resize listeners.
 *
 * This will return an object for adding or removing event handlers for the
 * provided `eventType` since only one base throttled event listener will be
 * created. Each callback that is added will be called with the event each time
 * the event is triggered. This does mean that you will manually need to remove
 * your callback like normal or else it can be called when no longer in use.
 * This also means that it doesn't "hurt" to call this function without
 * immediately calling the `add` function since the event won't start until
 * there is at least 1 callback.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/Events/resize#Examples
 * @param eventType - One of the event types that should be used to create a
 * delegated event for. This should be things like resize, click, scroll, etc.
 * @param eventTarget - The target that should have the delegated event handler
 * attached to. This is normally the window, but can be any element as needed.
 * @param throttle - Boolean if the event should be throttled or not. Normally
 * only event types like resize or scroll should be throttled for performance
 * boosts, but anything can be.
 * @returns The delegated event handler that allows you to add or remove
 * `EventListener`s to that event.
 * @internal
 */ export function delegateEvent(eventType, eventTarget = window, throttle = eventType === "resize" || eventType === "scroll", options) {
    let index = delegatedEvents.findIndex((event)=>event.type === eventType && event.target === eventTarget && event.options === options && event.throttle === throttle);
    if (index === -1) {
        delegatedEvents.push({
            type: eventType,
            target: eventTarget,
            options,
            throttle,
            handler: createDelegatedEventHandler(eventType, eventTarget, throttle, options)
        });
        index = delegatedEvents.length - 1;
    }
    return delegatedEvents[index].handler;
}

//# sourceMappingURL=delegateEvent.js.map