/** * The complete set of things integration is permitted to do to the design. * * The union has exactly three members and none of them names appearance. That * absence is load-bearing — see this file's header. * * - `text` — replace an element's text. Never its markup: `textContent`, not `innerHTML`. * - `attr` — set one attribute, from a fixed allowlist that excludes everything * capable of restyling: no `class`, no `style`, no `id`. * - `presence` — show or hide an element the design already styles for both states, * by toggling the design's OWN state attribute. `hiddenWhenFalsy` names the * attribute the drop's CSS keys on, so presence stays a design decision, not ours. */ export type BindingWrite = { readonly kind: "text"; } | { readonly kind: "attr"; readonly name: AllowedAttribute; } | { readonly kind: "presence"; readonly hiddenWhenFalsy: AllowedAttribute; }; /** * Attributes integration may write. Chosen because none of them can carry a visual * decision: they are content, identity and accessibility, not appearance. `class`, * `style` and `id` are excluded on purpose and adding them would defeat the file. */ export type AllowedAttribute = "aria-label" | "aria-valuenow" | "data-count" | "data-state" | "hidden" | "href" | "title"; export type Binding = { /** * Selector into the design's own markup. Verified to resolve against the drop. */ anchor: string; /** * Dotted path into the kernel snapshot, e.g. `identity.label`. */ source: string; /** * How the value is written. */ as: BindingWrite; /** * Why this binding exists — read by humans reviewing the seam. */ note: string; };