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 🙏

© 2025 – Pkg Stats / Ryan Hefner

tiny-event-intercept

v1.0.0

Published

Lightweight (~1.0KB) TypeScript library for conditional event interception with browser-standard API. Zero dependencies, SSR compatible, robust edge case handling.

Readme

tiny-event-intercept

npm version TypeScript License: MIT Bundle Size

A lightweight (~1.0KB), zero-dependency TypeScript library for conditional event interception with browser-standard API. Perfect for implementing conditional event handling in modern web applications.

Languages: English | 简体中文

Features

  • 🔒 Type Safe: Full TypeScript support with strict typing and IntelliSense
  • 🌐 Universal: SSR compatible, works in Node.js and browser environments
  • 🧹 Memory Safe: Automatic cleanup mechanisms prevent memory leaks
  • ⚡ Performance: Optimized event handling with minimal overhead (~700K ops/sec)
  • 📦 Lightweight: Only ~1.0KB minified, 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 = keyof GlobalEventHandlersEventMap | readonly (keyof GlobalEventHandlersEventMap)[]

interface InterceptOptions extends AddEventListenerOptions {
  events: EventTypes // Event types to intercept
  when: () => boolean // Condition function
  listener: EventListener // 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

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. Dynamic Target Selection

// Intercept clicks on currently active tab
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 robust cleanup mechanisms:

  • Manual cleanup: Call the returned cleanup function
  • Automatic cleanup: Listeners removed on page unload
  • 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