export { deltaRDT } from "./rdt/delta.js";
/**
 * @template T
 * @typedef {import('../schema.js').Schema<T>} Schema
 */
/**
 * Abstract interface for a delta-based Replicated Data Type.
 *
 * An RDT is an observable that emits a `'delta'` (and, on teardown, a `'destroy'`) event, exposes the
 * {@link Schema schema} of the deltas it produces via `$delta` (so a {@link Binding} can initialize a
 * transformer for it), exposes its current state as a delta via the `delta` getter, and accepts foreign
 * deltas via `applyDelta`.
 *
 * `applyDelta(d, origin)` applies `d` and then, if the change would violate the RDT's own invariants,
 * applies a **fix** of its own (e.g. reversing part of `d`, or inserting missing content) and returns
 * that fix — `null` when none was needed. The fix is a regular change on this RDT, so a {@link Binding}
 * maps it onto the other side just like any other change. `applyDelta` also emits the *effective* change
 * (`d` together with the fix) on the `'delta'` channel.
 *
 * ## Origins
 *
 * Every `'delta'` event carries a second argument, `origin` — an opaque `any` value (modelled after
 * {@link https://docs.yjs.dev/api/transactions Yjs transaction origins}) that identifies **where the
 * change came from**. Whoever produces the change sets it, and it is usually the producing instance
 * itself: a communication provider, an editor binding, or the {@link Binding} that mapped the change
 * over from the other side. A change an RDT observes locally (e.g. a `MutationObserver` firing on a DOM
 * edit) uses that RDT itself as the origin.
 *
 * Origins let a listener tell **its own** changes apart from foreign ones so it can skip the ones it
 * already knows about — a change it produced is not looped back to where it came from. The canonical use
 * is a network provider: it tags every remote update it applies with itself (`rdt.applyDelta(update,
 * this)`) and then ignores `'delta'` events whose `origin === this`, so it never re-broadcasts an update
 * it just received. The `origin` argument to `applyDelta` is optional and defaults to `null` (an
 * anonymous/local change); the emitted event always carries whatever value was supplied.
 *
 * A {@link Binding} distinguishes the two kinds of changes it produces. An ordinary change mapped
 * over from the other side carries the binding itself as its origin. A change that adjusts a side's
 * own earlier change after the fact — a fix returned by the opposite RDT transformed back, or a
 * transformer self-heal — carries {@link correctionOrigin}, so a consumer that applied a delta can recognise
 * that (part of) its change was reverted or amended.
 *
 * ## `Delta` vs `DeltaBuilder`
 *
 * The interface is parameterized by a {@link import('./delta.js').DeltaConf DeltaConf} (like a
 * {@link import('./transformer.js').Transformer transformer}). Almost everything it exposes is the
 * *read* form — {@link import('./delta.js').Delta Delta} — because those values are **shared** and must
 * not be mutated in place: `$delta` is the delta schema, the `delta` getter returns a state snapshot,
 * `applyDelta` reads a change into the RDT, and the `'delta'` event payload is broadcast to every
 * listener. The one *owned, mutable* form — {@link import('./delta.js').DeltaBuilder DeltaBuilder} — is
 * the fix `applyDelta` returns to the {@link Binding}. The binding never mutates a shared read delta: it
 * {@link import('./delta.js').cloneDeep deep-clones} every change into a private builder before the
 * transformer rebases it (transformers manipulate deltas in place — see {@link Binding}).
 *
 * @template {import('./delta.js').DeltaConf} Conf
 * @typedef {import('../observable.js').ObservableV2<{ delta: (delta: delta.Delta<Conf>, origin: any) => void, destroy: (rdt: RDT<Conf>) => void }> & {
 *   $delta: Schema<delta.Delta<Conf>>,
 *   delta: delta.Delta<Conf>,
 *   applyDelta: (delta: delta.Delta<Conf>, origin?: any) => delta.DeltaBuilder<Conf> | null,
 *   destroy: () => void
 * }} RDT
 */
