/** * Represents a single entry in the DOM position index. * * @remarks * Each entry maps a ProseMirror position range to a DOM element that was painted * with data-pm-start and data-pm-end attributes. */ export type DomPositionIndexEntry = { /** The starting ProseMirror position (inclusive) */ pmStart: number; /** The ending ProseMirror position (inclusive) */ pmEnd: number; /** The DOM element representing this position range */ el: HTMLElement; }; /** * Options for controlling how the DOM position index is rebuilt. */ type RebuildOptions = { /** * When true (default), only index "leaf" elements, meaning elements with * `data-pm-start`/`data-pm-end` that do not themselves contain any descendant * elements with PM range attributes. * * This prevents indexing container elements like pages/lines/fragments which * would otherwise overlap with run-level spans and complicate lookups. */ leafOnly?: boolean; }; /** * A lightweight index for mapping ProseMirror positions to painted DOM elements. * * This is rebuilt after each paint and can be used to efficiently locate the * DOM element corresponding to a given PM position, without repeated full-DOM scans. */ export declare class DomPositionIndex { #private; get size(): number; /** * Rebuilds the index by scanning the container for elements with PM position attributes. * * @param container - The root DOM element to scan (typically the painter host) * @param options - Options controlling index behavior * * @remarks * This method performs the following steps: * 1. Queries all elements with both data-pm-start and data-pm-end attributes * 2. Filters out inline SDT wrapper elements (which are metadata containers) * 3. If leafOnly is true (default), filters out container elements that have descendant * PM-position elements, keeping only leaf elements * 4. Validates that pmStart and pmEnd are finite numbers with pmEnd >= pmStart * 5. Sorts entries by pmStart (ascending), then by pmEnd (ascending) * * The leafOnly filtering prevents indexing container elements like pages, lines, and * fragments which would otherwise overlap with run-level spans and complicate lookups. * * The sorting ensures that binary search operations work correctly and that entries * with the same start position are ordered by their end position. * * Safe to call multiple times - each call completely replaces the index. The previous * index is discarded. */ rebuild(container: HTMLElement, options?: RebuildOptions): void; /** * Finds the index entry whose position range contains the given position. * * @param pos - The ProseMirror position to look up * @returns The entry containing this position, or null if none found * * @remarks * Uses binary search (upper bound) to efficiently find the rightmost entry whose * pmStart is less than or equal to pos, then validates that pos is within the * entry's [pmStart, pmEnd] range. * * Time complexity: O(log n) where n is the number of entries. * * Returns null if: * - The position is not a finite number * - The index is empty * - No entry contains the position (position is in a gap between entries) * * For positions that fall exactly on entry boundaries: * - If pos equals entry.pmStart, the entry is returned * - If pos equals entry.pmEnd, the entry is returned * - Due to sorting, if multiple entries could match, the first in sort order is returned */ findEntryAtPosition(pos: number): DomPositionIndexEntry | null; /** * Finds the index entry that either contains the given position, * or is the closest entry before or after it. * @param pos - The ProseMirror position to look up * @returns The closest entry to this position, or null if the index is empty * @remarks * This method first attempts to find an entry that contains the position. * If none is found, it then finds the closest entry before or after the position. * If the index is empty, it returns null. */ findEntryClosestToPosition(pos: number): DomPositionIndexEntry | null; findElementAtPosition(pos: number): HTMLElement | null; /** * Finds all index entries whose position ranges overlap with the given range. * * @param from - The start of the query range (inclusive) * @param to - The end of the query range (exclusive by default, inclusive with `boundaryInclusive`) * @param options - Options controlling boundary behavior * @returns Array of entries that overlap the range, in index order * * @remarks * By default, an entry overlaps the query range [start, end) if: * - entry.pmStart < end (entry starts before query range ends) * - entry.pmEnd > start (entry ends after query range starts) * * When `boundaryInclusive` is true, the overlap condition becomes [start, end]: * - entry.pmStart <= end (entry starts at or before query range ends) * - entry.pmEnd >= start (entry ends at or after query range starts) * * Use `boundaryInclusive: true` for selection overlay rendering where positions at * run boundaries (e.g., between two adjacent text runs with different marks) need to * resolve to adjacent DOM entries. ProseMirror run nodes create a 2-position gap * between adjacent text spans; inclusive boundaries ensure entries touching the gap * are found. * * The algorithm: * 1. Normalizes the range (swaps from/to if necessary) * 2. Uses binary search to find the first potentially overlapping entry * 3. Scans forward, collecting overlapping entries until entries start beyond the range * * Time complexity: O(log n + k) where n is total entries and k is the number of matching entries. * * Returns empty array if: * - Either from or to is not a finite number * - from equals to (zero-length range) * - The index is empty * - No entries overlap the range * * Edge cases: * - Zero-length ranges (from === to) return empty array * - Reversed ranges are automatically normalized (from > to is handled) */ findEntriesInRange(from: number, to: number, options?: { boundaryInclusive?: boolean; }): DomPositionIndexEntry[]; /** * Finds all DOM elements whose position ranges overlap with the given range. * * @param from - The start of the query range (inclusive) * @param to - The end of the query range (exclusive) * @returns Array of DOM elements that overlap the range, in index order * * @remarks * This is a convenience method that calls findEntriesInRange() and extracts the * element references from each entry. * * See findEntriesInRange() for details on the overlap algorithm and edge cases. */ findElementsInRange(from: number, to: number): HTMLElement[]; } export {}; //# sourceMappingURL=DomPositionIndex.d.ts.map