/**
 * @fileoverview Derived from @josephg's implementation here: https://github.com/josephg/jumprope
 *
 * MIT license etc etc
 *
 * Version that doesn't break reactivity.
 */
export type RopeLookup<K, T> = {
    data: T;
    length: number;
    /**
     * The ID of this lookup.
     * This will be the same as what was passed in to perform the lookup.
     */
    id: K;
    /**
     * The previous ID in sequence.
     */
    prevId: K;
    /**
     * The next ID in sequence.
     * This will be the zero ID if there is no following data.
     */
    nextId: K;
};
export type RopeRead<T> = {
    out: T[];
    len: number[];
};
/**
 * Implements a skip list with `O(logn)-ish` performance.
 *
 * We store data here, but mostly only as a convenience: it's a simple k/v map.
 * The length is far more important.
 *
 * Individual parts can have zero length.
 */
export declare class Rope<K, T = void> {
    private _length;
    private head;
    private tail;
    private readonly _zeroId;
    private readonly byId;
    private readonly dataById;
    private readonly nodeCache;
    /**
     * The zero ID that this {@link Rope} was created with.
     */
    zeroId(): K;
    /**
     * Clones this {@link Rope} using {@link structuredClone}.
     */
    clone(): Rope<K, T>;
    /**
     * Constructs a new {@link Rope}.
     *
     * The second argument may be passed purely as a TypeScript hint for {@link T} and it is stored on the root node, but it is not required and cannot ever be read.
     */
    constructor(zeroId: K, sampleData?: T);
    /**
     * The total length of all items in this {@link Rope}.
     */
    length(): number;
    /**
     * The ID of the right-most entry here.
     */
    last(): K;
    /**
     * The count of items in this {@link Rope}, even zero-length ones.
     */
    count(): number;
    /**
     * Find the length between these two valid IDs.
     *
     * This isn't a substitute for {@link compare} as zero length entries are allowed, so this won't return which one is first.
     *
     * Currently just calls {@link find} twice, so `O(logn)-ish`.
     */
    lengthBetween(low: K, high: K): number;
    /**
     * Prints out the rope for debugging.
     */
    _debug(): void;
    [Symbol.iterator](): Iterator<T, void, void>;
    /**
     * Finds the position after the given ID.
     *
     * Perf: `O(logn)-ish`.
     */
    find(ropeId: K): number;
    /**
     * Does this ID exist here.
     *
     * Perf: `O(1)-ish` (just {@link Map}).
     */
    has(ropeId: K): boolean;
    /**
     * Lookup information on this ID.
     *
     * This throws when trying to look up the zero ID.
     *
     * Perf: `O(1)-ish` (just {@link Map}).
     */
    lookup(ropeId: K): RopeLookup<K, T>;
    /**
     * Find the ID for the given position, and the offset from the end of that ID.
     * Always returns a valid value, is clamped to edge.
     *
     * By default, this will be the left-most ID that contains the position (even 'at end').
     * For example, looking up `offset=0` in an already-used rope will always yield `id=0`, as it has zero length.
     *
     * Specify the `biasEnd` parameter to flip this behavior.
     *
     * Perf: `O(logn)-ish`.
     */
    byPosition(position: number, biasAfter?: boolean): {
        id: K;
        offset: number;
    };
    /**
     * Reduced version of `rseek` for various purposes...
     */
    private rseekNodes;
    /**
     * Adjust the given entry's data/length.
     */
    adjust(id: K, data: T, length: number): void;
    /**
     * Inserts a node after a previous node.
     *
     * Perf: `O(logn)-ish`.
     */
    insertAfter(afterId: K, newId: K, length: number, data: T): void;
    /**
     * Deletes the given ID from this rope.
     *
     * Perf: `O(logn)-ish`.
     */
    deleteById(id: K): void;
    /**
     * Deletes after the given ID until the target ID.
     *
     * Perf: `O(logn)-ish`.
     */
    deleteTo(afterId: K, untilId: K): void;
    private insertIntoPool;
    /**
     * Is the ID in `a` before the ID in `b`?
     *
     * Perf: `O(logn)-ish`.
     */
    before(a: K, b: K): boolean;
    /**
     * Compares the position of these two IDs.
     *
     * Returns -1 if A is before B, zero if they are the same, and +1 if A is after B.
     *
     * Perf: `O(logn)-ish`.
     */
    compare(a: K, b: K): number;
    /**
     * Iterate from after the given ID, to the target ID inclusive (i.e., `(afterId,untilId]`).
     *
     * If no `untilId` is passed or the IDs are in the wrong order, iterates from after `afterId` until the end of this {@link Rope}.
     */
    iter(afterId?: K, untilId?: K): Iterable<{
        id: K;
        data: T;
        length: number;
    }, void, void>;
    /**
     * Reads all data from after the given ID, to the target ID inclusive.
     *
     * This is a convenience over {@link iter} and has the same semantics.
     */
    read(afterId?: K, untilId?: K): RopeRead<T>;
}