/**
 * Schema guard for any {@link RDT}. RDTs are **duck-typed** — they have several independent
 * implementations (`deltaRDT`, `domRDT`, …) and no common constructor — so this matches by shape
 * rather than by `instanceof`: an object exposing a `$delta` {@link Schema}, an `applyDelta` method,
 * and the observable `on`/`destroy` channel. The (possibly expensive) `delta` getter is not invoked.
 *
 * @type {Schema<RDT<any>>}
 */
export const $rdt: Schema<RDT<any>>;
/**
 * The {@link RDT origin} carried by every change a {@link Binding} applies as an after-the-fact
 * adjustment to a side's own change: a fix returned by the opposite RDT's `applyDelta` transformed back
 * onto the side that produced the original change, a transformer self-heal (including during the
 * initial-state sync), and every later round of the fix-convergence loop (fixes of fixes). A "fix"
 * covers invariant corrections as well as rebased concurrent edits (see `./rdt/dom.js`). An ordinary
 * mapped change carries the binding itself instead — see the "Origins" section of {@link RDT}. The
 * value is a plain string, so `origin === 'correction'` works without importing this constant.
 *
 * @type {'correction'}
 */
export const correctionOrigin: "correction";
/**
 * @typedef {object} BindOptions
 * @property {delta.DiffOptions['compare']} [diffCompare] **Experimental** (may be changed or removed
 * in a future release). Forwarded as `compare` to {@link delta.diff} when the initial-state sync diffs
 * `a`'s projection against `b`'s current state, controlling how nodes are paired into `modify` ops.
 */
/**
 * Connects two RDTs so that changes on either side are transformed and reflected on the other.
 *
 * The {@link dt.Transformer transformer} it drives **manipulates deltas in place** (it splices op lists
 * and rebases nodes directly, rather than only via `apply`/`rebase`) — a deliberate exception to the
 * general rule that deltas are edited through `apply`/`rebase`. Consequently every change handed to it
 * must be a privately-owned, fully-mutable delta, so the binding {@link delta.cloneDeep deep-clones}
 * each incoming change (which is a shared read delta — an event payload or a snapshot) before the
 * transformer touches it. See the initial-state sync below and {@link propagate}.
 *
 * @template {delta.DeltaConf} A
 * @template {delta.DeltaConf} B
 */
