/** * @license * Copyright 2022-2026 Matter.js Authors * SPDX-License-Identifier: Apache-2.0 */ import { Duration } from "#time/Duration.js"; import "../polyfills/disposable.js"; import { MaybePromise } from "./Promises.js"; /** * A callback function for observables. * * The observer return value effects how an {@link Observable} emits: * * - If an observer returns undefined the {@link Observable} invokes the next observer immediately. * * - If an observer returns a {@link Promise}, the {@link Observable} awaits the return value then continues as * described here. The emitter must then await the {@link Promise} returned by {@link Observable.emit}. * * - Any other return value is returned by {@link Observable.emit} and subsequent observers do not see emission. * * @param payload a list of arguments to be emitted */ export interface Observer { (...payload: T): R | undefined; [observant]?: boolean; } export interface AsyncObserver extends Observer> { } /** * A discrete event that may be monitored via callback. Could call it "event" but that could be confused with Matter * cluster events and/or DOM events. * * @param T arguments, should be a named tuple */ export interface Observable extends AsyncIterable, PromiseLike { /** * Notify observers. */ emit(...args: T): R | undefined; /** * Add an observer. */ on(observer: Observer): void; /** * Add an observer that may be released via disposal. */ use(observer: Observer): Disposable; /** * Add a "once" observer that may be released via disposal. */ useOnce(observer: Observer): Disposable; /** * Remove an observer. */ off(observer: Observer): void; /** * Add an observer that emits once then is unregistered. */ once(observer: Observer): void; /** * True if there is at least one observer registered. */ isObserved: boolean; /** * Determine whether an observer is registered. */ isObservedBy(observer: Observer): boolean; /** * Errors throw by observers will interrupt emitters unless an error handler is installed here and the handler does * not rethrow. * * The only exception to this is if {@link handlePromise} is false and an observer is asynchronous. In this case * the emitter cannot be made aware of the exception. */ handleError: ObserverErrorHandler; /** * We allow emitters to be async, but we do not want to overburden either the emitter or the observer with promise * tracking if the lifetime of the observer is not relevant to the emitter. * * To facilitate this we allow observables to be configured in one of three promise handling modes: * * * If you set handlePromise, isAsync is true; the handler is invoked for any observer promise * * * If isAsync is true but you do not set handlePromise, any observer promise is returned to the emitter which must * handle the promise * * * If isAsync is false, we log observer promise errors but the promise is otherwise untracked * * If the promiseHandler returns a promise or is true and the emitter returns a promise, the observable will emit to * successive observers only after the promise resolves. */ isAsync: boolean; /** * A promise handler. * * If you set {@link isAsync} (either true or false) the promise handler is set by the Observable. */ handlePromise: ObserverPromiseHandler | boolean; /** * Creates a promise that resolves when next emitted. */ then(onfulfilled?: ((value: T[0]) => TResult1 | PromiseLike) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null): Promise; /** * A diagnostic aid; set this to produce detailed logs of emission. */ traceAs: string | undefined; /** * Observable supports standard "for await (const value of observable"). * * Using an observer in this manner limits your listener to the first parameter normally emitted and your observer * cannot return a value. */ [Symbol.asyncIterator](): AsyncIterator; /** * Release resources associated with the observable. */ [Symbol.dispose](): void; } /** * An observable value. * * This is a stateful observable that remembers its last emitted value and maps to standard Promise semantics. * * Unlike a normal {@link Observable}, awaiting an {@link ObservableValue} will result in immediate resolution if the * value is truthy, and immediately upon updating to a truthy value otherwise. * * Also unlike a normal {@link Observable}, an {@link ObservableValue} may be placed into an error state which will * result in rejection if awaited. */ export interface ObservableValue = void> extends Observable, Promise { /** * The current value. * * Setting the value will resolve the promise interface but you must use {@link emit} to also emit an event. */ value: T[0] | undefined; error?: Error; /** * Place the observable into an error state. * * The error is cleared on next emit. */ reject(cause: unknown): void; then(onfulfilled?: ((value: T[0]) => TResult1 | PromiseLike) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null): Promise; catch(onrejected?: ((reason: any) => TResult | PromiseLike) | null): Promise; onError(handler: (cause: Error) => void): void; offError(handler: (cause: Error) => void): void; useError(handler: (cause: Error) => void): Disposable; } /** * An observer may designate itself as "not observant" for the purposes of {@link Observable.isObserved} by returning * false from this field. */ export declare const observant: unique symbol; /** * An {@link Observable} that explicitly supports asynchronous observers. */ export interface AsyncObservable extends Observable> { } /** * An {@link ObservableValue} that explicitly supports asynchronous observers. */ export interface AsyncObservableValue extends ObservableValue { } export type ObserverErrorHandler = (error: Error, observer: Observer) => void; export type ObserverPromiseHandler = (promise: Promise, observer: Observer) => unknown; /** * A concrete {@link Observable} implementation. */ export declare class BasicObservable implements Observable { #private; constructor(handleError?: ObserverErrorHandler, asyncConfig?: ObserverPromiseHandler | boolean); set traceAs(name: string | undefined); [Symbol.dispose](): void; set handleError(handleError: ObserverErrorHandler); get handleError(): ObserverErrorHandler; set isAsync(isAsync: boolean); get isAsync(): boolean; set handlePromise(handlePromise: ObserverPromiseHandler); get handlePromise(): ObserverPromiseHandler; get isObserved(): boolean; isObservedBy(observer: Observer): boolean; emit(...payload: T): R | undefined; on(observer: Observer): void; use(observer: Observer): { [Symbol.dispose]: () => void; }; useOnce(observer: Observer): { [Symbol.dispose]: () => void; }; off(observer: Observer): void; once(observer: Observer): void; then(onfulfilled?: ((value: T[0]) => TResult1 | PromiseLike) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null): Promise; [Symbol.asyncIterator](): AsyncIterator; detachObservers(): DetachedObservers | undefined; attachObservers(detached: DetachedObservers): void; } /** * Create an {@link Observable}. */ export declare const Observable: { new (errorHandler?: ObserverErrorHandler): Observable; (errorHandler?: ObserverErrorHandler): Observable; }; /** * Create an {@link AsyncObservable} that explicitly supports asynchronous results */ export declare const AsyncObservable: { new (handleError?: ObserverErrorHandler): AsyncObservable; (handleError?: ObserverErrorHandler): AsyncObservable; }; /** * A concrete {@link ObservableValue} implementation. */ export declare class BasicObservableValue = void> extends BasicObservable implements ObservableValue { #private; constructor(value?: T[0], handleError?: ObserverErrorHandler, asyncConfig?: ObserverPromiseHandler | boolean); get value(): T[0] | undefined; set value(value: T[0] | undefined); get error(): Error | undefined; reject(cause: unknown): void; then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null): Promise; catch(onrejected?: ((reason: any) => TResult | PromiseLike) | null): Promise; onError(handler: (cause: Error) => void): void; offError(handler: (cause: Error) => void): void; useError(handler: (cause: Error) => void): { [Symbol.dispose]: () => void; }; finally(onfinally?: (() => void) | null): Promise; [Symbol.toStringTag]: string; } /** * Create an {@link ObservableValue}. */ export declare const ObservableValue: { new (value?: T[0], errorHandler?: ObserverErrorHandler): ObservableValue; (value?: T[0], errorHandler?: ObserverErrorHandler): ObservableValue; }; /** * Create an {@link AsyncObservableValue}. */ export declare const AsyncObservableValue: { new (value?: T[0], errorHandler?: ObserverErrorHandler): AsyncObservableValue; (value?: T[0], errorHandler?: ObserverErrorHandler): AsyncObservableValue; }; /** * A set of observables. You can bind events using individual observables or the methods emulating a subset Node's * EventEmitter. * * To maintain type safety, implementers define events as observable child properties. */ export declare class EventEmitter { private events?; emit>(this: This, name: N, ...payload: EventEmitter.PayloadOf): void; addListener>(this: This, name: N, handler: EventEmitter.ObserverOf): void; removeListener>(this: This, name: N, handler: EventEmitter.ObserverOf): void; addEvent(name: string, event?: AsyncObservable): void; getEvent(name: string): AsyncObservable; hasEvent(name: string, onlyIfInitialized?: boolean): boolean | AsyncObservable | undefined; get eventNames(): string[]; [Symbol.dispose](): void; } export declare namespace EventEmitter { /** * Legal event names. If there are no events defined, assume this is an * untyped instance and allow any argument. */ type NamesOf = [EventNames] extends [never] ? string : EventNames; type EventNames = string & keyof { [K in keyof This as This[K] extends Observable ? K : never]: true; }; /** * Arguments for an event. If there are no events defined, assume this is * an untyped emitter and allow any argument. */ type PayloadOf = [EventPayload] extends [never] ? any[] : EventPayload; type EventPayload = This extends { [K in E]: Observable; } ? T : never; type ObserverOf = Observable>; } /** * An {@link Observable} that proxies to another {@link Observable}. * * Events emitted here instead emit on the target {@link Observable}. Events emitted on the target emit locally via * a listener installed by the proxy. * * This is useful for managing a subset of {@link Observer}s for an {@link Observable}. * * Note that this "proxy" acts as a proxy but is not a JS {@link Proxy}. */ export declare class ObservableProxy extends BasicObservable { #private; constructor(target: Observable); [Symbol.dispose](): void; get isObserved(): boolean; emit: (...payload: any) => any | undefined; protected get target(): Observable; } /** * A collection of observers managed as a unit. This makes it convenient to deregister multiple observers when an * object closes. */ export declare class ObserverGroup { #private; constructor(target?: {}); on(observable: Observable, observer: Observer>, NoInfer>, target?: {}): void; on(observable: AsyncObservable, observer: AsyncObserver>, NoInfer>, target?: {}): void; /** * Remove a single observer. * * @param observable the observable to observe * @param observer the observer function * @param target if the observer was bound in {@link on} this must match the bound target */ off(observable: Observable | AsyncObservable, observer: Observer>, target?: {} | undefined): void; /** * Checks if there are any observers currently subscribed to the given observable. * * @param observable the observable to observe */ observes(observable: Observable | AsyncObservable): number | boolean; /** * Checks if the given observer is subscribed to the given observable. * * @param observable the observable to observe * @param observer the observer function */ has(observable: Observable | AsyncObservable, observer: Observer): boolean; /** * Remove all observers. The instance can be reused afterward to add new observers. */ close(): void; [Symbol.dispose](): void; } /** * {@link Observer}s detached from an {@link Observable}. */ export interface DetachedObservers { observers?: Set>; once?: Set>; } export declare namespace ObserverGroup { /** * This is a workaround for a TS bug, without this the observer must provide a full argument set even if it does not * use all arguments. */ type VarArgs = T extends [...infer R, infer A] ? [...R, A] : T extends [infer A] ? A : []; } /** * An {@link Observable} that emits an algorithmically-reduced number of events. */ export declare class QuietObservable = void> extends BasicObservable implements QuietObservable.State { #private; constructor(config?: QuietObservable.Configuration); get config(): QuietObservable.Configuration; set config(config: QuietObservable.Configuration); get emitAutomatically(): boolean; set emitAutomatically(value: boolean); get suppressionEnabled(): boolean; set suppressionEnabled(value: boolean); get minimumEmitInterval(): Duration; set minimumEmitInterval(value: Duration); get source(): Observable | undefined; set source(source: Observable | undefined); get sink(): Observable | undefined; set sink(sink: Observable | undefined); get shouldEmit(): QuietObservable.EmitPredicate | undefined; set shouldEmit(shouldEmit: QuietObservable.EmitPredicate | undefined); get isObserved(): boolean; isObservedBy(observer: Observer): boolean; emit(...payload: T): R | undefined; /** * Emit immediately, regardless of suppression configuration. */ emitNow(): void; /** * Emit as soon as allowed by suppression. */ emitSoon(): void; [Symbol.dispose](): void; } export declare namespace QuietObservable { interface State = void> { /** * If true this observable will emit within the suppression constraints. If false it will only emit after calls * to {@link emitSoon} or {@link emitNow}. */ emitAutomatically: boolean; /** * If true then emit rate is constrained. If false emits will occur immediately. */ suppressionEnabled: boolean; /** * The minimum time between emits in milliseconds. */ minimumEmitInterval: Duration; /** * An input observable this observable will automatically observe to produce events. */ source?: Observable; /** * An output observable this observable will automatically emit to whenever it emits. */ sink?: Observable; /** * A predicate that determine whether a payload should emit. */ shouldEmit?: EmitPredicate; /** * Handler for errors returned by observers. */ handleError?: ObserverErrorHandler; /** * Designates async support (overridden if you supply {@link handlePromise}). */ isAsync?: boolean; /** * Handler for promises returned by observers. */ handlePromise?: ObserverPromiseHandler; /** * If true, skips emission when rate limited rather than delaying. */ skipSuppressedEmits?: boolean; } /** * An emit predicate may emit this value to force immediate emit. */ const now = "now"; /** * The return value of an emit predicate. "true" allows the event to emit as normal, "false" prevents the event * from emitting, and {@link now} forces immediate emit regardless of interval configuration. */ type EmitDirective = true | false | typeof now; /** * A predicate that may filter emits manually. */ interface EmitPredicate { (...payload: T): EmitDirective; } interface Configuration = void> extends Partial> { } const defaults: State; } //# sourceMappingURL=Observable.d.ts.map