UNPKG

compote-ui

Version:

An opinionated UI component library for Svelte, built on top of [Ark UI](https://ark-ui.com) with additional components and features not available in the core Ark UI library.

57 lines (56 loc) • 2.26 kB
export class DebouncedFilterEdits { // Raw, not deep: `base` must stay the exact filter value it is compared against — a deep // $state would proxy an array base (a range) and `Object.is` would never match it again. #pending = $state.raw({}); // Timer handles are bookkeeping, never rendered — a reactive map would only add overhead. // eslint-disable-next-line svelte/prefer-svelte-reactivity #timers = new Map(); #delay; constructor(delay = 300) { this.#delay = delay; } /** The pending edit for `id`, or undefined when there is none or it went stale. */ get(id, current) { const pending = this.#pending[id]; return pending && Object.is(pending.base, current) ? pending.value : undefined; } /** * Records an edit against the filter's `current` value: `update` receives the live * pending edit (undefined when there is none or it went stale) and returns the new one. * After the delay, `commit` runs with it — unless `read()` shows the filter changed. */ edit(id, current, update, read, commit) { this.#pending = { ...this.#pending, [id]: { value: update(this.get(id, current)), base: current } }; clearTimeout(this.#timers.get(id)); this.#timers.set(id, setTimeout(() => { this.#timers.delete(id); const pending = this.#pending[id]; this.#remove(id); if (pending && Object.is(read(), pending.base)) commit(pending.value); }, this.#delay)); } /** Drops the pending edit for `id` without committing it. */ cancel(id) { clearTimeout(this.#timers.get(id)); this.#timers.delete(id); this.#remove(id); } /** Drops every pending edit without committing. */ cancelAll() { for (const timer of this.#timers.values()) clearTimeout(timer); this.#timers.clear(); this.#pending = {}; } #remove(id) { if (!(id in this.#pending)) return; // eslint-disable-next-line @typescript-eslint/no-unused-vars -- dropped from the record const { [id]: _removed, ...rest } = this.#pending; this.#pending = rest; } }