/** * Lume.js Addons TypeScript Definitions * * Optional utilities for advanced reactive patterns. * Import from "lume-js/addons" for tree-shaking. */ import type { Unsubscribe, Subscriber, ReactiveState, TypedPlugin } from '../index.js'; export type { TypedPlugin }; /** * Computed value container returned by computed(). * T is the computed result type; when an error occurs the value becomes undefined. */ export interface Computed { /** Current computed value (undefined if computation threw). */ readonly value: T | undefined; /** Subscribe to changes; immediate invocation with current value (may be undefined). */ subscribe(callback: Subscriber): Unsubscribe; /** Dispose computed value and stop tracking dependencies. */ dispose(): void; } /** * Create a computed value that automatically re-evaluates when accessed reactive state keys change. * Uses effect() internally for dependency tracking. * * @param fn - Pure function that derives a value from reactive state. * @returns Computed value container with .value, .subscribe(), and .dispose() * @throws {Error} If fn is not a function * * @example * ```typescript * import { state } from 'lume-js'; * import { computed } from 'lume-js/addons'; * * const store = state({ count: 5 }); * const doubled = computed(() => store.count * 2); * * console.log(doubled.value); // 10 * * store.count = 10; * // After microtask: * console.log(doubled.value); // 20 (auto-updated) * * // Subscribe to changes * const unsub = doubled.subscribe(value => { * console.log('Doubled:', value); * }); * * // Cleanup * doubled.dispose(); * unsub(); * ``` */ export function computed(fn: () => T): Computed; export interface WatchOptions { /** * Whether to call the callback immediately with the current value (default: true). * Set to false to skip the initial call and only react to future changes. */ immediate?: boolean; } /** * Watch a single key on a reactive state object; convenience wrapper around $subscribe. * * By default the callback fires immediately with the current value, then on every change. * Pass `{ immediate: false }` to skip the initial call and only react to future changes. * * @param store - Reactive state object created with state(). * @param key - Property key to observe. * @param callback - Called with new value on change (and immediately unless immediate=false). * @param options - Watch options * @returns Unsubscribe function for cleanup * @throws {Error} If store is not a reactive state object * * @example * ```typescript * import { state } from 'lume-js'; * import { watch } from 'lume-js/addons'; * * const store = state({ count: 0 }); * * // Fires immediately with 0, then on every change * const unwatch = watch(store, 'count', (value) => { * console.log('Count is now:', value); * }); * * // Only fires on future changes (not the initial value) * watch(store, 'count', (value) => { * console.log('Count changed to:', value); * }, { immediate: false }); * * // Cleanup * unwatch(); * ``` */ export function watch( store: ReactiveState, key: K, callback: Subscriber, options?: WatchOptions ): Unsubscribe; /** * Context passed to preservation functions */ export interface PreservationContext { /** Whether this update is a reorder (vs add/remove) */ isReorder?: boolean; } /** * Focus preservation function signature * * @param container - The list container element * @returns Restore function to call after DOM updates, or null if nothing to restore */ export type FocusPreservation = (container: HTMLElement) => (() => void) | null; /** * Scroll preservation function signature * * @param container - The list container element * @param context - Additional context about the update * @returns Restore function to call after DOM updates */ export type ScrollPreservation = (container: HTMLElement, context?: PreservationContext) => () => void; /** * Context passed to update callback */ export interface UpdateContext { /** True on initial render, false on subsequent updates */ isFirstRender: boolean; } /** * Options for the repeat() function */ export interface RepeatOptions { /** Function to extract unique key from item */ key: (item: T) => string | number; /** * Function to render/update an item's element (called for all items on every update) * Use for simple cases. For complex cases, prefer create + update pattern. */ render?: (item: T, element: HTMLElement, index: number) => void; /** * Function called ONCE when element is created (for DOM structure setup) * Recommended for event listeners and innerHTML setup. * May return a cleanup function — it is called automatically when the * element is removed (by list update or full cleanup). */ create?: (item: T, element: HTMLElement, index: number) => void | (() => void); /** * Function called on every update for data binding * Skipped if same item reference AND same index (optimization) */ update?: (item: T, element: HTMLElement, index: number, context: UpdateContext) => void; /** * Additional cleanup when an element is removed. Called after any cleanup * function returned by create(). Prefer returning a cleanup from create() * for automatic lifecycle management. */ remove?: (item: T, element: HTMLElement) => void; /** * Declarative item structure from a standard