import type { QuestionAnswer, QuestionData } from "../../tool/types.ts";
import type { WrappingSelectItem } from "../../view/components/wrapping-select.ts";
/**
 * Pure derivation: does the option focused by `(currentTab, optionIndex)` carry a
 * non-empty `preview` string? Mode gates (chat focus, notes mode, multiSelect) layer
 * on top via dispatch branches; this predicate is intentionally mode-agnostic.
 */
export declare function computeFocusedOptionHasPreview(questions: readonly QuestionData[], currentTab: number, optionIndex: number): boolean;
/**
 * Numbering for the chat row's WrappingSelect, computed from the active tab's items.
 *
 * The chat row lives in its own one-item WrappingSelect; the host calls this on every tab
 * switch / selection update to keep the chat row's `N. ` label continuous with the visible
 * numbered rows of the active tab. The shape `{ offset, total }` mirrors
 * `WrappingSelect.setNumbering(numberStartOffset, totalItemsForNumbering)` directly.
 */
export declare function chatNumberingFor(items: readonly WrappingSelectItem[]): {
    offset: number;
    total: number;
};
/**
 * Which row in the active tab should be marked as "previously confirmed"? Drives the
 * `WrappingSelect` confirmed-row indicator (label + ` ✔`) when the user navigates back
 * to a question they already answered. Returns `undefined` when no marker should be drawn —
 * multi-select handles its own `[✔]` boxes via `multiSelectChecked`, `kind: "chat"` ends the
 * dialog so the row can never be re-entered, and a missing/non-matching answer (defensive)
 * silently skips the marker.
 */
export declare function selectConfirmedIndicator(questions: readonly QuestionData[], currentTab: number, answers: ReadonlyMap<number, QuestionAnswer>, items: readonly WrappingSelectItem[]): {
    index: number;
    labelOverride?: string;
} | undefined;
/**
 * Index of the preview pane to display for the current tab. The Submit tab (currentTab ===
 * questions.length) reuses the last question's pane purely for layout — the strategy
 * machinery picks the right body component independently. Defensive against `totalQuestions === 0`.
 */
export declare function selectActivePreviewPaneIndex(currentTab: number, totalQuestions: number): number;
/**
 * Items array for the active tab, with the same Submit-tab clamp as `selectActivePreviewPaneIndex`.
 * Falls back to an empty array if the index lands outside the items array (defensive).
 */
export declare function selectActiveTabItems(itemsByTab: ReadonlyArray<readonly WrappingSelectItem[]>, currentTab: number, totalQuestions: number): readonly WrappingSelectItem[];
//# sourceMappingURL=derivations.d.ts.map