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 | 简体中文
- 🔒 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
npm install tiny-event-intercept
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()
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
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')
},
})
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
})
let isModalOpen = false
const cleanup = interceptEvents(document, {
events: 'keydown',
when: () => isModalOpen,
listener: (event) => {
if (event.key === 'Escape') {
closeModal()
event.preventDefault()
}
},
})
const featureButton = document.querySelector('#new-feature-btn')
const cleanup = interceptEvents(featureButton, {
events: 'click',
when: () => !window.featureFlags?.newFeatureEnabled,
listener: (event) => {
event.preventDefault()
showFeatureNotAvailable()
},
})
// 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')
},
})
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()
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>
)
}
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 }
},
}
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
MIT