import { FlowBlock, Layout, Measure, Line } from '../../contracts/src/index.js';
import { Point, FragmentHit, PositionHit } from './position-hit.js';
export type { HeaderFooterType } from '../../contracts/src/index.js';
export { extractIdentifierFromConverter, getHeaderFooterType, defaultHeaderFooterIdentifier, resolveHeaderFooterForPage, buildMultiSectionIdentifier, defaultMultiSectionIdentifier, getHeaderFooterTypeForSection, getHeaderFooterIdForPage, resolveHeaderFooterForPageAndSection, } from './headerFooterUtils';
export type { HeaderFooterIdentifier, MultiSectionHeaderFooterIdentifier, SectionHeaderFooterIds, } from './headerFooterUtils';
export { layoutHeaderFooterWithCache, type HeaderFooterBatchResult, getBucketForPageNumber, getBucketRepresentative, } from './layoutHeaderFooter';
export type { HeaderFooterBatch, DigitBucket } from './layoutHeaderFooter';
export { findWordBoundaries, findParagraphBoundaries } from './text-boundaries';
export type { BoundaryRange } from './text-boundaries';
export { buildSectionAwareHeaderFooterLayoutKey, buildSectionContentWidth, buildEffectiveHeaderFooterRefsBySection, collectReferencedHeaderFooterRIds, buildSectionAwareHeaderFooterMeasurementGroups, } from './sectionAwareHeaderFooter';
export type { HeaderFooterSectionKind, HeaderFooterRefs, SectionAwareHeaderFooterMeasurementGroup, } from './sectionAwareHeaderFooter';
export { incrementalLayout, measureCache, normalizeMargin } from './incrementalLayout';
export type { HeaderFooterLayoutResult, IncrementalLayoutResult } from './incrementalLayout';
export { computeDisplayPageNumber } from '@superdoc/layout-engine';
export type { DisplayPageInfo, HeaderFooterConstraints } from '@superdoc/layout-engine';
export { remeasureParagraph } from './remeasure';
export { measureCharacterX, sliceRunsForLine } from './text-measurement';
export { clickToPositionDom, findPageElement } from './dom-mapping';
export { isListItem, getWordLayoutConfig, calculateTextStartIndent, extractParagraphIndent } from './list-indent-utils';
export type { TextIndentCalculationParams } from './list-indent-utils';
export { LayoutVersionLogger } from './instrumentation';
export { FontMetricsCache } from './font-metrics-cache';
export type { FontMetrics, FontMetricsCacheConfig } from './font-metrics-cache';
export { ParagraphLineCache } from './paragraph-line-cache';
export type { LineInfo, ParagraphLines } from './paragraph-line-cache';
export { CursorRenderer } from './cursor-renderer';
export type { CursorRendererOptions, CursorRect } from './cursor-renderer';
export { LocalParagraphLayout } from './local-paragraph-layout';
export type { LocalLayoutResult, TextRun } from './local-paragraph-layout';
export { PmDomFallback } from './pm-dom-fallback';
export type { PageTransform, PmEditorView } from './pm-dom-fallback';
export { PageGeometryHelper } from './page-geometry-helper';
export type { PageGeometryConfig } from './page-geometry-helper';
export { DirtyTracker } from './dirty-tracker';
export type { DirtyRange } from './dirty-tracker';
export { DebouncedPassManager } from './debounced-passes';
export type { DebouncedPass } from './debounced-passes';
export { PmPositionValidator } from './pm-position-validator';
export type { ValidationResult, ValidationError } from './pm-position-validator';
export { ImeHandler } from './ime-handler';
export type { ImeState } from './ime-handler';
export { TableHandler } from './table-handler';
export type { TableLayoutState } from './table-handler';
export { TrackChangesHandler } from './track-changes-handler';
export type { TrackChangeSpan } from './track-changes-handler';
export { CacheWarmer } from './cache-warmer';
export type { WarmingConfig, ParagraphWarmInfo } from './cache-warmer';
export { PerformanceMetricsCollector, perfMetrics } from './performance-metrics';
export type { MetricSample, MetricSummary, TypingPerfMetrics, BudgetViolation } from './performance-metrics';
export { SafetyNet } from './safety-net';
export type { FallbackReason, SafetyConfig } from './safety-net';
export { FocusWatchdog } from './focus-watchdog';
export type { FocusWatchdogConfig } from './focus-watchdog';
export { hashParagraphBorder, hashParagraphBorders, hashParagraphAttrs, hashBorderSpec, hashTableBorderValue, hashTableBorders, hashCellBorders, hasStringProp, hasNumberProp, hasBooleanProp, getRunStringProp, getRunNumberProp, getRunBooleanProp, } from './paragraph-hash-utils';
export type { Point, PageHit, FragmentHit, PositionHit, TableHitResult, GeometryPageHint, ClickToPositionGeometryOptions, } from './position-hit.js';
export { isAtomicFragment, getAtomicPmRange, isRtlBlock, determineColumn, findLineIndexAtY, mapPointToPm, snapToNearestFragment, hitTestPage, hitTestFragment, hitTestAtomicFragment, hitTestTableFragment, findBlockIndexByFragmentId, calculatePageTopFallback, resolvePositionHitFromDomPosition, clickToPositionGeometry, } from './position-hit.js';
export type Rect = {
    x: number;
    y: number;
    width: number;
    height: number;
    pageIndex: number;
};
/**
 * Compatibility wrapper — delegates to resolvePositionHitFromDomPosition and
 * clickToPositionGeometry from position-hit.ts.
 *
 * Production super-editor callers should use resolvePointerPositionHit (from
 * PositionHitResolver.ts) instead. This wrapper exists so that external
 * consumers and tests that import clickToPosition from @superdoc/layout-bridge
 * continue to work unchanged.
 */
