/** * Kit prop schemas + classing (W2 §The Kit). * * Every prop is a `PropSpec`: a zod schema, a class, and a one-line doc. The * class is the enforcement handle for the two laws — * - `data` props must trace to a tool call (law 1); * - `config` props tune behavior (sort, limit, format); * - `copy` props are human-facing strings the model may write freely. * The same specs are the single source for the GENERATED prompt (`kitPrompt`) * and for runtime validation (`propsSchema`). Hand-written prop lists are dead. */ import { z, type ZodTypeAny } from "zod"; export type PropClass = "config" | "copy" | "data"; export interface PropSpec { cls: PropClass; schema: ZodTypeAny; doc: string; required?: boolean; } interface PropOptions { required?: boolean; } /** A behavior/tuning prop (sort, limit, format, tone). */ export declare function config(schema: ZodTypeAny, doc: string, options?: PropOptions): PropSpec; /** A human-facing string the model may author (label, title, empty-state text). */ export declare function copy(schema: ZodTypeAny, doc: string, options?: PropOptions): PropSpec; /** A prop that must trace to a tool call — real business data (law 1). */ export declare function data(schema: ZodTypeAny, doc: string, options?: PropOptions): PropSpec; /** * A SLOT — a named place inside a component that holds an ELEMENT instead of a * value (a table column's `cell`, a Timeline's `marker`). It is a prop of its * own, or a field of the description objects one prop holds; `at` says which, * and `kitSlotPath` writes the two as one comparable string. */ export interface KitSlotSpec { /** 1-line "what goes here". */ doc: string; /** Painted once per row/entry rather than once for the component — so the * function form of this slot takes the ROW, and the screen VM calls it once per * row instead of once (`KIT_SLOT_PROPS`). */ perRow?: boolean; /** This slot holds FINISHED TEXT rather than elements — a chart's `format`, the * only shape of slot that does. Everything about the slot law is the same (the * VM resolves the function, the nesting check admits the path); what differs is * what may come back out, which is why the schema beside it is `textSlot` and * why `ui`'s slot-drift sweep probes this one with a string. A formatter that * handed back a component would paint "[object Object]" on an axis. */ text?: boolean; /** The prop holding the rows a `perRow` slot is painted once for. Required on * one — it is what the VM maps the slot's function over. */ rows?: string; /** The PROP whose description objects carry this slot as a field, so the slot * lives at `[].` (`columns[].cell`). Absent means the slot is a * prop of its own (`marker`). * * Load-bearing, not documentation: a component reads its slot at exactly one * place, so a same-named field anywhere else (`rows[].cell` on a DataTable * that only renders `columns[].cell`) is a value nothing paints. The nesting * check matches on this path and refuses the rest. */ at?: string; } /** * Two props the component cannot honour TOGETHER: it paints one and drops the * other, and no schema can say so — each is individually valid, and the pair is * what is wrong. `Timeline` is the case: given a `cell` AND a `titleField` the * cell wins in silence, so the model asked for a title and got a body it never * wrote, with every stage passing. */ export interface KitExclusiveProps { /** The props that may not be written together. */ props: readonly string[]; /** The repair, NAMED: which one to keep and what it costs to drop the other. A * refusal that only reports the collision leaves the model to guess. */ fix: string; } export interface KitComponentSpec { /** JSX tag name the model emits. */ name: string; /** 1-2 sentence "when to use". */ summary: string; /** Prop name → spec. */ props: Record; /** 1-2 canonical JSX examples. */ examples: string[]; /** Optional group for prompt organization (layout, values, data, charts, forms). */ group?: string; /** Does this component RENDER what is nested inside it? Absent means no — most * of the Kit is a leaf, and the renderer hands children to leaves too. */ takesChildren?: boolean; /** What to write INSTEAD of children, for a childless component whose own * props are not the obvious answer. The nesting check's generic sentence ends * with "give it what it showed through its own props", which is true and * useless for a ``: the entries are DATA plus one handler, and nothing * in the refusal said so. */ childrenFix?: string; /** The prop pairs this component cannot honour together, refused by the * nesting check rather than resolved in silence. */ exclusive?: readonly KitExclusiveProps[]; /** Slot name → spec. Absent means the component takes no elements in its * props at all, and one written there is refused rather than dropped. */ slots?: Record; /** * The third-party engine this component RENDERS ("recharts", "Base UI"), whose * own props pass through to it. Absent means the component wraps nothing, and * its prop list is closed — an undeclared name there is the "valid component, * nothing happens" class the floor refuses. * * An engine's prop vocabulary is the engine's, not ours: it is admitted * unvalidated, so an engine upgrade is free and a stored app naming a prop the * engine has since renamed or dropped renders wrong until it is regenerated. */ engine?: string; } /** Build a `z.object` from a spec's props, applying `.optional()` to non-required * ones. An engine-backed spec stays OPEN, because the engine's own props are * legal on it and a stripped `stroke` is a series that silently keeps the theme. */ export declare function propsSchema(spec: KitComponentSpec): z.ZodObject; /** Validate a props object against a spec. Returns zod's SafeParse result. */ export declare function validateProps(spec: KitComponentSpec, props: unknown): z.SafeParseReturnType<{ [x: string]: any; }, { [x: string]: any; }>; export {}; //# sourceMappingURL=schema.d.ts.map