UNPKG

tiny-event-intercept

Version:

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

271 lines (207 loc) 6.83 kB
# tiny-event-intercept [![npm version](https://badge.fury.io/js/tiny-event-intercept.svg)](https://badge.fury.io/js/tiny-event-intercept) [![TypeScript](https://img.shields.io/badge/TypeScript-5.8+-blue.svg)](https://www.typescriptlang.org/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Bundle Size](https://img.shields.io/bundlephobia/minzip/tiny-event-intercept)](https://bundlephobia.com/package/tiny-event-intercept) 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 | [简体中文](./README_zh-CN.md) ## 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 ```bash npm install tiny-event-intercept ``` ## Quick Start ```typescript 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. ```typescript 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 ```typescript 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 ```typescript 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 ```typescript let isModalOpen = false const cleanup = interceptEvents(document, { events: 'keydown', when: () => isModalOpen, listener: (event) => { if (event.key === 'Escape') { closeModal() event.preventDefault() } }, }) ``` ### 4. Feature Flag Implementation ```typescript 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 ```typescript // 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 ```typescript 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 ```typescript 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 ```typescript 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 ```typescript const cleanup = interceptEvents(document, { events: 'click', when: () => true, listener: () => {}, }) // Safe to call multiple times cleanup() cleanup() // No errors ``` ## License MIT