import type { PageModel } from './store.js'; /** * Host-declared presentation of one branch kind. * * `kind` matches either a `stateKind` a case declares, or one of the two kinds * the core derives on its own: `step` for a plain screen and `variant` for a * numbered branch that declares no state kind. */ export interface FrameBranchKindDef { kind: string; /** Word shown in the pill. */ label: string; /** Accent colour for the rule and the pill text. */ accent: string; } /** * Words for the facts the core counts. Defaults are English; a host renders * its own language by declaring them, so the core carries no product copy. */ export interface FrameLabelLabels { /** Unit for the layer count. Default "layers". */ layers?: string; /** Shown when a screen frame claims no scenario at all. Default "no scenario". */ noScenario?: string; /** Shown when the import dropped nodes. Default "some omissions". */ omissions?: string; /** Shown when the import failed. Default "check flow". */ checkFlow?: string; } export declare function resolveFrameLabelLabels(labels: FrameLabelLabels | undefined): Required; /** Branch kinds the core derives when a frame declares no state kind. */ export declare const FRAME_BRANCH_STEP = "step"; export declare const FRAME_BRANCH_VARIANT = "variant"; /** Neutral accent for a kind the host has not described. */ export declare const FRAME_BRANCH_FALLBACK_ACCENT = "#8b8b9e"; export interface FrameBranchKindDiagnostic { severity: 'error' | 'warning'; kind: string; message: string; } export declare function validateFrameBranchKinds(defs: readonly FrameBranchKindDef[], context?: { stateKinds?: readonly string[]; }): FrameBranchKindDiagnostic[]; /** Every scenario a page claims: the whole declared set, or its canonical id. */ export declare function pageScenarioIds(page: PageModel): readonly string[]; /** * A screen frame with nothing to say about coverage. Catalog sheets are not * screens and are not expected to claim scenarios, so only routed frames * count as a hole. */ export declare function pageMissesScenario(page: PageModel): boolean; export declare function framesMissingScenario(pages: readonly PageModel[]): readonly PageModel[]; /** * Branch kind of a frame. * * A declared state kind wins, because the host said what the branch is. Absent * one, a case number with a third segment (`02.02.2` beside `02.02`) is the * catalog's own way of saying "branch of the screen before it" — the same * convention the fold groups read. */ export declare function frameBranchKind(page: PageModel): string; /** Leading case number of a frame name, or null when it has none. */ export declare function frameLabelCode(page: PageModel): string | null; export interface FrameLabelParts { /** Case number, or null for a frame that is not numbered. */ code: string | null; /** Title after the flow prefix, e.g. "recording error". */ title: string; /** Secondary clause: the state this branch is in. */ state?: string; } /** * Splits a frame name into the banner's slots. * * Catalog names carry ` / `; the flow is already the * section, so repeating it in the title would spend the widest slot on the * thing the section band above it already says. */ export declare function frameLabelParts(page: PageModel): FrameLabelParts; /** * The counted line, in the order a reviewer scans it. An import that failed or * dropped nodes says so first — it changes whether the frame can be trusted at * all — and a screen claiming no scenario says that rather than staying quiet, * which is how fourteen uncovered screens went unnoticed. */ export declare function frameLabelFacts(page: PageModel, labels: Required<FrameLabelLabels>): string; export declare const FRAME_LABEL_STYLE: { readonly radius: 10; readonly pillRadius: 999; readonly ruleWidth: 6; readonly gap: 14; readonly paddingY: 10; readonly paddingRight: 16; readonly codeSize: 32; readonly titleSize: 20; readonly metaSize: 14; readonly pillSize: 12; readonly pillPaddingY: 4; readonly pillPaddingX: 10; /** Text of the unclassified-surfaces badge: a warning tint on the dark surface. */ readonly unclassified: "#f5c86b"; /** Bottom margin between the label and its frame. */ readonly marginBottom: 8; readonly surface: "#343441"; readonly pillSurface: "#2e2c3a"; readonly caption: "#a1a1b3"; readonly code: "#ffffff"; readonly title: "#e7e7f0"; readonly titleMuted: "#a1a1b3"; readonly meta: "#bebecb"; readonly purpose: "#c4ccd8"; }; /** * The full label's maximum height and the room it consumes above a viewport. * * The label is an overlay, so this does not change a frame's own coordinates. * Section titles and lane captions read the same clearance to stack above it * instead of being painted across the label on the first frame of a section. */ export declare const FRAME_LABEL_HEIGHT: number; export declare const FRAME_LABEL_OVERLAY_CLEARANCE: number; /** * Below this zoom the label keeps only its rule and code. * * At overview zoom the label is a few pixels tall: a 20px title renders at 5px * and is noise, while a 32px code renders at 8px and still parses, and colour * survives any scale at all. So the overview tier spends everything on the two * signals that keep working — which branch kind, which number — and a canvas * of sixty frames reads as a coloured structure instead of grey mush. */ export declare const FRAME_LABEL_COMPACT_ZOOM = 0.35; /** One editor's declared frame branch kinds and label labels. */ export declare function createFrameLabels(): { setFrameBranchKinds: (defs: readonly FrameBranchKindDef[], labels?: FrameLabelLabels) => void; getFrameBranchKinds: () => readonly FrameBranchKindDef[]; getFrameLabelLabels: () => FrameLabelLabels | undefined; frameBranchKindFor: (kind: string) => FrameBranchKindDef; }; export type FrameLabels = ReturnType<typeof createFrameLabels>;