export class Binding<A extends delta.DeltaConf, B extends delta.DeltaConf> {
    /**
     * @param {RDT<A>} a
     * @param {RDT<B>} b
     * @param {dt.TemplateFactory<A,B>} [template] a `$d => Template` factory; defaults to the
     * {@link dt.id identity} transformer. `bind` injects `a`'s schema, then materializes via `.init()`.
     * @param {BindOptions} [options]
     */
    constructor(a: RDT<A>, b: RDT<B>, template?: dt.TemplateFactory<A, B>, options?: BindOptions);
    /**
     * @type {dt.Transformer<A,B>}
     */
    t: dt.Transformer<A, B>;
    /**
     * @type {RDT<A>}
     */
    a: RDT<A>;
    /**
     * @type {RDT<B>}
     */
    b: RDT<B>;
    _mux: mux.mutex;
    _achanged: (delta: delta.Delta<A>, origin: any) => void;
    _bchanged: (delta: delta.Delta<B>, origin: any) => void;
    /**
     * Tear the binding down: unsubscribe both sides' `'delta'` and `'destroy'` listeners so changes are no
     * longer propagated. Call this when you no longer need the two RDTs kept in sync. It is also invoked
     * automatically when either bound RDT emits `'destroy'`. The RDTs themselves are NOT destroyed.
     */
    destroy: () => void;
}
export function bind<A extends delta.DeltaConf, B extends delta.DeltaConf>(a: RDT<A>, b: RDT<B>, template?: dt.TemplateFactory<A, B>, options?: BindOptions): Binding<A, B>;
export type Schema<T> = import("../schema.js").Schema<T>;
/**
 * Abstract interface for a delta-based Replicated Data Type.
 *
 * An RDT is an observable that emits a `'delta'` (and, on teardown, a `'destroy'`) event, exposes the
 * {@link Schema schema} of the deltas it produces via `$delta` (so a {@link Binding} can initialize a
 * transformer for it), exposes its current state as a delta via the `delta` getter, and accepts foreign
 * deltas via `applyDelta`.
 *
 * `applyDelta(d, origin)` applies `d` and then, if the change would violate the RDT's own invariants,
 * applies a **fix** of its own (e.g. reversing part of `d`, or inserting missing content) and returns
 * that fix — `null` when none was needed. The fix is a regular change on this RDT, so a {@link Binding}
 * maps it onto the other side just like any other change. `applyDelta` also emits the *effective* change
 * (`d` together with the fix) on the `'delta'` channel.
 *
 * ## Origins
 *
 * Every `'delta'` event carries a second argument, `origin` — an opaque `any` value (modelled after
 * {@link https://docs.yjs.dev/api/transactions Yjs transaction origins}) that identifies **where the
 * change came from**. Whoever produces the change sets it, and it is usually the producing instance
 * itself: a communication provider, an editor binding, or the {@link Binding} that mapped the change
 * over from the other side. A change an RDT observes locally (e.g. a `MutationObserver` firing on a DOM
 * edit) uses that RDT itself as the origin.
 *
 * Origins let a listener tell **its own** changes apart from foreign ones so it can skip the ones it
 * already knows about — a change it produced is not looped back to where it came from. The canonical use
 * is a network provider: it tags every remote update it applies with itself (`rdt.applyDelta(update,
 * this)`) and then ignores `'delta'` events whose `origin === this`, so it never re-broadcasts an update
 * it just received. The `origin` argument to `applyDelta` is optional and defaults to `null` (an
 * anonymous/local change); the emitted event always carries whatever value was supplied.
 *
 * A {@link Binding} distinguishes the two kinds of changes it produces. An ordinary change mapped
 * over from the other side carries the binding itself as its origin. A change that adjusts a side's
 * own earlier change after the fact — a fix returned by the opposite RDT transformed back, or a
 * transformer self-heal — carries {@link correctionOrigin}, so a consumer that applied a delta can recognise
 * that (part of) its change was reverted or amended.
 *
 * ## `Delta` vs `DeltaBuilder`
 *
 * The interface is parameterized by a {@link import ('./delta.js').DeltaConf DeltaConf} (like a
 * {@link import ('./transformer.js').Transformer transformer}). Almost everything it exposes is the
 * *read* form — {@link import ('./delta.js').Delta Delta} — because those values are **shared** and must
 * not be mutated in place: `$delta` is the delta schema, the `delta` getter returns a state snapshot,
 * `applyDelta` reads a change into the RDT, and the `'delta'` event payload is broadcast to every
 * listener. The one *owned, mutable* form — {@link import ('./delta.js').DeltaBuilder DeltaBuilder} — is
 * the fix `applyDelta` returns to the {@link Binding}. The binding never mutates a shared read delta: it
 * {@link import ('./delta.js').cloneDeep deep-clones} every change into a private builder before the
 * transformer rebases it (transformers manipulate deltas in place — see {@link Binding}).
 */
export type RDT<Conf extends import("./delta.js").DeltaConf> = import("../observable.js").ObservableV2<{
    delta: (delta: delta.Delta<Conf>, origin: any) => void;
    destroy: (rdt: RDT<Conf>) => void;
}> & {
    $delta: Schema<delta.Delta<Conf>>;
    delta: delta.Delta<Conf>;
    applyDelta: (delta: delta.Delta<Conf>, origin?: any) => delta.DeltaBuilder<Conf> | null;
    destroy: () => void;
};
export type BindOptions = {
    /**
     * **Experimental** (may be changed or removed
     * in a future release). Forwarded as `compare` to {@link delta.diff} when the initial-state sync diffs
     * `a`'s projection against `b`'s current state, controlling how nodes are paired into `modify` ops.
     */
    diffCompare?: delta.DiffOptions["compare"];
};
import * as delta from './delta.js';
import * as dt from './transformer.js';
import * as mux from '../mutex.js';
export { $domDelta, domRDT } from "./rdt/dom.js";
//# sourceMappingURL=rdt.d.ts.map