UNPKG

anystatejs

Version:
67 lines (66 loc) 2.55 kB
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 = []; } }