/** * What a pattern instance holds, as the properties column shows it (#473). * * READ-ONLY, and that is a decision rather than a phase boundary. Binding a * part is a model edit that `apply` already performs through `update-concept` * with `parts` (#448); a second way in, through a panel, would be a second * spelling of one operation. This says what the instance holds and what it has * not decided, and leaves the deciding to the surface that already does it. * * A pure model over plain data, tested without a DOM. The component around it * renders these rows and nothing else. */ import type { PatternMembership, PatternVacancy } from '../compiler.js'; import type { YarramateOperation } from '../operations.js'; /** One slot of one instance, bound or not. */ export interface SlotRow { readonly slot: string; /** * The subject bound into it, or `null` where nothing is. A null row is a * decision nobody has taken, which is exactly what the interview asks about * (ADR 0140) — the properties column and the question are two views of one * fact, so they must not be able to disagree. */ readonly member: string | null; /** * `context` slots name what the instance USES rather than what it holds, so * a reader looking at a box needs them marked: they are the only rows here * that do NOT fold inside it. */ readonly wiring: PatternMembership['wiring']; /** For an unbound slot, whether the model does not stand up without it. */ readonly required: boolean; /** How many OTHER instances bind the same subject, for a shared part. */ readonly sharedWith: number; /** * Bound by a change that is STAGED and not yet landed (#473 phase 4). * * The compile knows only what landed, so without this a reviewer picks a * subject for an empty slot, the row snaps back to "to decide", and the only * evidence anything happened is a count in another section. The properties * form already overlays staged edits onto the fields it shows, and the slots * are the same question asked about `parts`. */ readonly staged?: boolean; } export interface SlotsSection { readonly pattern: string; readonly rows: readonly SlotRow[]; /** Bound slots, and slots still to decide. Cheap for a heading. */ readonly boundCount: number; readonly vacantCount: number; } /** * The slots of one instance, bound rows first and vacancies after, each group * in slot-name order. * * Bound first because a reader opening the panel is usually checking what IS * there; the vacancies read as a to-do list under it, which is what they are. * * Returns `null` for a subject that is not a pattern instance at all — a panel * with an empty Slots heading says "this has no parts", which is a different * and wrong claim. */ export declare function slotsSectionFor(subjectId: string, memberships?: readonly PatternMembership[], vacancies?: readonly PatternVacancy[], /** * The pending changeset, so a staged binding shows where it was made. Read * in tray order, the way `apply` replays a batch, so a slot picked twice * shows the LAST choice rather than the first. */ staged?: readonly YarramateOperation[]): SlotsSection | null; /** * What one row says, in words, so the component renders a string it did not * compose and a test can assert the wording without a DOM. */ export declare function slotRowLabel(row: SlotRow): string;