npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tiny-event-intercept

v2.0.0

Published

Lightweight (~1.2KB gzip) TypeScript library for conditional event interception with browser-standard API. Zero dependencies, browser-first, SSR-safe.

Readme

tiny-event-intercept

npm version TypeScript License: MIT Bundle Size

A lightweight (~1.2KB gzip), zero-dependency TypeScript library for conditional event interception with browser-standard API. Designed for modern web apps and safe to call in SSR or other non-browser environments.

Languages: English | 简体中文

Features

  • 🔒 Type Safe: Full TypeScript support with strict typing and IntelliSense
  • 🌐 Browser-First: Works in browsers and safely returns a noop cleanup outside the browser
  • 🧹 Predictable Cleanup: Explicit cleanup with AbortSignal support
  • ⚡ Performance: Optimized event handling with minimal overhead (~700K ops/sec)
  • 📦 Lightweight: About ~1.2KB gzip for the runtime bundle, zero dependencies
  • 🎯 Browser Standard: Extends native AddEventListenerOptions API
  • 🔄 Framework Agnostic: Works with React, Vue, Svelte, or vanilla JavaScript

Installation

npm install tiny-event-intercept

Quick Start

import { interceptEvents } from 'tiny-event-intercept'

// Prevent clicks when feature is disabled
let isFeatureEnabled = false

const cleanup = interceptEvents(document, {
  events: 'click',
  when: () => !isFeatureEnabled, // Only intercept when feature is disabled
  listener: (event) => {
    console.log('Feature is currently disabled')
    event.preventDefault()
    event.stopPropagation()
  },
})

// Enable feature later
isFeatureEnabled = true

// Clean up when done (removes all event listeners)
cleanup()

API

interceptEvents(target, options): CleanupFunction

Creates conditional event interceptors with a browser-standard API.

function interceptEvents(target: TargetElement, options: InterceptOptions): CleanupFunction

// Types
type TargetElement = EventTarget | (() => EventTarget | null) | null
type EventTypes<K extends keyof GlobalEventHandlersEventMap = keyof GlobalEventHandlersEventMap> =
  | K
  | readonly K[]

interface InterceptOptions<K extends keyof GlobalEventHandlersEventMap = keyof GlobalEventHandlersEventMap>
  extends AddEventListenerOptions {
  events: EventTypes<K> // Event types to intercept
  when: () => boolean // Condition function
  listener: (event: GlobalEventHandlersEventMap[K]) => void // Event handler
  // Inherits: capture?, once?, passive?, signal?
}

type EventTarget = Element | Document | Window
type CleanupFunction = () => void

Parameters:

  • target - Target element, function returning element, or null (defaults to document)
  • options - Intercept options including events, condition, and listener

Returns:

  • CleanupFunction - Function to remove all event listeners

Notes:

  • target === null defaults to document
  • Function targets are resolved once when interceptEvents() is called
  • If a target resolver returns null or throws, no listeners are attached
  • Use as const for event arrays if you want the narrowest union type in listener

Real-World Use Cases

1. Form Validation Blocking

const submitButton = document.querySelector('#submit-btn')
let isFormValid = false

const cleanup = interceptEvents(submitButton, {
  events: 'click',
  when: () => !isFormValid,
  listener: (event) => {
    event.preventDefault()
    showValidationErrors()
    console.log('Form submission blocked - validation failed')
  },
})

2. Loading State Management

let isLoading = false

const cleanup = interceptEvents(document, {
  events: ['click', 'keydown', 'submit'],
  when: () => isLoading,
  listener: (event) => {
    event.preventDefault()
    event.stopPropagation()
    showLoadingMessage('Please wait...')
  },
  capture: true, // Intercept in capture phase for better control
})

3. Modal/Dialog Interaction Control

let isModalOpen = false

const cleanup = interceptEvents(document, {
  events: 'keydown',
  when: () => isModalOpen,
  listener: (event) => {
    if (event.key === 'Escape') {
      closeModal()
      event.preventDefault()
    }
  },
})

4. Feature Flag Implementation

const featureButton = document.querySelector('#new-feature-btn')

const cleanup = interceptEvents(featureButton, {
  events: 'click',
  when: () => !window.featureFlags?.newFeatureEnabled,
  listener: (event) => {
    event.preventDefault()
    showFeatureNotAvailable()
  },
})

5. Lazy Target Resolution

// Resolve the active tab once when registering listeners
const cleanup = interceptEvents(() => document.querySelector('.tab.active'), {
  events: 'click',
  when: () => isTabSwitchingDisabled,
  listener: (event) => {
    event.preventDefault()
    showMessage('Tab switching is temporarily disabled')
  },
})

6. Advanced Options Usage

const controller = new AbortController()

const cleanup = interceptEvents(document.body, {
  events: ['mousedown', 'touchstart'],
  when: () => isDragModeActive,
  listener: (event) => {
    startDragOperation(event)
  },
  capture: true, // Capture phase for early interception
  passive: false, // Allow preventDefault()
  signal: controller.signal, // AbortController support
})

// Later: abort all listeners
controller.abort()

Framework Integration

React

import { useEffect, useState } from 'react'
import { interceptEvents } from 'tiny-event-intercept'

function FeatureToggle() {
  const [isEnabled, setIsEnabled] = useState(false)

  useEffect(() => {
    const cleanup = interceptEvents(document, {
      events: 'click',
      when: () => !isEnabled,
      listener: (event) => {
        console.log('Feature disabled')
        event.preventDefault()
      }
    })

    return cleanup // Cleanup on unmount
  }, [isEnabled])

  return (
    <button onClick={() => setIsEnabled(!isEnabled)}>
      {isEnabled ? 'Disable' : 'Enable'} Feature
    </button>
  )
}

Vue

import { onMounted, onUnmounted, ref } from 'vue'
import { interceptEvents } from 'tiny-event-intercept'

export default {
  setup() {
    const isEnabled = ref(false)
    let cleanup: (() => void) | null = null

    onMounted(() => {
      cleanup = interceptEvents(document, {
        events: 'click',
        when: () => !isEnabled.value,
        listener: (event) => event.preventDefault(),
      })
    })

    onUnmounted(() => {
      cleanup?.()
    })

    return { isEnabled }
  },
}

Memory Management

The library provides predictable cleanup mechanisms:

  • Manual cleanup: Call the returned cleanup function
  • AbortSignal support: Native listener cleanup via signal
  • Idempotent: Safe to call cleanup multiple times
const cleanup = interceptEvents(document, {
  events: 'click',
  when: () => true,
  listener: () => {},
})

// Safe to call multiple times
cleanup()
cleanup() // No errors

License

MIT