New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

tiny-event-intercept

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tiny-event-intercept

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

latest
Source
npmnpm
Version
2.0.0
Version published
Maintainers
1
Created
Source

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

Keywords

event-intercept

FAQs

Package last updated on 14 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts