@petrarca/sonnet-schema-designer 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,875 @@
1
+ import { JsonSchemaProperty, JsonSchema, UISchema, UILayoutConfig, UISchemaOptions, UILayoutGroupConfig, UILayoutRowConfig, ValueType, Binding } from '@petrarca/sonnet-core/schema';
2
+ import { z } from 'zod';
3
+
4
+ /**
5
+ * Path navigation over a JsonSchema tree.
6
+ *
7
+ * A path is a list of typed segments from the root down to a property. Most
8
+ * segments are property keys (`{kind:"prop"}`) -- object children nest through
9
+ * `properties`, array-of-object children through `items.properties`, and the
10
+ * navigator descends through `items` transparently so an array and its item
11
+ * object share one editing surface.
12
+ *
13
+ * Logic constructs introduce non-property segments: `{kind:"branch"}` for a
14
+ * `oneOf`/`allOf` element, and `{kind:"slot"}` for a fixed schema slot
15
+ * (`then`/`else`/`items`). The discriminated union keeps the distinction
16
+ * explicit and type-checked; a single codec (pathKey/parsePathKey) owns all
17
+ * conversion to/from strings.
18
+ */
19
+
20
+ /** A fixed schema slot that holds a single sub-schema. */
21
+ type PathSlot = "then" | "else" | "items";
22
+ /**
23
+ * The array a conditional (if/then/else) member lives in. `allOf` = every
24
+ * condition must hold (AND); `anyOf` = any condition suffices (OR). Maps to
25
+ * FHIR `enableBehavior` "all" / "any".
26
+ */
27
+ type ConditionCombinator = "allOf" | "anyOf";
28
+ /** One step in a property path. */
29
+ type PathSegment = {
30
+ kind: "prop";
31
+ key: string;
32
+ } | {
33
+ kind: "branch";
34
+ index: number;
35
+ } | {
36
+ kind: "condition";
37
+ combinator: ConditionCombinator;
38
+ index: number;
39
+ } | {
40
+ kind: "slot";
41
+ slot: PathSlot;
42
+ } | {
43
+ kind: "def";
44
+ name: string;
45
+ };
46
+ type PropertyPath = PathSegment[];
47
+ /**
48
+ * Whether a property key is reserved by the path codec. Keys matching
49
+ * `/^#(branch|condition|def|slot):/` would corrupt the pathKey/parsePathKey
50
+ * round-trip. The designer guards against these at rename/add time.
51
+ */
52
+ declare function isReservedKey(key: string): boolean;
53
+ /** Construct a property-key segment. */
54
+ declare function prop(key: string): PathSegment;
55
+ /** Construct a branch (oneOf element) segment. */
56
+ declare function branch(index: number): PathSegment;
57
+ /** Construct a condition (if/then/else member) segment for a combinator array. */
58
+ declare function condition(index: number, combinator?: ConditionCombinator): PathSegment;
59
+ /** Construct a fixed-slot segment. */
60
+ declare function slot(name: PathSlot): PathSegment;
61
+ /** Construct a definition ($defs entry) segment. Root-only in practice. */
62
+ declare function def(name: string): PathSegment;
63
+ /** Serialize a path to a stable string (React key, selection id, scope value). */
64
+ declare function pathKey(path: PropertyPath): string;
65
+ /** Parse a string produced by {@link pathKey} back into a path. */
66
+ declare function parsePathKey(key: string): PropertyPath;
67
+ /** Whether two path segments refer to the same position. */
68
+ declare function sameSegment(a: PathSegment, b: PathSegment): boolean;
69
+ /** Whether two paths refer to the same node (structural comparison). */
70
+ declare function samePath(a: PropertyPath | null, b: PropertyPath | null): boolean;
71
+ /** How a child slot is presented and mutated. */
72
+ type SlotKind = "property" | "branch" | "conditional" | "definition";
73
+ /** A single editable child of a property (or the root). */
74
+ interface ChildSlot {
75
+ /** Segment appended to the parent path to reach this child. */
76
+ segment: PathSegment;
77
+ /** Display label for the tree row. */
78
+ label: string;
79
+ /** The child schema. */
80
+ property: JsonSchemaProperty;
81
+ kind: SlotKind;
82
+ removable: boolean;
83
+ reorderable: boolean;
84
+ }
85
+ /**
86
+ * The properties map that holds a property's named children, or undefined when
87
+ * it has none. Object children live in `properties`; array-of-object children
88
+ * live in `items.properties`. (Logic constructs use branch/slot children and
89
+ * are surfaced via {@link childSlots}, not here.)
90
+ */
91
+ declare function childContainer(prop: JsonSchemaProperty): Record<string, JsonSchemaProperty> | undefined;
92
+ /**
93
+ * The reusable definitions map of a schema. Canonically 2020-12 `$defs`; also
94
+ * reads Draft-7 `definitions` so both dialects surface as editable nodes. New
95
+ * definitions are always authored into `$defs` (see mutate.addDefinition).
96
+ */
97
+ declare function definitionsOf(property: JsonSchemaProperty): Record<string, JsonSchemaProperty> | undefined;
98
+ /**
99
+ * The ordered child slots of a property (the single extension point for the
100
+ * tree/inspector/mutations). Surfaces object/array property children, oneOf
101
+ * branches, if/then/else conditionals (allOf/anyOf members), and $defs
102
+ * definitions (root-only in practice).
103
+ */
104
+ declare function childSlots(property: JsonSchemaProperty): ChildSlot[];
105
+ /**
106
+ * Wrap a JsonSchema root as an object-shaped JsonSchemaProperty so the path
107
+ * navigation machinery can traverse it with the same stepInto logic as any
108
+ * nested property. Pass the keys needed by the caller; unused fields default
109
+ * to undefined.
110
+ */
111
+ declare function schemaAsRootProp(schema: JsonSchema): JsonSchemaProperty;
112
+ /** Resolve a path to its property definition, or undefined if not found. */
113
+ declare function getProperty(schema: JsonSchema, path: PropertyPath): JsonSchemaProperty | undefined;
114
+ /** Whether a property has (or can have) child slots (properties, branches, conditionals). */
115
+ declare function isContainer(prop: JsonSchemaProperty): boolean;
116
+
117
+ /**
118
+ * Pure edit operations over { schema, uiSchema }.
119
+ *
120
+ * Every function returns a new pair; nothing mutates in place. Operations keep
121
+ * the schema and uiSchema consistent -- renaming a property rewrites the property
122
+ * key, the uiSchema entry, the required entry, and any x-ui-order reference at
123
+ * the same level. Mirrors the graph-model/mutate.ts discipline.
124
+ */
125
+
126
+ type UiSchemaMap = Record<string, UISchema>;
127
+ interface DesignerModel {
128
+ schema: JsonSchema;
129
+ uiSchema: UiSchemaMap;
130
+ }
131
+ /** Kinds that can be created as a new property. */
132
+ type NewPropertyKind = "scalar" | "object" | "array" | "oneOf";
133
+ /** A default property for a newly created property of a given kind. */
134
+ declare function newProperty(kind: NewPropertyKind): JsonSchemaProperty;
135
+ /** A default oneOf branch: an object with a const-valued `kind` discriminator. */
136
+ declare function newBranch(value: string): JsonSchemaProperty;
137
+ /** Add a property under a parent path (root when empty). Returns the new model. */
138
+ declare function addProperty(model: DesignerModel, parentPath: PropertyPath, kind: NewPropertyKind): {
139
+ model: DesignerModel;
140
+ path: PropertyPath;
141
+ };
142
+ /** Add a branch to the oneOf property at `path`. Returns the new model + branch path. */
143
+ declare function addBranch(model: DesignerModel, path: PropertyPath): {
144
+ model: DesignerModel;
145
+ path: PropertyPath;
146
+ };
147
+ /** Remove the branch at `path` (a branch segment). Returns the new model. */
148
+ declare function removeBranch(model: DesignerModel, path: PropertyPath): DesignerModel;
149
+ /** Move the branch at `path` up (-1) or down (+1) among its siblings. */
150
+ declare function moveBranch(model: DesignerModel, path: PropertyPath, direction: -1 | 1): DesignerModel;
151
+ /**
152
+ * A seed conditional member: an empty `if` (no field yet) plus an empty `then`.
153
+ * The condition is filled in by setCondition; `then` fields are added like any
154
+ * object's properties.
155
+ */
156
+ declare function newCondition(): JsonSchemaProperty;
157
+ /**
158
+ * Add a conditional (if/then/else) to the object at `objectPath` (root when
159
+ * empty), appended to the given combinator array (`allOf` = AND, default;
160
+ * `anyOf` = OR). Returns the new model + the condition path.
161
+ */
162
+ declare function addConditional(model: DesignerModel, objectPath: PropertyPath, combinator?: ConditionCombinator): {
163
+ model: DesignerModel;
164
+ path: PropertyPath;
165
+ };
166
+ /** Remove the conditional at `path` (a condition segment). Returns the new model. */
167
+ declare function removeConditional(model: DesignerModel, path: PropertyPath): DesignerModel;
168
+ /** Write the `if` of the conditional at `path` from a condition triple. */
169
+ declare function setCondition(model: DesignerModel, path: PropertyPath, ifSchema: JsonSchemaProperty): DesignerModel;
170
+ /** Add an empty `else` branch to the conditional at `path`. */
171
+ declare function addElse(model: DesignerModel, path: PropertyPath): DesignerModel;
172
+ /** Remove the `else` branch from the conditional at `path`. */
173
+ declare function removeElse(model: DesignerModel, path: PropertyPath): DesignerModel;
174
+ /**
175
+ * Switch the combinator (AND/OR) for the conditionals of the object at
176
+ * `objectPath`. Migrates every conditional member from the current combinator
177
+ * array to `next`. Non-conditional members (structural allOf/anyOf entries)
178
+ * stay put. No-op when already using `next` or when there are no conditionals.
179
+ */
180
+ declare function setConditionalBehavior(model: DesignerModel, objectPath: PropertyPath, next: ConditionCombinator): DesignerModel;
181
+ /** Delete the property at path. Returns the new model. */
182
+ declare function deleteProperty(model: DesignerModel, path: PropertyPath): DesignerModel;
183
+ /** Rename the property at path. Rewrites key, order, required, and uiSchema. */
184
+ declare function renameProperty(model: DesignerModel, path: PropertyPath, nextKey: string): {
185
+ model: DesignerModel;
186
+ path: PropertyPath;
187
+ };
188
+ /** Move the property at path up (-1) or down (+1) among its siblings. */
189
+ declare function moveProperty(model: DesignerModel, path: PropertyPath, direction: -1 | 1): DesignerModel;
190
+ /** Toggle whether the property at path is required among its siblings. */
191
+ declare function setRequired(model: DesignerModel, path: PropertyPath, required: boolean): DesignerModel;
192
+ /** Replace the property definition at path (merges the given partial). */
193
+ declare function updateProperty(model: DesignerModel, path: PropertyPath, patch: Partial<JsonSchemaProperty>): DesignerModel;
194
+ /** The kind a property can be changed to: a JSON Schema type, or a "oneOf" union. */
195
+ type PropertyTypeChoice = NonNullable<JsonSchemaProperty["type"]> | "oneOf";
196
+ /**
197
+ * Change the kind of the property at path, reshaping structural keys: object
198
+ * adds an empty `properties`; array adds `items`; oneOf adds branches + a
199
+ * discriminator; leaving a kind strips its keys. Type-specific validation keys
200
+ * that no longer apply are dropped.
201
+ */
202
+ declare function changePropertyType(model: DesignerModel, path: PropertyPath, next: PropertyTypeChoice): DesignerModel;
203
+ /**
204
+ * Point the property at path to a definition by name, writing a local `$ref`
205
+ * (`#/$defs/<name>`) and stripping type-specific keys. Turns a plain property
206
+ * into a reference usage. No-op for the root or an unknown target.
207
+ */
208
+ declare function setReference(model: DesignerModel, path: PropertyPath, name: string): DesignerModel;
209
+ /**
210
+ * Add a new empty object definition under `$defs`. Returns the new model and the
211
+ * path to the created definition for selection.
212
+ */
213
+ declare function addDefinition(model: DesignerModel, name?: string): {
214
+ model: DesignerModel;
215
+ path: PropertyPath;
216
+ };
217
+ /**
218
+ * Rename a `$defs` entry, preserving order, and rewrite every local `$ref` that
219
+ * targets it (both `#/$defs/` and `#/definitions/` forms) to the new pointer.
220
+ * No-op on collision, reserved, or empty names.
221
+ */
222
+ declare function renameDefinition(model: DesignerModel, oldName: string, newName: string): {
223
+ model: DesignerModel;
224
+ path: PropertyPath;
225
+ };
226
+ /**
227
+ * Remove a `$defs` entry. Blocked (no-op) while any local `$ref` still targets
228
+ * it; the UI surfaces the usage count. Drops the `$defs` map when it empties.
229
+ */
230
+ declare function removeDefinition(model: DesignerModel, name: string): DesignerModel;
231
+ /** Whether a definition is referenced anywhere (for UI delete-guard messaging). */
232
+ declare function definitionUsageCount(schema: JsonSchema, name: string): number;
233
+ /** One enum choice: a value and an optional display label. */
234
+ interface EnumChoice {
235
+ value: string;
236
+ label?: string;
237
+ }
238
+ declare function setEnum(model: DesignerModel, path: PropertyPath, choices: EnumChoice[]): DesignerModel;
239
+ /** Read the current enum choices for a property + its uiSchema entry. */
240
+ declare function readEnumChoices(prop: JsonSchemaProperty, uiEntry: UISchema | undefined): EnumChoice[];
241
+ /** Table presentation hints for a property (embedded in the schema). */
242
+ interface TableHints {
243
+ cell?: string;
244
+ cellOptions?: Record<string, unknown>;
245
+ column?: NonNullable<JsonSchemaProperty["x-ui-column"]>;
246
+ }
247
+ /**
248
+ * Set (or clear) a property's table hints: x-ui-cell, x-ui-cell-options, and
249
+ * x-ui-column. These live embedded on the property (EntityTable reads them
250
+ * there). Empty values clear the corresponding key.
251
+ */
252
+ declare function setTableHints(model: DesignerModel, path: PropertyPath, hints: TableHints): DesignerModel;
253
+ /** Read a property's current table hints. */
254
+ declare function readTableHints(prop: JsonSchemaProperty): TableHints;
255
+ /** Read the UISchema entry for a property path, or undefined. */
256
+ declare function getUiEntryAtPath(uiSchema: UiSchemaMap, path: PropertyPath): UISchema | undefined;
257
+ /** Set (or clear) the UISchema entry at a property path (any nesting depth). */
258
+ declare function setUiEntry(model: DesignerModel, path: PropertyPath, entry: UISchema | undefined): DesignerModel;
259
+ /**
260
+ * Set (or clear) the x-ui-layout of an object/array property at path. Object
261
+ * layout lives on the property; array layout lives on `items`.
262
+ */
263
+ declare function setPropertyLayout(model: DesignerModel, path: PropertyPath, layout: UILayoutConfig | undefined): DesignerModel;
264
+ /** Set (or clear) the root form layout (uiSchema["x-ui-layout"]). */
265
+ declare function setRootLayout(model: DesignerModel, layout: UILayoutConfig | undefined): DesignerModel;
266
+ /**
267
+ * Set (or clear) the root layout rows (uiSchema["x-ui-layout"].rows),
268
+ * preserving other x-ui-layout keys. Clearing rows to empty removes the key;
269
+ * if x-ui-layout then has no keys, it is removed entirely.
270
+ */
271
+ declare function setRootLayoutRows(model: DesignerModel, rows: UILayoutConfig["rows"]): DesignerModel;
272
+ /**
273
+ * Set the layout rows for a scope: the root form (path []) or an object/array
274
+ * container (its property path). Root rows live in uiSchema["x-ui-layout"];
275
+ * a container's rows live on the property's x-ui-layout (array -> items).
276
+ * Preserves other x-ui-layout keys.
277
+ */
278
+ declare function setScopedLayoutRows(model: DesignerModel, scopePath: PropertyPath, rows: UILayoutConfig["rows"]): DesignerModel;
279
+ /** Read the current x-ui-layout for a scope (root or a container property). */
280
+ declare function getScopedLayout(schema: JsonSchema, uiSchema: UiSchemaMap, scopePath: PropertyPath): UILayoutConfig | undefined;
281
+ /**
282
+ * Merge scalar layout options (direction/gap/labels/compact) into a scope's
283
+ * x-ui-layout, preserving rows and other keys. Undefined values clear the key.
284
+ */
285
+ declare function setScopedLayoutOptions(model: DesignerModel, scopePath: PropertyPath, options: Pick<UILayoutConfig, "direction" | "gap" | "labels" | "compact">): DesignerModel;
286
+ /**
287
+ * Set the group definitions for a scope, preserving other x-ui-layout keys.
288
+ * Passing an empty list (or undefined) clears groups, returning the scope to the
289
+ * flat row layout. Root groups live in uiSchema["x-ui-layout"]; a container's
290
+ * live on the property's x-ui-layout (array -> items).
291
+ *
292
+ * Groups and flat rows are mutually exclusive (the renderer gives groups
293
+ * precedence), so setting groups drops `rows` -- otherwise the orphaned list
294
+ * would be invisible in both the form and the designer.
295
+ */
296
+ declare function setScopedLayoutGroups(model: DesignerModel, scopePath: PropertyPath, groups: UILayoutConfig["groups"]): DesignerModel;
297
+ /** Append an empty group. The label defaults to the next ordinal ("Group 3"). */
298
+ declare function addLayoutGroup(model: DesignerModel, scopePath: PropertyPath, label?: string): DesignerModel;
299
+ /** Rename one group. No-op for an unknown index or a blank label. */
300
+ declare function renameLayoutGroup(model: DesignerModel, scopePath: PropertyPath, groupIndex: number, label: string): DesignerModel;
301
+ /**
302
+ * Place a property into one group's row, removing it from wherever it currently
303
+ * sits across *all* groups. Passing a null target returns it to the pool.
304
+ *
305
+ * Needed because each group owns its own rows: without a cross-group operation a
306
+ * field could only be moved between groups by visiting its old group first.
307
+ */
308
+ declare function placeFieldInGroup(model: DesignerModel, scopePath: PropertyPath, key: string, target: {
309
+ groupIndex: number;
310
+ rowIndex: number;
311
+ } | null): DesignerModel;
312
+ /** Move one group left (-1) or right (+1). No-op at the ends. */
313
+ declare function moveLayoutGroup(model: DesignerModel, scopePath: PropertyPath, groupIndex: number, direction: -1 | 1): DesignerModel;
314
+ /**
315
+ * Set (or clear) a group's show/hide rule. Passing undefined makes the group
316
+ * unconditional.
317
+ */
318
+ declare function setLayoutGroupRule(model: DesignerModel, scopePath: PropertyPath, groupIndex: number, rule: UILayoutGroupConfig["rule"]): DesignerModel;
319
+ /**
320
+ * Set the group presentation for a scope ("groups", "stepper", or a custom
321
+ * template name). Passing undefined restores the default group presentation.
322
+ */
323
+ declare function setScopedLayoutVariant(model: DesignerModel, scopePath: PropertyPath, variant: UILayoutConfig["variant"]): DesignerModel;
324
+ /**
325
+ * Remove one group. Its rows are not discarded: removing the last remaining group
326
+ * flattens them back into the scope's flat row layout, so a single click can
327
+ * never destroy every field placement.
328
+ */
329
+ declare function removeLayoutGroup(model: DesignerModel, scopePath: PropertyPath, groupIndex: number): DesignerModel;
330
+ /** Replace the rows of one group in a scope. No-op for an unknown group index. */
331
+ declare function setScopedGroupRows(model: DesignerModel, scopePath: PropertyPath, groupIndex: number, rows: UILayoutRowConfig[]): DesignerModel;
332
+ /**
333
+ * Switch a scope between flat rows and groups, carrying the existing layout over
334
+ * so no field placement is lost: rows become the first group's rows, and leaving
335
+ * group mode flattens every group's rows back into one list.
336
+ */
337
+ declare function setScopedLayoutMode(model: DesignerModel, scopePath: PropertyPath, mode: "rows" | "groups"): DesignerModel;
338
+ /** Set (or clear) the root global options (uiSchema["x-ui-globalOptions"]). */
339
+ declare function setGlobalOptions(model: DesignerModel, options: UISchemaOptions | undefined): DesignerModel;
340
+
341
+ /**
342
+ * Value types as answer types -- a value type contributed to the questionnaire
343
+ * designer: a question whose `$ref` is the type's id is that answer type, and
344
+ * its settings are fields the panel shows, read from and written to the
345
+ * question through the contribution. Sonnet contributes the core types the
346
+ * same way an application contributes its own. Pure, no React. See
347
+ * docs/design/value-types.md (workspace).
348
+ */
349
+
350
+ /** A value type's settings: the panel's fields, read from and written to the question. */
351
+ interface ValueTypeSettings {
352
+ /** The fields, by name, as JSON Schema properties of the panel's form. */
353
+ fields: Record<string, JsonSchemaProperty>;
354
+ /** The settings' values, read from the question's property and hints. */
355
+ read(prop: JsonSchemaProperty, ui: UISchema): Record<string, unknown>;
356
+ /** What the values write: keywords beside the `$ref`, and `x-ui-options` keys -- undefined removes one. */
357
+ write(values: Record<string, unknown>): {
358
+ prop: Partial<JsonSchemaProperty>;
359
+ options: Record<string, unknown>;
360
+ };
361
+ }
362
+ /** A value type contributed as an answer type of the questionnaire designer. */
363
+ interface ValueTypeAnswer {
364
+ type: ValueType;
365
+ /** The keywords it narrows beside its `$ref` (the quantity's `properties`). */
366
+ keywords?: string[];
367
+ /** The `x-ui-options` keys its settings use (the quantity's `units`). */
368
+ options?: string[];
369
+ /** Whether a property of the type is one the designer understands; default: any. */
370
+ accepts?(prop: JsonSchemaProperty): boolean;
371
+ settings?: ValueTypeSettings;
372
+ }
373
+ /** The quantity as an answer type: narrowed at most to its units, each in its range. */
374
+ declare const QUANTITY_ANSWER: ValueTypeAnswer;
375
+ /** The binding a coded value's settings write; none without a list. */
376
+ declare function codingBindingOf(values: Record<string, unknown>): Binding | undefined;
377
+ /** The coded value as an answer type: a code from the list its binding names. */
378
+ declare const CODING_ANSWER: ValueTypeAnswer;
379
+ /** The codeable concept as an answer type: a concept coded in its first list and in further ones, or its text. */
380
+ declare const CODEABLE_CONCEPT_ANSWER: ValueTypeAnswer;
381
+ /** The value types sonnet contributes: the core types. */
382
+ declare const DEFAULT_VALUE_TYPES: readonly ValueTypeAnswer[];
383
+ /** The value type a property is, among those contributed -- by its `$ref`, or that or a text; undefined when none. */
384
+ declare function valueTypeOf(prop: JsonSchemaProperty, types: readonly ValueTypeAnswer[]): ValueTypeAnswer | undefined;
385
+ /** The contribution of an answer type, when it is a value type. */
386
+ declare function valueTypeAnswer(answerType: string, types: readonly ValueTypeAnswer[]): ValueTypeAnswer | undefined;
387
+
388
+ /**
389
+ * Answer types -- a question's kind of answer, as a pattern of schema keywords
390
+ * and form hints. Pure, no React.
391
+ *
392
+ * An answer type is never stored: `recognizeAnswerType` finds it in a property
393
+ * and its effective hints, and names the keywords the pattern does not account
394
+ * for (the question's extra settings, kept untouched). See
395
+ * docs/design/questionnaires.md, "Answer types".
396
+ */
397
+
398
+ /** The answer types the questionnaire designer knows itself. */
399
+ type BuiltinAnswerType = "yesNo" | "shortText" | "longText" | "integer" | "decimal" | "date" | "time" | "dateTime" | "singleChoice" | "multipleChoice" | "choiceWithText" | "listOfText" | "parts";
400
+ /**
401
+ * An answer type: a built-in one, or a contributed value type -- by its id
402
+ * (see valueTypes.ts).
403
+ */
404
+ type AnswerType = BuiltinAnswerType | (string & {});
405
+ /** What each built-in answer type is called where an author sees it. */
406
+ declare const ANSWER_TYPE_LABELS: Record<BuiltinAnswerType, string>;
407
+ /** Whether an answer type is one the designer knows itself, not a contributed value type. */
408
+ declare function isBuiltinAnswerType(type: string): type is BuiltinAnswerType;
409
+ /** What an answer type is called: its label, or its contribution's. */
410
+ declare function answerTypeLabel(type: AnswerType, types?: readonly ValueTypeAnswer[]): string;
411
+ /**
412
+ * The container widget a choice with text renders with: it arranges its two
413
+ * children, `choice` and `text`, each rendered by its own widget -- a select,
414
+ * radio buttons, a terminology picker -- resolved as for any field.
415
+ */
416
+ declare const CHOICE_WITH_TEXT_WIDGET = "choice-with-text";
417
+ /** Whether an answer type is a container -- its children answers of their own, it no answer itself. */
418
+ declare function isContainerType(type: AnswerType): boolean;
419
+ /** A recognized answer: its type, and the keywords the pattern leaves unexplained. */
420
+ interface RecognizedAnswer {
421
+ type: AnswerType;
422
+ /** Schema keywords and hints beyond the pattern -- shown as extra settings, kept as they are. */
423
+ extras: string[];
424
+ }
425
+ /**
426
+ * The option of a choice with text whose choice asks for the text ("other,
427
+ * please describe"); none for the variant whose text is an optional note.
428
+ *
429
+ * The note variant has `choice` and `text` as properties. The other variant
430
+ * has only `choice`, and one conditional of its own: if the choice is that
431
+ * option, then `text`, required.
432
+ */
433
+ declare function choiceTextWhen(prop: JsonSchemaProperty): string | undefined;
434
+ /** The conditional of a choice with text's "other" variant: if the choice is `when`, then the text, required. */
435
+ declare function otherTextMember(when: string, text: JsonSchemaProperty): JsonSchemaProperty;
436
+ /** A choice with text's choice and text, wherever its variant keeps the text -- unchecked. */
437
+ declare function rawChoiceAndText(prop: JsonSchemaProperty): {
438
+ choice?: JsonSchemaProperty;
439
+ text?: JsonSchemaProperty;
440
+ };
441
+ /**
442
+ * The answer type a property follows, with its extra settings; null when the
443
+ * property follows no answer type -- the questionnaire designer then does not
444
+ * understand it. A widget the type does not know is an extra setting, not a
445
+ * reason: the type comes from the schema's shape.
446
+ */
447
+ declare function recognizeAnswerType(prop: JsonSchemaProperty, ui: UISchema, types?: readonly ValueTypeAnswer[]): RecognizedAnswer | null;
448
+ /** The hints a property carries on itself (embedded x-ui-* keys), as a UISchema entry. */
449
+ declare function embeddedHints(prop: JsonSchemaProperty): UISchema;
450
+ /** A new answer's schema and hints: what writing an answer type sets, as one unit. */
451
+ interface AnswerFragment {
452
+ prop: JsonSchemaProperty;
453
+ ui: UISchema;
454
+ }
455
+ /**
456
+ * The schema and hints of an answer type -- the reverse of recognizeAnswerType:
457
+ * `recognizeAnswerType(fragment.prop, fragment.ui)` is the type, with no extras.
458
+ */
459
+ declare function answerTypeFragment(type: AnswerType, options?: string[]): AnswerFragment;
460
+
461
+ /**
462
+ * Condition builder: the bridge between a friendly (property, operator, value)
463
+ * triple and the JSON Schema `if` sub-schema the renderer evaluates.
464
+ *
465
+ * An `if` tests a sibling property. Operators map to standard schema keywords
466
+ * (mirrors the FHIR operator table in packages/sonnet-fhir/docs/design/fhir-questionnaire-adapter.md, tier 1):
467
+ *
468
+ * = -> { properties: { field: { const: value } }, required: [field] }
469
+ * != -> { properties: { field: { not: { const: value } } }, required: [field] }
470
+ * > >= < <= -> exclusiveMinimum / minimum / exclusiveMaximum / maximum
471
+ * exists -> { required: [field] }
472
+ *
473
+ * A value operator always adds `required: [field]` so an absent field does not
474
+ * vacuously satisfy the condition.
475
+ */
476
+
477
+ type ConditionOperator = "=" | "!=" | ">" | ">=" | "<" | "<=" | "exists";
478
+ /** A condition as edited in the inspector. */
479
+ interface Condition {
480
+ field: string;
481
+ operator: ConditionOperator;
482
+ /** Raw string value from the inspector; coerced to number where numeric. */
483
+ value: string;
484
+ /** On a coded question that also takes a text: the value is that text, not a code. */
485
+ asText?: boolean;
486
+ }
487
+
488
+ /**
489
+ * Show only if -- when a question is asked: conditions on the answers to other
490
+ * questions of its section, all of them or any. Pure, no React.
491
+ *
492
+ * In the schema a conditional item is an `allOf` member of its section,
493
+ * `{ if, then: { properties: { <item> }, required } }`: the renderer adds the
494
+ * item to the form while the `if` holds and removes it -- with its answer --
495
+ * when it does not. "All" is one `if` testing every condition; "any" is an `if`
496
+ * of `anyOf` single conditions. Each condition is the schema designer's
497
+ * (model/conditions.ts). A member is understood only when writing back what
498
+ * was read gives exactly the member: what the questionnaire designer cannot
499
+ * show as conditions stays locked. See docs/design/questionnaires.md.
500
+ */
501
+
502
+ /** When an item is shown: all of its conditions hold, or any of them. */
503
+ interface ShowIf {
504
+ behavior: "all" | "any";
505
+ conditions: Condition[];
506
+ }
507
+ /** A section's field, by key -- the comparand is written as its type takes it. */
508
+ type FieldType = (field: string) => JsonSchemaProperty | undefined;
509
+ /** The `if` a show-if is written as. */
510
+ declare function showIfToIf(showIf: ShowIf, typeOf: FieldType): JsonSchemaProperty;
511
+ /** A conditional member's `then`: the items it shows and which of them are required. */
512
+ interface ConditionalItems {
513
+ showIf: ShowIf;
514
+ properties: Record<string, JsonSchemaProperty>;
515
+ required: string[];
516
+ }
517
+ /**
518
+ * The show-if of a section's `allOf` member and the items it shows, or null
519
+ * when the member is not one the questionnaire designer understands -- its `if`
520
+ * is more than conditions on the section's fields, or its `then` more than items.
521
+ */
522
+ declare function readConditional(member: JsonSchemaProperty, sectionKeys: ReadonlySet<string>, typeOf: FieldType): ConditionalItems | null;
523
+
524
+ /**
525
+ * Limits -- what an answer may be: a text's length and pattern, a number's
526
+ * range, a date's or a time's (`formatMinimum` / `formatMaximum`), how many a
527
+ * list holds. Plain JSON Schema keywords on the question,
528
+ * which the form validates; each answer type takes its own. Pure, no React.
529
+ */
530
+
531
+ type LimitKeyword = "minLength" | "maxLength" | "pattern" | "minimum" | "maximum" | "minItems" | "maxItems" | "formatMinimum" | "formatMaximum";
532
+ /** A question's limits, by keyword: counts and bounds are numbers, a pattern its text. */
533
+ interface Limits {
534
+ minLength?: number;
535
+ maxLength?: number;
536
+ pattern?: string;
537
+ minimum?: number;
538
+ maximum?: number;
539
+ minItems?: number;
540
+ maxItems?: number;
541
+ /** The earliest date, time or datetime, as the answer is written. */
542
+ formatMinimum?: string;
543
+ formatMaximum?: string;
544
+ }
545
+ /** The limits each answer type takes; one not listed takes none. */
546
+ declare const ANSWER_TYPE_LIMITS: Partial<Record<AnswerType, LimitKeyword[]>>;
547
+ /** What each limit is called where an author sees it. */
548
+ declare const LIMIT_LABELS: Record<LimitKeyword, string>;
549
+ /** The limits an answer type takes. */
550
+ declare function limitsFor(type: AnswerType): LimitKeyword[];
551
+ /** The limits a question has, of those its answer type takes. */
552
+ declare function limitsOf(prop: JsonSchemaProperty, type: AnswerType): Limits;
553
+
554
+ /**
555
+ * classifyQuestionnaire -- a schema (with its uiSchema) read as a questionnaire:
556
+ * its sections, texts and questions, and in their place whatever the
557
+ * questionnaire designer does not understand. Pure, no React.
558
+ *
559
+ * Every part is sorted into one of three classes: understood (an item), partly
560
+ * understood (an item with `extras` -- the keywords it keeps untouched) and not
561
+ * understood (a `locked` item, with the reason). Nothing is dropped: the
562
+ * classification only reads. See docs/design/questionnaires.md, "The boundary
563
+ * with the schema designer".
564
+ */
565
+
566
+ interface ItemBase {
567
+ key: string;
568
+ path: PropertyPath;
569
+ /** When the item is shown; none: always. */
570
+ showIf?: ShowIf;
571
+ }
572
+ /** A section: a heading, an introduction, its items; repeating when it is a list of them. */
573
+ interface SectionItem extends ItemBase {
574
+ kind: "section";
575
+ title: string;
576
+ description?: string;
577
+ repeats: boolean;
578
+ required: boolean;
579
+ /** A repeating section's count: how many entries at least, at most. */
580
+ limits?: {
581
+ minItems?: number;
582
+ maxItems?: number;
583
+ };
584
+ items: QuestionnaireItem[];
585
+ extras: string[];
586
+ }
587
+ /** Static text between questions. */
588
+ interface TextItem extends ItemBase {
589
+ kind: "text";
590
+ title?: string;
591
+ text?: string;
592
+ extras: string[];
593
+ }
594
+ /** One option of a choice: the value stored, the label shown. */
595
+ interface ChoiceOption {
596
+ value: string;
597
+ label: string;
598
+ }
599
+ /** A question: its text, help, example, and its answer type. */
600
+ interface QuestionItem extends ItemBase {
601
+ kind: "question";
602
+ title: string;
603
+ help?: string;
604
+ placeholder?: string;
605
+ required: boolean;
606
+ readOnly: boolean;
607
+ answerType: AnswerType;
608
+ /** How the question is shown, when it names a widget its answer type knows (`radio`, `select`, ...). */
609
+ presentation?: string;
610
+ /** A choice's options, in order (single, multiple, the choice of a choice with text). */
611
+ options?: ChoiceOption[];
612
+ /** The sub-answers of a container answer type (parts; a choice with text's choice and text). */
613
+ parts?: QuestionItem[];
614
+ /** A choice with text: the option that asks for the text ("other"); none: the text is a note. */
615
+ textWhen?: string;
616
+ /** What the answer may be: its length, pattern, range, count -- as its answer type takes them. */
617
+ limits?: Limits;
618
+ /** A value type's settings, read through its contribution (a quantity's units). */
619
+ settings?: Record<string, unknown>;
620
+ /** The answer given until the person answers (`default`); none for a container. */
621
+ defaultAnswer?: unknown;
622
+ extras: string[];
623
+ }
624
+ /** A part the questionnaire designer does not understand: kept, shown locked, edited in the schema designer. */
625
+ interface LockedItem extends ItemBase {
626
+ kind: "locked";
627
+ title: string;
628
+ reason: string;
629
+ }
630
+ type QuestionnaireItem = SectionItem | TextItem | QuestionItem | LockedItem;
631
+ /** A schema read as a questionnaire. */
632
+ interface QuestionnaireView {
633
+ title?: string;
634
+ description?: string;
635
+ items: QuestionnaireItem[];
636
+ /** The root's keywords and hints the questionnaire designer keeps untouched (a layout, definitions). */
637
+ extras: string[];
638
+ /** The reasons a question may be left unanswered for; none declared: every question is answered. */
639
+ reasons?: ChoiceOption[];
640
+ }
641
+ /** A choice's options: its enum values with their labels (x-ui-options.enumNames); none for another type. */
642
+ declare function optionsOf(prop: JsonSchemaProperty, ui: UISchema, type: AnswerType): ChoiceOption[] | undefined;
643
+ /** What holds a section's items: the root schema, an object, or a repeating section's items. */
644
+ type Container = Pick<JsonSchemaProperty, "properties" | "required" | "x-ui-order" | "allOf" | "anyOf">;
645
+ /** Every item of a container by key: its properties, and those its conditionals show -- what a show-if may test. */
646
+ declare function containerFields(container: Container): Record<string, JsonSchemaProperty>;
647
+ /** The keys of a container's items in the order the form shows them -- conditional ones included. */
648
+ declare function containerOrder(container: Container): string[];
649
+ /** Every item of a questionnaire, at any depth: each section before what it holds. */
650
+ declare function itemsOf(items: QuestionnaireItem[]): QuestionnaireItem[];
651
+ /** The schema read as a questionnaire: every part an item, nothing dropped. */
652
+ declare function classifyQuestionnaire(model: DesignerModel, types?: readonly ValueTypeAnswer[]): QuestionnaireView;
653
+
654
+ /**
655
+ * Questionnaire edits -- what the questionnaire designer does to the schema,
656
+ * in the author's terms. Pure, no React; built on the schema designer's own
657
+ * operations (model/mutate.ts), so both designers edit the same way.
658
+ *
659
+ * Every edit changes only what it touches: the rest of the schema, its
660
+ * uiSchema and every keyword the designer does not understand stay as they
661
+ * are. Changing an answer type is the one edit that can drop something; it
662
+ * returns what it dropped, so the designer asks before applying it. See
663
+ * docs/design/questionnaires.md, "The boundary with the schema designer".
664
+ */
665
+
666
+ /** What an author adds: a question of an answer type, a text, or a section. */
667
+ type NewItem = {
668
+ kind: "question";
669
+ answerType: AnswerType;
670
+ } | {
671
+ kind: "text";
672
+ } | {
673
+ kind: "section";
674
+ };
675
+ /** A key from a question's text: lower case, words joined by `_`, unique among `taken`. */
676
+ declare function keyFromText(text: string, taken: Iterable<string>): string;
677
+ /** Whether a key may be set: lower case letters, digits and `_`, starting with a letter. */
678
+ declare function isValidKey(key: string): boolean;
679
+ /** Add a question, a text or a section at the end of a container; its key from its text. */
680
+ declare function addItem(model: DesignerModel, parentPath: PropertyPath, item: NewItem, text: string): {
681
+ model: DesignerModel;
682
+ path: PropertyPath;
683
+ };
684
+ /** Set a question's, a section's or a text's heading. */
685
+ declare function setItemText(model: DesignerModel, path: PropertyPath, text: string): DesignerModel;
686
+ /** Set a question's help, a section's introduction, a text's body. */
687
+ declare function setHelp(model: DesignerModel, path: PropertyPath, help: string): DesignerModel;
688
+ /** Set whether a question is shown, not entered. */
689
+ declare function setReadOnly(model: DesignerModel, path: PropertyPath, readOnly: boolean): DesignerModel;
690
+ /** Set how a question is shown -- a widget its answer type knows (`radio`, `select`, ...); undefined: its default. */
691
+ declare function setPresentation(model: DesignerModel, path: PropertyPath, widget: string | undefined): DesignerModel;
692
+ /**
693
+ * Set a question's default answer (`default`): given until the person
694
+ * answers, which they may change. An empty one removes it.
695
+ */
696
+ declare function setDefaultAnswer(model: DesignerModel, path: PropertyPath, value: unknown): DesignerModel;
697
+ /** Set a question's example: shown in the empty field, never stored. */
698
+ declare function setPlaceholder(model: DesignerModel, path: PropertyPath, example: string): DesignerModel;
699
+ /** Set an item's key; refused (the model unchanged) when the key is invalid or taken. */
700
+ declare function setKey(model: DesignerModel, path: PropertyPath, key: string): {
701
+ model: DesignerModel;
702
+ path: PropertyPath;
703
+ };
704
+ /** Set a choice's options, in order: their values in the schema, their labels as hints. */
705
+ declare function setOptions(model: DesignerModel, path: PropertyPath, options: ChoiceOption[]): DesignerModel;
706
+ /** The result of changing an answer type: the new model, and what it dropped. */
707
+ interface AnswerTypeChange {
708
+ model: DesignerModel;
709
+ /** Settings the new type does not take -- a `pattern`, an unknown widget, the options. */
710
+ lost: string[];
711
+ }
712
+ /**
713
+ * Change a question's answer type. Its text, help, example and read-only flag
714
+ * stay; options move from one kind of choice to another. What the new type does
715
+ * not take is dropped and named in `lost` -- the designer asks before applying.
716
+ */
717
+ declare function changeAnswerType(model: DesignerModel, path: PropertyPath, type: AnswerType, types?: readonly ValueTypeAnswer[], keep?: readonly string[]): AnswerTypeChange;
718
+ /**
719
+ * Set keywords the questionnaire designer keeps but does not edit itself -- a
720
+ * converter's annotations, say -- on an item, or (an empty path) on the
721
+ * questionnaire; an undefined value removes one.
722
+ */
723
+ declare function setKeywords(model: DesignerModel, path: PropertyPath, keywords: Record<string, unknown>): DesignerModel;
724
+ /**
725
+ * Set whether a section repeats -- a list of entries, each with the section's
726
+ * items. Its items keep their paths: the list's entries are its container.
727
+ */
728
+ declare function setSectionRepeats(model: DesignerModel, path: PropertyPath, repeats: boolean): DesignerModel;
729
+ /** Set one of a question's limits -- its length, pattern, range or count; undefined or empty removes it. */
730
+ declare function setLimit(model: DesignerModel, path: PropertyPath, keyword: LimitKeyword, value: number | string | undefined): DesignerModel;
731
+ /** Set the questionnaire's own title or introduction (the root's title and description). */
732
+ declare function setQuestionnaireText(model: DesignerModel, text: {
733
+ title?: string;
734
+ description?: string;
735
+ }): DesignerModel;
736
+ /** The path of the section an item is in -- the same for its conditional siblings. */
737
+ declare function sectionPathOf(path: PropertyPath): PropertyPath;
738
+ /**
739
+ * Show an item only if conditions hold, or (null) always. The item keeps its
740
+ * key, its place in the section's order and its hints; it moves into a
741
+ * conditional of its own -- or back among the section's properties.
742
+ */
743
+ declare function setShowIf(model: DesignerModel, path: PropertyPath, showIf: ShowIf | null): {
744
+ model: DesignerModel;
745
+ path: PropertyPath;
746
+ };
747
+ /** Move an item up (-1) or down (+1) among its section's items -- conditional ones included. */
748
+ declare function moveItem(model: DesignerModel, path: PropertyPath, direction: -1 | 1): DesignerModel;
749
+ /** Put an item before another of its section (by key), or last (null) -- dragging it there. */
750
+ declare function reorderItem(model: DesignerModel, path: PropertyPath, beforeKey: string | null): DesignerModel;
751
+ /** Delete an item: its definition, its hints, its place in the order -- and its conditional, once empty. */
752
+ declare function deleteItem(model: DesignerModel, path: PropertyPath): DesignerModel;
753
+ /**
754
+ * Set a value type's settings on its question -- the quantity's units -- as its
755
+ * contribution writes them: keywords beside the `$ref`, `x-ui-options` keys.
756
+ */
757
+ declare function setValueTypeSettings(model: DesignerModel, path: PropertyPath, answer: ValueTypeAnswer, values: Record<string, unknown>): DesignerModel;
758
+ /** The option a choice with text's "other" variant adds when its options have none. */
759
+ declare const OTHER_OPTION: {
760
+ value: string;
761
+ label: string;
762
+ };
763
+ /**
764
+ * Set what a choice with text's text is: a note, always offered (null), or
765
+ * asked for only when the choice is one option -- "other, please describe" --
766
+ * and then required. Switching to the latter adds an "other" option when the
767
+ * choice has none; the text keeps its definition either way.
768
+ */
769
+ declare function setChoiceTextWhen(model: DesignerModel, path: PropertyPath, when: string | null): DesignerModel;
770
+ /** The reasons the questionnaire declares (its root's `absent`); none: every question is answered. */
771
+ declare function declaredReasons(model: DesignerModel): ChoiceOption[] | undefined;
772
+ /**
773
+ * Set whether a question must be answered. With reasons declared, an always
774
+ * asked question is required unless a reason is given for it; a conditional
775
+ * one, and any question without reasons, is plainly required.
776
+ */
777
+ declare function setQuestionRequired(model: DesignerModel, path: PropertyPath, required: boolean): DesignerModel;
778
+ /**
779
+ * Declare the reasons a question may be left unanswered for -- or none (null),
780
+ * so every question is answered. Every section gets (or loses) its `absent`,
781
+ * and its required questions become required unless a reason is given (or
782
+ * plainly required again).
783
+ */
784
+ declare function setReasons(model: DesignerModel, reasons: ChoiceOption[] | null): DesignerModel;
785
+
786
+ /**
787
+ * Reasons for no answer -- *unknown*, *not applicable*: a statement about a
788
+ * question instead of its answer. Pure, no React.
789
+ *
790
+ * A questionnaire declares its reasons once; every section then carries them
791
+ * in its own `absent` property, an object of question keys whose values are
792
+ * the declared reasons, so an answer keeps its type and a reason sits beside
793
+ * it. A required question is required *unless* the section's `absent` names
794
+ * it -- one conditional per question, `{ if: { not: <absent names it> }, then:
795
+ * { required: [key] } }` -- so the form asks for an answer or a reason, and
796
+ * the renderer enforces it. See docs/design/questionnaires.md, "Reasons for no
797
+ * answer".
798
+ */
799
+
800
+ /** The property of a section that holds its reasons. */
801
+ declare const ABSENT_KEY = "absent";
802
+ /** The widget a section's reasons are entered with. */
803
+ declare const ABSENT_WIDGET = "absent-reasons";
804
+ /** The `absent` property of a section: question keys to one of the reasons. */
805
+ declare function absentProperty(reasons: ChoiceOption[]): JsonSchemaProperty;
806
+ /** The reasons an `absent` property declares; none when the property is not of that shape. */
807
+ declare function readReasons(prop: JsonSchemaProperty | undefined): ChoiceOption[] | undefined;
808
+ /** The conditional that makes a question required unless a reason is given for it. */
809
+ declare function unlessReasonMember(key: string): JsonSchemaProperty;
810
+ /** The question an "unless a reason" conditional makes required; none for another member. */
811
+ declare function unlessReasonKey(member: JsonSchemaProperty): string | undefined;
812
+ /** The answers of one section: its values, and its reasons in `absent`. */
813
+ type SectionAnswers = Record<string, unknown> & {
814
+ [ABSENT_KEY]?: Record<string, string>;
815
+ };
816
+ /** Whether a question has an answer or a reason in its section's answers. */
817
+ declare function answeredOrExcused(answers: SectionAnswers | undefined, key: string): boolean;
818
+
819
+ /**
820
+ * Completion -- whether a set of answers is complete: every question asked has
821
+ * an answer or a reason for none. A question shown only if conditions hold is
822
+ * asked while they hold. Distinct from `required`, which says an answer must
823
+ * be given. Pure, no React. See docs/design/questionnaires.md, "Reasons for no
824
+ * answer".
825
+ */
826
+
827
+ type Answers = Record<string, unknown>;
828
+ /** Whether the answers are complete, and the questions that still lack an answer or a reason. */
829
+ interface Completion {
830
+ complete: boolean;
831
+ /** The missing questions, by key path (`company.vat_id`; a repeating section's entry by index). */
832
+ missing: string[];
833
+ }
834
+ /** Whether an item is asked, given its section's answers: always, or while its show-if holds. */
835
+ declare function isAsked(showIf: ShowIf | undefined, answers: Answers): boolean;
836
+ /** Whether a set of answers is complete: every question asked has an answer or a reason. */
837
+ declare function isComplete(view: QuestionnaireView, answers: Answers): Completion;
838
+
839
+ /**
840
+ * QuestionnaireDesigner capabilities -- a profile that limits what an author
841
+ * may build. As the schema designer's (../capabilities.ts): the Zod schema is
842
+ * the single source, every field optional and defaulting to the most
843
+ * permissive value, so adding a capability never tightens a profile already
844
+ * written. A profile limits authoring; it never hides what a schema holds --
845
+ * a question of a type the profile does not offer is still shown and edited.
846
+ */
847
+
848
+ declare const questionnaireCapabilitiesSchema: z.ZodObject<{
849
+ answerTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
850
+ sections: z.ZodDefault<z.ZodBoolean>;
851
+ logic: z.ZodDefault<z.ZodBoolean>;
852
+ reasons: z.ZodDefault<z.ZodBoolean>;
853
+ switchToDesigner: z.ZodDefault<z.ZodBoolean>;
854
+ previews: z.ZodDefault<z.ZodArray<z.ZodEnum<{
855
+ form: "form";
856
+ json: "json";
857
+ capabilities: "capabilities";
858
+ }>>>;
859
+ }, z.core.$strip>;
860
+ type QuestionnaireDesignerCapabilities = z.input<typeof questionnaireCapabilitiesSchema>;
861
+ /** The resolved profile: every field set, the answer types listed. */
862
+ type ResolvedQuestionnaireCapabilities = Required<z.output<typeof questionnaireCapabilitiesSchema>>;
863
+ /** A profile checked: its value, or what is wrong with it, by path. */
864
+ declare function validateQuestionnaireCapabilities(input: unknown): {
865
+ ok: true;
866
+ value: QuestionnaireDesignerCapabilities;
867
+ } | {
868
+ ok: false;
869
+ errors: string[];
870
+ };
871
+ /** Resolve a profile: defaults applied; an invalid one warns and falls back to the defaults. */
872
+ declare function resolveQuestionnaireCapabilities(capabilities: QuestionnaireDesignerCapabilities | undefined, valueTypes?: readonly ValueTypeAnswer[]): ResolvedQuestionnaireCapabilities;
873
+
874
+ export { addLayoutGroup as $, ABSENT_KEY as A, LIMIT_LABELS as L, absentProperty as M, OTHER_OPTION as O, addBranch as W, addConditional as X, addDefinition as Y, addElse as Z, addItem as _, renameProperty as a$, addProperty as a0, answerTypeFragment as a1, answerTypeLabel as a2, answeredOrExcused as a3, branch as a4, changeAnswerType as a5, changePropertyType as a6, childContainer as a7, childSlots as a8, choiceTextWhen as a9, moveBranch as aA, moveItem as aB, moveLayoutGroup as aC, moveProperty as aD, newBranch as aE, newCondition as aF, newProperty as aG, optionsOf as aH, otherTextMember as aI, parsePathKey as aJ, pathKey as aK, placeFieldInGroup as aL, prop as aM, questionnaireCapabilitiesSchema as aN, rawChoiceAndText as aO, readConditional as aP, readEnumChoices as aQ, readReasons as aR, readTableHints as aS, recognizeAnswerType as aT, removeBranch as aU, removeConditional as aV, removeDefinition as aW, removeElse as aX, removeLayoutGroup as aY, renameDefinition as aZ, renameLayoutGroup as a_, classifyQuestionnaire as aa, codingBindingOf as ab, condition as ac, containerFields as ad, containerOrder as ae, declaredReasons as af, def as ag, definitionUsageCount as ah, definitionsOf as ai, deleteItem as aj, deleteProperty as ak, embeddedHints as al, getProperty as am, getScopedLayout as an, getUiEntryAtPath as ao, isAsked as ap, isBuiltinAnswerType as aq, isComplete as ar, isContainer as as, isContainerType as at, isReservedKey as au, isValidKey as av, itemsOf as aw, keyFromText as ax, limitsFor as ay, limitsOf as az, ABSENT_WIDGET as b, reorderItem as b0, resolveQuestionnaireCapabilities as b1, samePath as b2, sameSegment as b3, schemaAsRootProp as b4, sectionPathOf as b5, setChoiceTextWhen as b6, setCondition as b7, setConditionalBehavior as b8, setDefaultAnswer as b9, setSectionRepeats as bA, setShowIf as bB, setTableHints as bC, setUiEntry as bD, setValueTypeSettings as bE, showIfToIf as bF, slot as bG, unlessReasonKey as bH, unlessReasonMember as bI, updateProperty as bJ, validateQuestionnaireCapabilities as bK, valueTypeAnswer as bL, valueTypeOf as bM, setEnum as ba, setGlobalOptions as bb, setHelp as bc, setItemText as bd, setKey as be, setKeywords as bf, setLayoutGroupRule as bg, setLimit as bh, setOptions as bi, setPlaceholder as bj, setPresentation as bk, setPropertyLayout as bl, setQuestionRequired as bm, setQuestionnaireText as bn, setReadOnly as bo, setReasons as bp, setReference as bq, setRequired as br, setRootLayout as bs, setRootLayoutRows as bt, setScopedGroupRows as bu, setScopedLayoutGroups as bv, setScopedLayoutMode as bw, setScopedLayoutOptions as bx, setScopedLayoutRows as by, setScopedLayoutVariant as bz, ANSWER_TYPE_LABELS as c, ANSWER_TYPE_LIMITS as d, CHOICE_WITH_TEXT_WIDGET as h, CODEABLE_CONCEPT_ANSWER as i, CODING_ANSWER as j, DEFAULT_VALUE_TYPES as p, QUANTITY_ANSWER as w };
875
+ export type { BuiltinAnswerType as B, ConditionCombinator as C, DesignerModel as D, EnumChoice as E, FieldType as F, ResolvedQuestionnaireCapabilities as G, SectionItem as H, ShowIf as I, TextItem as J, ValueTypeSettings as K, NewPropertyKind as N, PropertyPath as P, QuestionnaireDesignerCapabilities as Q, RecognizedAnswer as R, SlotKind as S, TableHints as T, UiSchemaMap as U, ValueTypeAnswer as V, PropertyTypeChoice as a, AnswerFragment as e, AnswerType as f, AnswerTypeChange as g, ChildSlot as k, ChoiceOption as l, Completion as m, Condition as n, ConditionalItems as o, LimitKeyword as q, Limits as r, LockedItem as s, NewItem as t, PathSegment as u, PathSlot as v, QuestionItem as x, QuestionnaireItem as y, QuestionnaireView as z };