UNPKG

@thi.ng/atom

Version:

Mutable wrappers for nested immutable values with optional undo/redo history and transaction support

89 lines (88 loc) 2.19 kB
import { defGetterUnsafe } from "@thi.ng/paths/getter"; import { defSetterUnsafe } from "@thi.ng/paths/setter"; import { Atom } from "./atom.js"; import { nextID } from "./idgen.js"; function defCursor(parent, path, opts) { return new Cursor(parent, path, opts); } function defCursorUnsafe(parent, path, opts) { return new Cursor(parent, path, opts); } class Cursor { id; parent; local; selfUpdate; constructor(parent, path, opts = {}) { const validate = opts.validate; const lookup = defGetterUnsafe(path); const update = defSetterUnsafe(path); this.parent = parent; this.id = opts.id || `cursor-${nextID()}`; this.selfUpdate = false; this.local = new Atom(lookup(parent.deref()), validate); this.local.addWatch(this.id, (_, prev, curr) => { if (prev !== curr) { this.selfUpdate = true; parent.swap((state) => update(state, curr)); this.selfUpdate = false; } }); parent.addWatch(this.id, (_, prev, curr) => { if (!this.selfUpdate) { const cval = lookup(curr); if (cval !== lookup(prev)) { this.local.reset(cval); } } }); } get value() { return this.deref(); } set value(val) { this.reset(val); } deref() { return this.local.deref(); } release() { this.local.release(); this.parent.removeWatch(this.id); delete this.local; delete this.parent; return true; } reset(val) { return this.local.reset(val); } resetIn(path, val) { return this.local.resetInUnsafe(path, val); } resetInUnsafe(path, val) { return this.local.resetInUnsafe(path, val); } swap(fn, ...args) { return this.local.swap(fn, ...args); } swapIn(path, fn, ...args) { return this.local.swapInUnsafe(path, fn, ...args); } swapInUnsafe(path, fn, ...args) { return this.local.swapInUnsafe(path, fn, ...args); } addWatch(id, fn) { return this.local.addWatch(id, fn); } removeWatch(id) { return this.local.removeWatch(id); } notifyWatches(oldState, newState) { return this.local.notifyWatches(oldState, newState); } } export { Cursor, defCursor, defCursorUnsafe };