/**
 * RealtimeText — a compact RGA-style sequence CRDT for collaborative text.
 *
 * Each character is a node with a globally-unique id (`<lamport>@<peerId>`) and
 * an `after` pointer to the node it follows. Concurrent inserts sharing an
 * anchor are ordered deterministically (higher lamport first, peer id as
 * tiebreak), so all replicas converge regardless of delivery order. Deletes are
 * tombstones, making them idempotent and commutative.
 *
 * This is intentionally minimal — enough for a genuine multiplayer editor demo
 * without the weight of a full production CRDT (no block compaction, GC, or
 * rich formatting).
 */
import type { RealtimeRoom } from './room.js';
export interface TextNode {
    id: string;
    ch: string;
    after: string | null;
    deleted: boolean;
}
export type TextOp = {
    op: 'ins';
    id: string;
    ch: string;
    after: string | null;
} | {
    op: 'del';
    id: string;
};
export interface RealtimeTextOptions {
    peerId: string;
    /** Optional room binding for automatic op + state sync. */
    room?: RealtimeRoom;
    /** Broadcast channel name when bound to a room. Default `text`. */
    channel?: string;
}
export declare class RealtimeText {
    private nodes;
    private counter;
    private peerId;
    private listeners;
    private room?;
    private channel;
    private unsubscribe?;
    constructor(opts: RealtimeTextOptions);
    /** Materialized visible text. */
    toString(): string;
    /** Current length of visible text. */
    get length(): number;
    /** Insert a string at a visible index. Broadcasts ops when room-bound. */
    insert(index: number, str: string): TextOp[];
    /** Delete `count` visible characters starting at `index`. */
    delete(index: number, count?: number): TextOp[];
    /** Apply a single remote op. Returns true if the document changed. */
    applyOp(op: TextOp): boolean;
    /** Apply a batch of remote ops, emitting once. */
    applyOps(ops: TextOp[]): void;
    /** Snapshot of all nodes (including tombstones) for state sync. */
    getNodes(): TextNode[];
    /** Merge a remote snapshot of nodes. */
    mergeNodes(nodes: TextNode[]): void;
    /** Subscribe to text changes. Returns an unsubscribe fn. */
    onChange(cb: (text: string) => void): () => void;
    /** Detach room bindings. */
    dispose(): void;
    private onRemote;
    private publish;
    private visibleNodes;
    private nextId;
    private bumpCounter;
    private emit;
}
//# sourceMappingURL=text.d.ts.map