import { FlowBlock, Layout, LayoutBlockRef, LayoutFragmentId, LayoutSourceIdentity, LayoutStoryLocator, Measure, SourceAnchor, LAYOUT_BOUNDARY_SCHEMA } from '../../contracts/src/index.js';
import { ClickToPositionGeometryOptions, PositionHit, Point } from './position-hit.js';
/** Container-space rectangle (mirrors `Rect` from this package's `index.ts`). */
export type LayoutRect = {
    x: number;
    y: number;
    width: number;
    height: number;
    pageIndex: number;
};
/**
 * Layout-side representation of a hit-tested point.
 *
 * Carries everything an editor-neutral consumer needs to address the
 * rendered fragment under a click. Legacy PM fields (`pmPosition`,
 * `layoutEpoch`, `lineIndex`, `column`) are surfaced under `legacyPm` for
 * v1 callers that still need them.
 */
export type LayoutHit = {
    /** Schema version for this hit-test result. */
    schema: typeof LAYOUT_BOUNDARY_SCHEMA;
    /** Layout revision (today: `layout.layoutEpoch`). */
    layoutRevision: number;
    /** Composite editor-neutral identity for the hit fragment. */
    identity: LayoutSourceIdentity;
    /** Story locator for the hit fragment. */
    story: LayoutStoryLocator;
    /** Source block reference (today: producer's `blockId`). */
    blockRef: LayoutBlockRef;
    /** Stable opaque fragment id. */
    fragmentId: LayoutFragmentId;
    /** 0-based page index containing the hit. */
    pageIndex: number;
    /** Optional cross-reference to the DOCX source anchor. */
    sourceAnchor?: SourceAnchor;
    /** Diagnostics for partially supported or rejected hits. */
    diagnostics?: LayoutHitDiagnostic[];
    /**
     * Legacy PM-shaped position hit.
     *
     * AIDEV-NOTE: compat-fallback - v1 callers (PresentationEditor,
     * super-editor selection) still consume `pmPosition`. Retire once the v2
     * provider stops relying on PM positions to map this hit back to a v2
     * ref. Do not gate new editor-neutral behavior on this field.
     */
    legacyPm?: PositionHit;
};
export type LayoutHitDiagnostic = {
    code: 'no-page-hit';
} | {
    code: 'no-fragment-hit';
} | {
    code: 'pm-position-unavailable';
} | {
    code: 'unsupported-fragment-kind';
    fragmentKind: string;
};
/**
 * Subrange of a single fragment, in editor-neutral terms.
 *
 * `inlineFromOpaque` / `inlineToOpaque` are placeholders for the offsets a
 * future neutral text-offset model will carry. They are intentionally
 * optional because the current producer can only describe character offsets
 * via PM positions, and PM-required fields are not allowed on this contract.
 * v1 consumers that need pixel rects should use `selectionToRects` directly;
 * they should not gate behavior on this neutral surface yet.
 */
export type LayoutFragmentSubrange = {
    identity: LayoutSourceIdentity;
    story: LayoutStoryLocator;
    blockRef: LayoutBlockRef;
    fragmentId: LayoutFragmentId;
    pageIndex: number;
    /** Container-space rectangle covered by the fragment slice. */
    rect: LayoutRect;
    /** Optional opaque inline-offset start (may be omitted). */
    inlineFromOpaque?: string;
    /** Optional opaque inline-offset end (may be omitted). */
    inlineToOpaque?: string;
};
/**
 * PM-free rendered range for the current neutral subset.
 *
 * This maps one or more already-known rendered fragment ids to their full
 * fragment rectangles. It intentionally does not model text offsets; v1 PM
 * range slicing remains available through `PmOpaqueRange`.
 */
export type LayoutFragmentOpaqueRange = {
    fragmentIds: readonly LayoutFragmentId[];
};
/**
 * Result of mapping an opaque source range to rendered fragments.
 *
 * The opaque range type is intentionally `unknown` here; today the only
 * concrete instantiation is `{ pmFrom: number; pmTo: number }`, but the
 * contract names neither, so a future v2 source range can substitute
 * without reopening the layout boundary.
 */
export type LayoutRangeMapping = {
    schema: typeof LAYOUT_BOUNDARY_SCHEMA;
    layoutRevision: number;
    fragments: LayoutFragmentSubrange[];
    diagnostics?: LayoutHitDiagnostic[];
};
/**
 * Concrete opaque-range instantiation for v1 consumers using PM positions.
 *
 * Kept here (and not in `@superdoc/contracts`) because nothing about it is
 * editor-neutral. v2 consumers should not import this type; they should
 * define their own opaque-range shape and the same `mapRangeToFragmentsNeutral`
 * entry point will accept it (via the function overload defined below).
 */
export type PmOpaqueRange = {
    pmFrom: number;
    pmTo: number;
};
/**
 * Hit-test a container-space coordinate and return an editor-neutral
 * `LayoutHit`.
 *
 * Today the implementation derives the underlying mapping by calling
 * `clickToPositionGeometry` and projecting the result onto the neutral
 * shape. The `legacyPm` field is populated so v1 callers continue to work.
 *
 * Returns `null` only when no page can be hit at all; partial hits emit
 * diagnostics rather than failing closed so consumers can distinguish
 * "outside content" from "fragment unrecognized".
 */
export declare function hitTestNeutral(layout: Layout, blocks: FlowBlock[], measures: Measure[], containerPoint: Point, options?: ClickToPositionGeometryOptions): LayoutHit | null;
/**
 * Project rendered selection rectangles into editor-neutral fragment
 * subranges.
 *
 * Accepts a `PmOpaqueRange` today; future neutral range shapes can be
 * accepted via overloads without reopening this contract.
 *
 * The `selectionToRects` produces one `Rect` per visual line; this helper
 * groups them by page and surfaces the underlying fragment identity for
 * each rect. v1 callers that need raw pixel rects should continue to call
 * `selectionToRects` directly — this is the editor-neutral adapter.
 */
export declare function mapRangeToFragmentsNeutral(layout: Layout, blocks: FlowBlock[], measures: Measure[], range: PmOpaqueRange, selectionToRectsFn: (layout: Layout, blocks: FlowBlock[], measures: Measure[], from: number, to: number) => LayoutRect[]): LayoutRangeMapping;
export declare function mapRangeToFragmentsNeutral(layout: Layout, blocks: FlowBlock[], measures: Measure[], range: LayoutFragmentOpaqueRange): LayoutRangeMapping;
//# sourceMappingURL=neutral-hit.d.ts.map