Skip to content

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

License

Notifications You must be signed in to change notification settings

crper/tiny-event-intercept

Repository files navigation

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

About

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

Topics

Resources

License

Contributing

Stars

Watchers

Forks