import { Focus, PickEquality } from '../types'; import { FocusAutoDispose } from './disposalGroup'; /** * Options for the list helper. */ export interface ListOptions { /** * Auto-dispose items when removed. * * - `false` / `undefined`: No auto-disposal (default) * - `true`: Dispose immediately via microtask * - `number`: Grace period in ms (e.g., `100` = 100ms delay) * - `string`: Named disposal group (shared across collections) * - `DisposalGroup`: Direct group instance * - `{ group, gracePeriodMs }`: Full options * * @example * ```ts * // Simple auto-dispose * list({ autoDispose: true }) * * // With 100ms grace period * list({ autoDispose: 100 }) * * // Named group - items moving between lists with same group name won't be disposed * list({ autoDispose: "todos" }) * * // Named group with grace period * list({ autoDispose: { group: "todos", gracePeriodMs: 100 } }) * * // Direct group instance * const group = disposalGroup(); * list({ autoDispose: group }) * ``` */ autoDispose?: FocusAutoDispose; /** * Called when item(s) are added to the list. */ onAdded?: (item: T, index: number) => void; /** * Called when item(s) are removed from the list. */ onRemoved?: (item: T, index: number) => void; } /** * List API returned by the list() helper. */ export interface FocusList { /** Get the current array (returns empty array if undefined/null) */ get(): T[]; /** Get item at index */ at(index: number): T | undefined; /** Get the length of the array */ length(): number; /** Check if array is empty */ isEmpty(): boolean; /** Get the first item */ first(): T | undefined; /** Get the last item */ last(): T | undefined; /** Push item(s) to the end */ push(...items: T[]): void; /** Add item(s) to the beginning */ unshift(...items: T[]): void; /** Remove and return the last item (auto-disposes if enabled) */ pop(): T | undefined; /** Remove and return the first item (auto-disposes if enabled) */ shift(): T | undefined; /** Remove item(s) by reference (auto-disposes if enabled) */ remove(...items: T[]): number; /** Remove item at index (auto-disposes if enabled) */ removeAt(index: number): T | undefined; /** Remove items matching predicate (auto-disposes if enabled) */ removeWhere(predicate: (item: T, index: number) => boolean): number; /** Insert item at index */ insert(index: number, ...items: T[]): void; /** * Set item at index (auto-disposes old item if enabled). * Accepts direct value, reducer, or immer-style updater. * * @example * items.set(0, newItem); // Direct value * items.set(0, prev => ({ ...prev, done: true })); // Reducer * items.set(0, draft => { draft.done = true }); // Updater (mutates draft) */ set(index: number, itemOrReducerOrUpdater: T | ((prev: T) => T | void)): void; /** * Ensure item exists at index, creating it if necessary. * * @example * const item = items.ensure(5, () => ({ id: 5, name: 'New' })); */ ensure(index: number, create: () => T): T; /** * Swap items at two indices. * * @example * items.swap(0, 2); // Swap first and third items */ swap(indexA: number, indexB: number): void; /** Clear all items (auto-disposes all if enabled) */ clear(): void; /** Replace entire array (auto-disposes old items if enabled) */ replace(items: T[]): void; /** Find item matching predicate */ find(predicate: (item: T, index: number) => boolean): T | undefined; /** Find index of item matching predicate */ findIndex(predicate: (item: T, index: number) => boolean): number; /** Check if item exists */ includes(item: T): boolean; /** Map items (read-only, doesn't mutate) */ map(fn: (item: T, index: number) => U): U[]; /** Filter items (read-only, doesn't mutate) */ filter(predicate: (item: T, index: number) => boolean): T[]; /** Create a pick selector for fine-grained reactivity */ pick(equality?: PickEquality): T[]; } /** * Create a list helper for array focus. * Handles undefined/null arrays gracefully. * * @example * ```ts * const todoStore = store({ * name: 'todos', * state: { items: [] as TodoItem[] }, * setup({ focus }) { * const items = focus('items').as(list()); * return { * addTodo: (text: string) => items.push({ id: Date.now(), text, done: false }), * removeTodo: (todo: TodoItem) => items.remove(todo), * clearDone: () => items.removeWhere(item => item.done), * clearAll: () => items.clear(), * }; * }, * }); * ``` * * @example * ```ts * // With named disposal group for cross-collection moves * const todoStore = store({ * name: 'todos', * state: { * active: [] as TodoItem[], * completed: [] as TodoItem[], * }, * setup({ focus }) { * // Same group name = items moving between won't be disposed * const active = focus('active').as(list({ autoDispose: "todos" })); * const completed = focus('completed').as(list({ autoDispose: "todos" })); * * return { * complete: (todo: TodoItem) => { * active.remove(todo); // Schedules disposal * completed.push(todo); // Cancels disposal - same group! * }, * }; * }, * }); * ``` */ export declare function list(options?: ListOptions): (focus: Focus | Focus | Focus | Focus) => FocusList; export { disposalGroup, getNamedGroup, type DisposalGroup, type FocusAutoDispose, type FocusAutoDisposeOptions, } from './disposalGroup'; //# sourceMappingURL=list.d.ts.map