import {Slice} from "./parts/slice.js" import {deep} from "../tools/deep/deep.js" import {SliceAccessors, Sliceable} from "./parts/types.js" export class StateTree implements Sliceable { #state: S #readable: S #onChange: () => void #circularity_lock = false #make_frozen_clone() { return deep.freeze(structuredClone(this.#state)) } constructor(state: S, onChange = () => {}) { this.#state = structuredClone(state) this.#readable = this.#make_frozen_clone() this.#onChange = onChange } get state() { return this.#readable } transmute(fun: (state: S) => S) { if (this.#circularity_lock) throw new Error("circular error") this.#circularity_lock = true this.#state = fun(structuredClone(this.#state)) this.#readable = this.#make_frozen_clone() this.#onChange() this.#circularity_lock = false } slice({getter, setter}: SliceAccessors) { return new Slice({ parent: this as Sliceable, getter, setter, }) } }