type PromiseWithMeta<T> = Promise<T> & {
    status?: "pending" | "fulfilled" | "rejected";
    value?: T;
    reason?: unknown;
};

interface KVEvents<Param, Value, Key = unknown> {
    "state:update": CustomEvent<{
        param: Param;
        key: Key;
        value: Value;
    }>;
    "state:reset": CustomEvent<void>;
}
interface KVDataEventTargetConfig<Param, Key = string> {
    getKey?: (param: Param) => Key;
}
declare class KVDataEventTarget<Param, Value, Key = unknown> extends EventTarget {
    #private;
    lastUpdated: number;
    constructor(initialEntries?: readonly (readonly [Param, Value])[] | null, config?: KVDataEventTargetConfig<Param, Key>);
    /**
     * Read attempts to return the current value synchronously if one exists,
     * but otherwise returns a Promise that will resolve when a value is set.
     */
    read(param: Param): Value | Promise<Value>;
    /**
     * Prime ensures there is a Promise ready to receive a future value.
     * Useful for setting up the Promise before you need the value.
     */
    prime(param: Param): void;
    /**
     * Peek will always synchronously read the value.
     * It will return undefined if no value has been set yet.
     */
    peek(param: Param): Value | undefined;
    /**
     * GetAsync will always return a *stable* Promise that resolves when a value is set.
     */
    getAsync(param: Param): PromiseWithMeta<Value>;
    /**
     * Sets the value, resolving any pending Promises.
     */
    set(param: Param, value: Value): void;
    onMissing(cb: EventListener): void;
    clear(): void;
    destroy(): void;
    addEventListener<K extends keyof KVEvents<Param, Value, Key>>(type: K, listener: (ev: KVEvents<Param, Value, K>[K]) => void, options?: boolean | AddEventListenerOptions): void;
    addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
    removeEventListener<K extends keyof KVEvents<Param, Value, Key>>(type: K, listener: (ev: KVEvents<Param, Value, K>[K]) => void, options?: boolean | EventListenerOptions): void;
    removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}

declare class DataEventTarget<Value> extends EventTarget {
    #private;
    lastUpdated: number;
    constructor(initialValue?: Value);
    /**
     * Read attempts to return the current value synchronously if one exists,
     * but otherwise returns a Promise that will resolve when a value is set.
     */
    read(): Value | PromiseWithMeta<Value>;
    /**
     * Prime ensures there is a Promise ready to receive a future value.
     * Useful for setting up the Promise before you need the value.
     */
    prime(): void;
    /**
     * Peek will always synchronously read the value.
     * It will return undefined if no value has been set yet.
     */
    peek(): Value | undefined;
    /**
     * GetAsync will always return a *stable* Promise that resolves when a value is set.
     */
    getAsync(): PromiseWithMeta<Value>;
    /**
     * Sets the value, resolving any pending Promises.
     */
    set(value: Value): void;
    onMissing(cb: EventListener): void;
    clear(): void;
    destroy(): void;
}

interface BroadcastMessageType {
    type: string;
    namespace: string;
    detail: unknown;
}
declare abstract class Broadcast<MessageType extends BroadcastMessageType> {
    protected controller: AbortController;
    protected signal: AbortSignal;
    abstract onMessage(handler: (event: MessageEvent<MessageType>) => void): void;
    abstract postMessage(message: MessageType, options?: unknown): void;
    detach(): void;
}

declare class WindowBroadcast<MessageType extends BroadcastMessageType> extends Broadcast<MessageType> {
    private receiver;
    private sender;
    constructor(receiver: Window, sender: Window | Window[] | ((message: MessageType) => Window[]));
    onMessage(handler: (event: MessageEvent<MessageType>) => void): void;
    postMessage(message: MessageType, { targetOrigin, transfer }?: WindowPostMessageOptions): void;
}

declare function source<T extends EventTarget & {
    lastUpdated?: number;
}>(toBroadcastTarget: WindowBroadcast<any>, fromSourceTarget: T, namespace: string, config?: {
    id?: string;
    eventsToBroadcast?: string[];
}): T;

type SinkEventTarget = EventTarget & {
    set: (...args: any[]) => void;
    clear: () => void;
    onMissing: (cb: EventListener) => void;
};
type SinkEventHandlers<T extends SinkEventTarget> = {
    [eventType: string]: (target: T, detail: any) => void;
};
declare function sink<T extends SinkEventTarget>(fromBroadcastSource: WindowBroadcast<any>, toSinkTarget: T, namespace: string, eventHandlers?: SinkEventHandlers<T>): T;

export { Broadcast, type BroadcastMessageType, DataEventTarget, KVDataEventTarget, type KVEvents, WindowBroadcast, sink, source };