export declare function clickToPosition(layout: Layout, blocks: FlowBlock[], measures: Measure[], containerPoint: Point, domContainer?: HTMLElement, clientX?: number, clientY?: number, geometryHelper?: import('./page-geometry-helper').PageGeometryHelper): PositionHit | null;
/**
 * Given a PM range [from, to), return selection rectangles for highlighting.
 *
 * @param layout - The layout containing page and fragment data
 * @param blocks - Array of flow blocks
 * @param measures - Array of measurements corresponding to blocks
 * @param from - Start PM position
 * @param to - End PM position
 * @param geometryHelper - Optional PageGeometryHelper for accurate Y calculations (recommended)
 * @returns Array of selection rectangles in container space
 */
export declare function selectionToRects(layout: Layout, blocks: FlowBlock[], measures: Measure[], from: number, to: number, geometryHelper?: import('./page-geometry-helper').PageGeometryHelper): Rect[];
export declare function getFragmentAtPosition(layout: Layout, blocks: FlowBlock[], measures: Measure[], pos: number): FragmentHit | null;
export declare function findLinesIntersectingRange(block: FlowBlock, measure: Measure, from: number, to: number): {
    line: Line;
    index: number;
}[];
/**
 * Computes the ProseMirror position range for a line within a paragraph block.
 *
 * This function calculates the start and end PM positions by iterating through all runs
 * that contribute to the line, handling partial runs at line boundaries and accounting
 * for various run types (text, images, breaks, annotations).
 *
 * **Empty Run Handling (SD-1108 Fix):**
 * Unlike `pmPosToCharOffset` which skips empty runs during position-to-character mapping,
 * this function intentionally PRESERVES empty runs to support cursor positioning in
 * zero-width content like empty table cells. Empty runs carry PM position metadata that
 * enables click-to-position mapping even when there's no visible text.
 *
 * **Why the difference?**
 * - `computeLinePmRange`: Used for spatial operations (click mapping, selection highlighting)
 *   where we need to know the PM range of ALL content, including zero-width positions.
 * - `pmPosToCharOffset`: Used for text measurement where only visible characters matter.
 *   Empty runs contribute no pixels and should be skipped during character-based calculations.
 *
 * **Algorithm:**
 * 1. Filter out atomic runs (images, line breaks, field annotations) - they have no text length
 * 2. For each text run in the line:
 *    a. If the run is empty (length 0), preserve its PM positions for cursor support
 *    b. If the run has text, calculate PM positions based on character offsets
 *    c. Handle partial runs (first/last in line) by adjusting offsets
 * 3. Return the accumulated PM range
 *
 * **Edge Cases Handled:**
 * - Empty runs (zero text length but valid PM positions) - PRESERVED for SD-1108
 * - Atomic runs (images, breaks) - skipped, don't contribute to text range
 * - Runs with missing PM data - skipped with warning logged
 * - Runs with invalid PM positions (negative, Infinity, NaN) - logged as warnings
 * - Partial runs at line boundaries - offset calculations applied
 *
 * @param block - The flow block to compute PM range for (must be a paragraph block)
 * @param line - The line specification including run range (fromRun to toRun) and character offsets
 * @returns Object containing pmStart and pmEnd positions, or empty object if block is not a paragraph
 *
 * @example
 * ```typescript
 * // Normal text run
 * const range = computeLinePmRange(paragraphBlock, line);
 * // { pmStart: 10, pmEnd: 25 }
 *
 * // Empty table cell (SD-1108 fix)
 * const emptyRange = computeLinePmRange(emptyParagraphBlock, line);
 * // { pmStart: 15, pmEnd: 15 } - zero-width but valid for cursor positioning
 * ```
 *
 * @see pmPosToCharOffset - Related function that skips empty runs during character offset calculation
 */
