UNPKG

watch-selector

Version:

Runs a function when a selector is added to dom

167 lines โ€ข 7.39 kB
/** * @module watch-selector * * A powerful, type-safe DOM observation library with generator-based composition. * Watch is a lightweight alternative to web components and frameworks, perfect for * server-driven websites, user scripts, Chrome extensions, and anywhere you need * reactive DOM interactions without controlling the markup. * * ## Key Features * * - ๐ŸŽฏ **Selector-Based**: Watch for elements matching CSS selectors * - ๐Ÿ”„ **Generator Composition**: Yield functions for elegant async flows * - ๐Ÿง  **Smart State Management**: Per-element state with reactivity * - โšก **Advanced Events**: Debouncing, throttling, delegation, queuing * - ๐ŸŽจ **DOM Manipulation**: Comprehensive dual API (direct + generator) * - ๐Ÿ›ก๏ธ **Type-Safe**: Full TypeScript support with inference * - ๐Ÿงน **Memory Safe**: Automatic cleanup and lifecycle management * - ๐ŸŽ›๏ธ **Controller System**: Layer behaviors and manage instances * * @example Basic Usage * ```typescript * import { watch, click, addClass, text } from 'watch-selector'; * * // Watch buttons and make them interactive * watch('button', function* () { * yield addClass('interactive'); * yield click((event, button) => { * text(button, 'Clicked!'); * }); * }); * ``` * * @example Generator Event Handlers * ```typescript * import { watch, click, addClass, removeClass, delay, getState, setState } from 'watch-selector'; * * watch('.counter', function* () { * yield click(function* (event) { * // Full access to Watch context! * const button = self(); * const count = getState('clicks') || 0; * * // Yield Watch functions for elegant composition * yield addClass('clicked'); * yield delay(150); * yield removeClass('clicked'); * * // Update state and DOM * setState('clicks', count + 1); * yield text(`Clicked ${count + 1} times`); * }); * }); * ``` * * @example Advanced Event Handling * ```typescript * import { watch, on, input, setState, getState } from 'watch-selector'; * * watch('.search-form', function* () { * // Real-time search with advanced options * yield input(function* (event) { * const query = (event.target as HTMLInputElement).value; * setState('query', query); * * // Perform search * const results = await searchAPI(query); * yield updateResults(results); * }, { * // Advanced debouncing with leading/trailing edge control * debounce: { wait: 300, leading: false, trailing: true }, * delegate: 'input[type="search"]', * queue: 'latest' // Cancel previous searches * }); * }); * ``` * * @example Component Composition * ```typescript * import { watch, createEventBehavior, composeEventHandlers } from 'watch-selector'; * * // Create reusable behaviors * const rippleEffect = createEventBehavior('click', function* (event) { * yield addClass('ripple'); * yield delay(600); * yield removeClass('ripple'); * }); * * const clickCounter = createEventBehavior('click', function* (event) { * const count = getState('clicks') || 0; * setState('clicks', count + 1); * yield text(`${count + 1} clicks`); * }); * * // Compose multiple behaviors * const materialButton = composeEventHandlers(rippleEffect, clickCounter); * * watch('.material-btn', function* () { * yield click(materialButton); * }); * ``` * * @example Controller System * ```typescript * import { watch } from 'watch-selector'; * * // Create a controller for behavior management * const buttonController = watch('button', function* () { * yield addClass('base-button'); * yield click(() => console.log('Base click')); * }); * * // Layer additional behaviors * buttonController.layer(function* () { * yield addClass('enhanced'); * yield click(() => console.log('Enhanced click')); * }); * * // Inspect managed instances * console.log(buttonController.getInstances()); * * // Clean up when done * buttonController.destroy(); * ``` * * @example State Management * ```typescript * import { watch, createState, setState, getState, watchState } from 'watch-selector'; * * watch('.todo-app', function* () { * // Create reactive state * const todos = createState('todos', []); * * // Watch state changes * watchState('todos', (newTodos, oldTodos) => { * console.log('Todos updated:', newTodos); * updateTodoList(newTodos); * }); * * yield click('.add-todo', function* () { * const input = el('input') as HTMLInputElement; * const currentTodos = getState('todos') || []; * setState('todos', [...currentTodos, input.value]); * input.value = ''; * }); * }); * ``` * * @version 1.0.0 * @author Patrick Glenn * @license MIT */ export { watch, run, runOn, layer, getInstances, destroy } from './watch'; export type { ElementFromSelector, ElementHandler, ElementFn, WatchContext, ElementProxy, SelfFunction, GeneratorFunction, CleanupFunction, ElementEventHandler, AttributeChange, TextChange, VisibilityChange, ResizeChange, MountHandler, UnmountHandler, WatchTarget, ElementMatcher, ParentContext, WatchController, ManagedInstance, CustomEventHandler, EventHandler, WatchEventListenerOptions, HybridEventHandler as EnhancedEventHandler, HybridCustomEventHandler as EnhancedCustomEventHandler, HybridEventOptions as EnhancedEventOptions, DebounceOptions, ThrottleOptions } from './types'; export { isElement, isElementLike, resolveElement, text, html, addClass, removeClass, toggleClass, hasClass, style, attr, removeAttr, hasAttr, prop, data, value, checked, focus, blur, show, hide, query, queryAll, parent, children, siblings, batchAll, el as elDOM, all as allDOM, createChildWatcher, child } from './api/dom'; export { on, emit, click, change, input, submit, createEventBehavior, composeEventHandlers, delegate, createCustomEvent, onAttr, onText, onVisible, onResize, onMount, onUnmount } from './api/events-hybrid'; export { self, el, all, cleanup, ctx, createGenerator, gen, watchGenerator, getParentContext } from './core/generator'; export { context, contextFor, button, input as inputFactory, form, div, span, withData, withDebounce, withThrottle, once as onceFactory, withFilter } from './core/context-factory'; export { debounceGenerator, throttleGenerator, onceGenerator, delayGenerator, batchGenerator } from './core/generator-utils'; export { getState, setState, updateState, hasState, deleteState, createTypedState, createState, createComputed, watchState, setStateReactive, batchStateUpdates, createPersistedState, clearAllState, debugState, logState } from './core/state'; export { once as onceHelper, delay, throttle, debounce, when, safely, batch, retry, rateLimit, memoize, timeout, compose, unless, async } from './core/execution-helpers'; export { getCurrentElement, getCurrentContext } from './core/context'; export { register, getObserverStatus, cleanup as cleanupObserver } from './core/observer'; export { scopedWatch, scopedWatchBatch, scopedWatchTimeout, scopedWatchOnce, scopedWatchWithController, scopedWatchBatchWithController, type ScopedWatchOptions, type ScopedWatcher } from './scoped-watch'; export { createScopedWatcher, disconnectScopedWatchers, getScopedWatchers } from './core/scoped-observer'; export { el as $ } from './core/generator'; export { watch as default } from './watch'; //# sourceMappingURL=index.d.ts.map