anystatejs
Version:
javascript state handler
67 lines (66 loc) • 2.55 kB
JavaScript
import { distinctUntilChanged, map, BehaviorSubject } from 'rxjs';
class Action {
}
class ChildSubscription {
}
export class StateManager {
constructor(initialValue) {
this.initialValue = initialValue;
this.state$ = new BehaviorSubject(initialValue);
this.childrenSubscriptions = [];
this.actions = [];
}
get subscribe() { return this.state$.subscribe.bind(this.state$); }
get value() { return this.state$.getValue(); }
set(value) {
this.state$.next(value);
}
reset() {
this.state$.next(this.initialValue);
}
update(partialValue) {
this.state$.next(Object.assign(Object.assign({}, this.value), partialValue));
}
getPropertyObservable(key) {
return this.state$.pipe(map((state) => state[key]), distinctUntilChanged());
}
call(name, ...inputs) {
const action = this.actions.find((action) => action.name === name);
if (!action)
return;
this.update(action.call(this.value, ...inputs));
}
createAction(name, action) {
this.actions = [...this.actions, { name, call: action }];
}
removeAction(name) {
this.actions = this.actions
.filter((action) => action.name !== name);
}
createChild(key) {
const child = new StateManager(this.value[key]);
// update this on child updated
const childSubscription = child.subscribe((value) => {
if (value === this.value[key])
return;
this.update({ [key]: value });
});
this.childrenSubscriptions = [...this.childrenSubscriptions, { property: key, subscription: childSubscription }];
// update child on this updated
const propertySubscription = this.getPropertyObservable(key).subscribe(child.set.bind(child));
this.childrenSubscriptions = [...this.childrenSubscriptions, { property: key, subscription: propertySubscription }];
return child;
}
removeChild(key) {
this.childrenSubscriptions
.filter(({ property }) => property === key)
.forEach(({ subscription }) => subscription.unsubscribe());
this.childrenSubscriptions = this.childrenSubscriptions
.filter(({ property }) => property !== key);
}
removeAllChildren() {
this.childrenSubscriptions
.forEach(({ subscription }) => subscription.unsubscribe());
this.childrenSubscriptions = [];
}
}