export declare function computeLinePmRange(block: FlowBlock, line: Line): {
    pmStart?: number;
    pmEnd?: number;
};
/**
 * Convert a ProseMirror position to a character offset within a line.
 *
 * This function performs ratio-based interpolation to handle cases where the PM position
 * range doesn't match the text length (e.g., when a run has formatting marks or when
 * there are position gaps between runs due to wrapper nodes).
 *
 * Algorithm:
 * 1. Iterate through runs in the line
 * 2. For each run, calculate its PM range and character count
 * 3. If pmPos falls within the run's PM range:
 *    - Use ratio interpolation: (pmPos - runStart) / runPmRange * runCharCount
 *    - This handles cases where PM positions don't align 1:1 with characters
 * 4. Return the accumulated character offset
 *
 * Edge Cases:
 * - Position before line start: Returns 0
 * - Position after line end: Returns total character count of the line
 * - Empty runs (images, breaks): Skipped, don't contribute to character count
 * - Runs with missing PM data: Skipped
 * - Zero-length PM range: Returns current accumulated offset without adding
 *
 * Performance:
 * - Time complexity: O(n) where n is the number of runs in the line
 * - Space complexity: O(1)
 *
 * @param block - The paragraph block containing the line
 * @param line - The line containing the position
 * @param pmPos - The ProseMirror position to convert
 * @returns Character offset from start of line (0-based), or 0 if position not found
 *
 * @example
 * ```typescript
 * // Run with PM range [10, 15] containing "Hello" (5 chars)
 * // pmPos = 12 should map to character offset 2 within the run
 * const offset = pmPosToCharOffset(block, line, 12);
 * // offset = 2 (ratio: (12-10)/(15-10) * 5 = 2/5 * 5 = 2)
 * ```
 */
export declare function pmPosToCharOffset(block: FlowBlock, line: Line, pmPos: number): number;
/**
 * Convert a ProseMirror position to a rendered character offset within a line.
 *
 * Unlike {@link pmPosToCharOffset}, this helper includes visual-only text runs
 * that do not carry PM positions. That matters for selection highlighting when
 * a line starts with rendered chrome such as a synthetic footnote number:
 * the marker consumes horizontal space in the painter, but it is not part of
 * the editable PM story. Using a PM-only offset would place the highlight too
 * far left by the marker's width.
 *
 * The returned offset is intended for visual X mapping, not for slicing PM text.
 */
export declare function pmPosToVisualCharOffset(block: FlowBlock, line: Line, pmPos: number): number;
//# sourceMappingURL=index.d.ts.map