@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
JavaScript
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
};