// A Cubit (from the BLoC pattern): one immutable state object, replaced by emit(). // Views subscribe and render whatever state they are handed; they never mutate it. export class Cubit extends EventTarget { #state; constructor(state) { super(); this.#state = Object.freeze(state); } get state() { return this.#state; } // Shallow-merges patch into a new frozen state and notifies subscribers with (state, previous). emit(patch) { const previous = this.#state; this.#state = Object.freeze({ ...previous, ...patch }); this.dispatchEvent(new CustomEvent("change", { detail: { state: this.#state, previous } })); } // Calls fn(state, previous) now and on every change; returns an unsubscribe function. subscribe(fn) { const listener = (event) => fn(event.detail.state, event.detail.previous); this.addEventListener("change", listener); fn(this.#state, undefined); return () => this.removeEventListener("change", listener); } }