@petrarca/sonnet-schema-designer 0.4.2 → 0.6.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.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { JsonSchemaProperty, JsonSchema, UISchema, UILayoutConfig, UISchemaOptions } from '@petrarca/sonnet-core/schema';
1
+ import { JsonSchemaProperty, JsonSchema, RefResolver, UISchema, UILayoutConfig, UISchemaOptions, UILayoutGroupConfig, UILayoutRowConfig } from '@petrarca/sonnet-core/schema';
2
2
  import { z } from 'zod';
3
3
  import React from 'react';
4
4
  import { WidgetOptionDef } from '@petrarca/sonnet-forms/widget-options';
@@ -7,26 +7,115 @@ import { TableUiSchema } from '@petrarca/sonnet-ui';
7
7
  /**
8
8
  * Path navigation over a JsonSchema tree.
9
9
  *
10
- * A property path is an array of property keys from the root down to a
11
- * property, e.g. ["address", "city"]. Object children nest through
12
- * `properties`; array children nest through `items.properties`. The path names
13
- * the property and the navigator descends through `items` transparently, so an
14
- * array-of-objects and its item object share one editing surface.
10
+ * A path is a list of typed segments from the root down to a property. Most
11
+ * segments are property keys (`{kind:"prop"}`) -- object children nest through
12
+ * `properties`, array-of-object children through `items.properties`, and the
13
+ * navigator descends through `items` transparently so an array and its item
14
+ * object share one editing surface.
15
+ *
16
+ * Logic constructs introduce non-property segments: `{kind:"branch"}` for a
17
+ * `oneOf`/`allOf` element, and `{kind:"slot"}` for a fixed schema slot
18
+ * (`then`/`else`/`items`). The discriminated union keeps the distinction
19
+ * explicit and type-checked; a single codec (pathKey/parsePathKey) owns all
20
+ * conversion to/from strings.
15
21
  */
16
22
 
17
- type PropertyPath = string[];
18
- /** Serialize a path for use as a stable React key or selection id. */
23
+ /** A fixed schema slot that holds a single sub-schema. */
24
+ type PathSlot = "then" | "else" | "items";
25
+ /**
26
+ * The array a conditional (if/then/else) member lives in. `allOf` = every
27
+ * condition must hold (AND); `anyOf` = any condition suffices (OR). Maps to
28
+ * FHIR `enableBehavior` "all" / "any".
29
+ */
30
+ type ConditionCombinator = "allOf" | "anyOf";
31
+ /** One step in a property path. */
32
+ type PathSegment = {
33
+ kind: "prop";
34
+ key: string;
35
+ } | {
36
+ kind: "branch";
37
+ index: number;
38
+ } | {
39
+ kind: "condition";
40
+ combinator: ConditionCombinator;
41
+ index: number;
42
+ } | {
43
+ kind: "slot";
44
+ slot: PathSlot;
45
+ } | {
46
+ kind: "def";
47
+ name: string;
48
+ };
49
+ type PropertyPath = PathSegment[];
50
+ /**
51
+ * Whether a property key is reserved by the path codec. Keys matching
52
+ * `/^#(branch|condition|def|slot):/` would corrupt the pathKey/parsePathKey
53
+ * round-trip. The designer guards against these at rename/add time.
54
+ */
55
+ declare function isReservedKey(key: string): boolean;
56
+ /** Construct a property-key segment. */
57
+ declare function prop(key: string): PathSegment;
58
+ /** Construct a branch (oneOf element) segment. */
59
+ declare function branch(index: number): PathSegment;
60
+ /** Construct a condition (if/then/else member) segment for a combinator array. */
61
+ declare function condition(index: number, combinator?: ConditionCombinator): PathSegment;
62
+ /** Construct a fixed-slot segment. */
63
+ declare function slot(name: PathSlot): PathSegment;
64
+ /** Construct a definition ($defs entry) segment. Root-only in practice. */
65
+ declare function def(name: string): PathSegment;
66
+ /** Serialize a path to a stable string (React key, selection id, scope value). */
19
67
  declare function pathKey(path: PropertyPath): string;
20
- /** Whether two paths refer to the same property. */
68
+ /** Parse a string produced by {@link pathKey} back into a path. */
69
+ declare function parsePathKey(key: string): PropertyPath;
70
+ /** Whether two path segments refer to the same position. */
71
+ declare function sameSegment(a: PathSegment, b: PathSegment): boolean;
72
+ /** Whether two paths refer to the same node (structural comparison). */
21
73
  declare function samePath(a: PropertyPath | null, b: PropertyPath | null): boolean;
22
- /** The container that holds a property's children, or undefined for scalars. */
74
+ /** How a child slot is presented and mutated. */
75
+ type SlotKind = "property" | "branch" | "conditional" | "definition";
76
+ /** A single editable child of a property (or the root). */
77
+ interface ChildSlot {
78
+ /** Segment appended to the parent path to reach this child. */
79
+ segment: PathSegment;
80
+ /** Display label for the tree row. */
81
+ label: string;
82
+ /** The child schema. */
83
+ property: JsonSchemaProperty;
84
+ kind: SlotKind;
85
+ removable: boolean;
86
+ reorderable: boolean;
87
+ }
88
+ /**
89
+ * The properties map that holds a property's named children, or undefined when
90
+ * it has none. Object children live in `properties`; array-of-object children
91
+ * live in `items.properties`. (Logic constructs use branch/slot children and
92
+ * are surfaced via {@link childSlots}, not here.)
93
+ */
23
94
  declare function childContainer(prop: JsonSchemaProperty): Record<string, JsonSchemaProperty> | undefined;
95
+ /**
96
+ * The reusable definitions map of a schema. Canonically 2020-12 `$defs`; also
97
+ * reads Draft-7 `definitions` so both dialects surface as editable nodes. New
98
+ * definitions are always authored into `$defs` (see mutate.addDefinition).
99
+ */
100
+ declare function definitionsOf(property: JsonSchemaProperty): Record<string, JsonSchemaProperty> | undefined;
101
+ /**
102
+ * The ordered child slots of a property (the single extension point for the
103
+ * tree/inspector/mutations). Surfaces object/array property children, oneOf
104
+ * branches, if/then/else conditionals (allOf/anyOf members), and $defs
105
+ * definitions (root-only in practice).
106
+ */
107
+ declare function childSlots(property: JsonSchemaProperty): ChildSlot[];
108
+ /**
109
+ * Wrap a JsonSchema root as an object-shaped JsonSchemaProperty so the path
110
+ * navigation machinery can traverse it with the same stepInto logic as any
111
+ * nested property. Pass the keys needed by the caller; unused fields default
112
+ * to undefined.
113
+ */
114
+ declare function schemaAsRootProp(schema: JsonSchema): JsonSchemaProperty;
24
115
  /** Resolve a path to its property definition, or undefined if not found. */
25
116
  declare function getProperty(schema: JsonSchema, path: PropertyPath): JsonSchemaProperty | undefined;
26
- /** Whether a property has (or can have) child properties. */
117
+ /** Whether a property has (or can have) child slots (properties, branches, conditionals). */
27
118
  declare function isContainer(prop: JsonSchemaProperty): boolean;
28
- /** The child properties of a property, or an empty map for scalars. */
29
- declare function childrenOf(prop: JsonSchemaProperty): Record<string, JsonSchemaProperty>;
30
119
 
31
120
  /**
32
121
  * Read-shaping: turn a JsonSchema into a property tree for the designer UI.
@@ -35,32 +124,51 @@ declare function childrenOf(prop: JsonSchemaProperty): Record<string, JsonSchema
35
124
  * first, then remaining keys in declaration order.
36
125
  */
37
126
 
38
- type PropertyKind = "scalar" | "enum" | "object" | "array";
127
+ type PropertyKind = "scalar" | "enum" | "object" | "array" | "oneOf" | "conditional" | "reference" | "definition";
39
128
  interface PropertyNode {
40
129
  path: PropertyPath;
41
130
  key: string;
42
131
  property: JsonSchemaProperty;
43
132
  kind: PropertyKind;
133
+ /** How this node sits in its parent: a named property or a oneOf branch. */
134
+ slotKind: SlotKind;
44
135
  required: boolean;
45
136
  /** Short type descriptor for the tree row, e.g. "string", "object[]". */
46
137
  typeLabel: string;
47
138
  /** Resolved widget override (x-ui-widget) if any. */
48
139
  widget?: string;
140
+ /**
141
+ * When this node is a `$ref`, the ref string it points at. Undefined for
142
+ * non-ref nodes.
143
+ */
144
+ reference?: string;
145
+ /**
146
+ * True for nodes that live inside a resolved `$ref` (the ref's descendants).
147
+ * These come from a shared definition and are not editable here -- the tree
148
+ * and inspector use this to show read-only affordances. Computed once at
149
+ * build time (no per-render schema walks). The ref node itself is NOT marked
150
+ * (the usage can be renamed/deleted).
151
+ */
152
+ readOnly?: boolean;
49
153
  children: PropertyNode[];
50
154
  }
51
155
  /** Classify a property into a tree kind. */
52
156
  declare function propertyKind(prop: JsonSchemaProperty): PropertyKind;
53
157
  /** Order keys by explicit x-ui-order, then remaining declaration order. */
54
158
  declare function orderedKeys(properties: Record<string, JsonSchemaProperty>, order: string[] | undefined): string[];
55
- /** Build the full property tree for a schema. */
56
- declare function buildPropertyTree(schema: JsonSchema): PropertyNode[];
159
+ /**
160
+ * Build the full property tree for a schema. Pass `resolve` to expand `$ref`
161
+ * nodes (read-only) so referenced structure is legible; without it, ref nodes
162
+ * show as leaves. `resolve` mirrors the renderer's RefResolver.
163
+ */
164
+ declare function buildPropertyTree(schema: JsonSchema, resolve?: RefResolver): PropertyNode[];
57
165
  /**
58
166
  * A layout scope: a container whose fields can be arranged into rows. Root is
59
167
  * the form itself (path []); nested scopes are object/array containers.
60
168
  */
61
169
  interface LayoutScope {
62
170
  /** Empty for root, otherwise the property path to the container. */
63
- path: string[];
171
+ path: PropertyPath;
64
172
  /** Human label, e.g. "Form (root)" or "contact" or "addresses (items)". */
65
173
  label: string;
66
174
  }
@@ -81,13 +189,56 @@ interface DesignerModel {
81
189
  schema: JsonSchema;
82
190
  uiSchema: UiSchemaMap;
83
191
  }
192
+ /** Kinds that can be created as a new property. */
193
+ type NewPropertyKind = "scalar" | "object" | "array" | "oneOf";
84
194
  /** A default property for a newly created property of a given kind. */
85
- declare function newProperty(kind: "scalar" | "object" | "array"): JsonSchemaProperty;
195
+ declare function newProperty(kind: NewPropertyKind): JsonSchemaProperty;
196
+ /** A default oneOf branch: an object with a const-valued `kind` discriminator. */
197
+ declare function newBranch(value: string): JsonSchemaProperty;
86
198
  /** Add a property under a parent path (root when empty). Returns the new model. */
87
- declare function addProperty(model: DesignerModel, parentPath: PropertyPath, kind: "scalar" | "object" | "array"): {
199
+ declare function addProperty(model: DesignerModel, parentPath: PropertyPath, kind: NewPropertyKind): {
200
+ model: DesignerModel;
201
+ path: PropertyPath;
202
+ };
203
+ /** Add a branch to the oneOf property at `path`. Returns the new model + branch path. */
204
+ declare function addBranch(model: DesignerModel, path: PropertyPath): {
205
+ model: DesignerModel;
206
+ path: PropertyPath;
207
+ };
208
+ /** Remove the branch at `path` (a branch segment). Returns the new model. */
209
+ declare function removeBranch(model: DesignerModel, path: PropertyPath): DesignerModel;
210
+ /** Move the branch at `path` up (-1) or down (+1) among its siblings. */
211
+ declare function moveBranch(model: DesignerModel, path: PropertyPath, direction: -1 | 1): DesignerModel;
212
+ /**
213
+ * A seed conditional member: an empty `if` (no field yet) plus an empty `then`.
214
+ * The condition is filled in by setCondition; `then` fields are added like any
215
+ * object's properties.
216
+ */
217
+ declare function newCondition(): JsonSchemaProperty;
218
+ /**
219
+ * Add a conditional (if/then/else) to the object at `objectPath` (root when
220
+ * empty), appended to the given combinator array (`allOf` = AND, default;
221
+ * `anyOf` = OR). Returns the new model + the condition path.
222
+ */
223
+ declare function addConditional(model: DesignerModel, objectPath: PropertyPath, combinator?: ConditionCombinator): {
88
224
  model: DesignerModel;
89
225
  path: PropertyPath;
90
226
  };
227
+ /** Remove the conditional at `path` (a condition segment). Returns the new model. */
228
+ declare function removeConditional(model: DesignerModel, path: PropertyPath): DesignerModel;
229
+ /** Write the `if` of the conditional at `path` from a condition triple. */
230
+ declare function setCondition(model: DesignerModel, path: PropertyPath, ifSchema: JsonSchemaProperty): DesignerModel;
231
+ /** Add an empty `else` branch to the conditional at `path`. */
232
+ declare function addElse(model: DesignerModel, path: PropertyPath): DesignerModel;
233
+ /** Remove the `else` branch from the conditional at `path`. */
234
+ declare function removeElse(model: DesignerModel, path: PropertyPath): DesignerModel;
235
+ /**
236
+ * Switch the combinator (AND/OR) for the conditionals of the object at
237
+ * `objectPath`. Migrates every conditional member from the current combinator
238
+ * array to `next`. Non-conditional members (structural allOf/anyOf entries)
239
+ * stay put. No-op when already using `next` or when there are no conditionals.
240
+ */
241
+ declare function setConditionalBehavior(model: DesignerModel, objectPath: PropertyPath, next: ConditionCombinator): DesignerModel;
91
242
  /** Delete the property at path. Returns the new model. */
92
243
  declare function deleteProperty(model: DesignerModel, path: PropertyPath): DesignerModel;
93
244
  /** Rename the property at path. Rewrites key, order, required, and uiSchema. */
@@ -101,12 +252,45 @@ declare function moveProperty(model: DesignerModel, path: PropertyPath, directio
101
252
  declare function setRequired(model: DesignerModel, path: PropertyPath, required: boolean): DesignerModel;
102
253
  /** Replace the property definition at path (merges the given partial). */
103
254
  declare function updateProperty(model: DesignerModel, path: PropertyPath, patch: Partial<JsonSchemaProperty>): DesignerModel;
255
+ /** The kind a property can be changed to: a JSON Schema type, or a "oneOf" union. */
256
+ type PropertyTypeChoice = NonNullable<JsonSchemaProperty["type"]> | "oneOf";
257
+ /**
258
+ * Change the kind of the property at path, reshaping structural keys: object
259
+ * adds an empty `properties`; array adds `items`; oneOf adds branches + a
260
+ * discriminator; leaving a kind strips its keys. Type-specific validation keys
261
+ * that no longer apply are dropped.
262
+ */
263
+ declare function changePropertyType(model: DesignerModel, path: PropertyPath, next: PropertyTypeChoice): DesignerModel;
264
+ /**
265
+ * Point the property at path to a definition by name, writing a local `$ref`
266
+ * (`#/$defs/<name>`) and stripping type-specific keys. Turns a plain property
267
+ * into a reference usage. No-op for the root or an unknown target.
268
+ */
269
+ declare function setReference(model: DesignerModel, path: PropertyPath, name: string): DesignerModel;
104
270
  /**
105
- * Change the type of the property at path, reshaping structural keys: switching to
106
- * object adds an empty `properties`; to array adds `items`; leaving them strips
107
- * those keys. Type-specific validation keys that no longer apply are dropped.
271
+ * Add a new empty object definition under `$defs`. Returns the new model and the
272
+ * path to the created definition for selection.
108
273
  */
109
- declare function changePropertyType(model: DesignerModel, path: PropertyPath, nextType: JsonSchemaProperty["type"]): DesignerModel;
274
+ declare function addDefinition(model: DesignerModel, name?: string): {
275
+ model: DesignerModel;
276
+ path: PropertyPath;
277
+ };
278
+ /**
279
+ * Rename a `$defs` entry, preserving order, and rewrite every local `$ref` that
280
+ * targets it (both `#/$defs/` and `#/definitions/` forms) to the new pointer.
281
+ * No-op on collision, reserved, or empty names.
282
+ */
283
+ declare function renameDefinition(model: DesignerModel, oldName: string, newName: string): {
284
+ model: DesignerModel;
285
+ path: PropertyPath;
286
+ };
287
+ /**
288
+ * Remove a `$defs` entry. Blocked (no-op) while any local `$ref` still targets
289
+ * it; the UI surfaces the usage count. Drops the `$defs` map when it empties.
290
+ */
291
+ declare function removeDefinition(model: DesignerModel, name: string): DesignerModel;
292
+ /** Whether a definition is referenced anywhere (for UI delete-guard messaging). */
293
+ declare function definitionUsageCount(schema: JsonSchema, name: string): number;
110
294
  /** One enum choice: a value and an optional display label. */
111
295
  interface EnumChoice {
112
296
  value: string;
@@ -160,6 +344,58 @@ declare function getScopedLayout(schema: JsonSchema, uiSchema: UiSchemaMap, scop
160
344
  * x-ui-layout, preserving rows and other keys. Undefined values clear the key.
161
345
  */
162
346
  declare function setScopedLayoutOptions(model: DesignerModel, scopePath: PropertyPath, options: Pick<UILayoutConfig, "direction" | "gap" | "labels" | "compact">): DesignerModel;
347
+ /**
348
+ * Set the group definitions for a scope, preserving other x-ui-layout keys.
349
+ * Passing an empty list (or undefined) clears groups, returning the scope to the
350
+ * flat row layout. Root groups live in uiSchema["x-ui-layout"]; a container's
351
+ * live on the property's x-ui-layout (array -> items).
352
+ *
353
+ * Groups and flat rows are mutually exclusive (the renderer gives groups
354
+ * precedence), so setting groups drops `rows` -- otherwise the orphaned list
355
+ * would be invisible in both the form and the designer.
356
+ */
357
+ declare function setScopedLayoutGroups(model: DesignerModel, scopePath: PropertyPath, groups: UILayoutConfig["groups"]): DesignerModel;
358
+ /** Append an empty group. The label defaults to the next ordinal ("Group 3"). */
359
+ declare function addLayoutGroup(model: DesignerModel, scopePath: PropertyPath, label?: string): DesignerModel;
360
+ /** Rename one group. No-op for an unknown index or a blank label. */
361
+ declare function renameLayoutGroup(model: DesignerModel, scopePath: PropertyPath, groupIndex: number, label: string): DesignerModel;
362
+ /**
363
+ * Place a property into one group's row, removing it from wherever it currently
364
+ * sits across *all* groups. Passing a null target returns it to the pool.
365
+ *
366
+ * Needed because each group owns its own rows: without a cross-group operation a
367
+ * field could only be moved between groups by visiting its old group first.
368
+ */
369
+ declare function placeFieldInGroup(model: DesignerModel, scopePath: PropertyPath, key: string, target: {
370
+ groupIndex: number;
371
+ rowIndex: number;
372
+ } | null): DesignerModel;
373
+ /** Move one group left (-1) or right (+1). No-op at the ends. */
374
+ declare function moveLayoutGroup(model: DesignerModel, scopePath: PropertyPath, groupIndex: number, direction: -1 | 1): DesignerModel;
375
+ /**
376
+ * Set (or clear) a group's show/hide rule. Passing undefined makes the group
377
+ * unconditional.
378
+ */
379
+ declare function setLayoutGroupRule(model: DesignerModel, scopePath: PropertyPath, groupIndex: number, rule: UILayoutGroupConfig["rule"]): DesignerModel;
380
+ /**
381
+ * Set the group presentation for a scope ("groups", "stepper", or a custom
382
+ * template name). Passing undefined restores the default group presentation.
383
+ */
384
+ declare function setScopedLayoutVariant(model: DesignerModel, scopePath: PropertyPath, variant: UILayoutConfig["variant"]): DesignerModel;
385
+ /**
386
+ * Remove one group. Its rows are not discarded: removing the last remaining group
387
+ * flattens them back into the scope's flat row layout, so a single click can
388
+ * never destroy every field placement.
389
+ */
390
+ declare function removeLayoutGroup(model: DesignerModel, scopePath: PropertyPath, groupIndex: number): DesignerModel;
391
+ /** Replace the rows of one group in a scope. No-op for an unknown group index. */
392
+ declare function setScopedGroupRows(model: DesignerModel, scopePath: PropertyPath, groupIndex: number, rows: UILayoutRowConfig[]): DesignerModel;
393
+ /**
394
+ * Switch a scope between flat rows and groups, carrying the existing layout over
395
+ * so no field placement is lost: rows become the first group's rows, and leaving
396
+ * group mode flattens every group's rows back into one list.
397
+ */
398
+ declare function setScopedLayoutMode(model: DesignerModel, scopePath: PropertyPath, mode: "rows" | "groups"): DesignerModel;
163
399
  /** Set (or clear) the root global options (uiSchema["x-ui-globalOptions"]). */
164
400
  declare function setGlobalOptions(model: DesignerModel, options: UISchemaOptions | undefined): DesignerModel;
165
401
 
@@ -293,12 +529,17 @@ interface UseDesignerStateArgs {
293
529
  onChange?: (schema: JsonSchema, uiSchema: UiSchemaMap) => void;
294
530
  readOnly?: boolean;
295
531
  capabilities?: SchemaDesignerCapabilities;
532
+ /** Optional resolver for non-local `$ref`s (registry id / URI); local $defs
533
+ * resolve automatically. Used to expand ref nodes (read-only) in the tree. */
534
+ refResolver?: RefResolver;
296
535
  }
297
536
  interface DesignerState {
298
537
  schema: JsonSchema;
299
538
  uiSchema: UiSchemaMap;
300
539
  selection: PropertyPath | null;
301
540
  readOnly: boolean;
541
+ /** Resolver for $ref expansion in the tree (undefined = local $defs only). */
542
+ refResolver?: RefResolver;
302
543
  /** Resolved capability profile (readOnly + editablePaths applied). */
303
544
  capabilities: ResolvedCapabilities;
304
545
  /** Whether the property at path may be renamed / deleted / retyped / reordered. */
@@ -306,13 +547,43 @@ interface DesignerState {
306
547
  /** Whether a child property may be added to the container at path (root = []). */
307
548
  canAddChild: (path: PropertyPath) => boolean;
308
549
  select: (path: PropertyPath | null) => void;
309
- addProperty: (parentPath: PropertyPath, kind: "scalar" | "object" | "array") => void;
550
+ addProperty: (parentPath: PropertyPath, kind: NewPropertyKind) => void;
551
+ /** Add a branch to the oneOf property at path. */
552
+ addBranch: (path: PropertyPath) => void;
553
+ /** Remove the branch at path (a branch segment). */
554
+ removeBranch: (path: PropertyPath) => void;
555
+ /** Move the branch at path up (-1) or down (+1). */
556
+ moveBranch: (path: PropertyPath, direction: -1 | 1) => void;
557
+ /** Add an if/then/else conditional to the object at path (root when empty). */
558
+ addConditional: (objectPath: PropertyPath, combinator?: ConditionCombinator) => void;
559
+ /** Switch the AND/OR combinator for the conditionals of the object at path. */
560
+ setConditionalBehavior: (objectPath: PropertyPath, combinator: ConditionCombinator) => void;
561
+ /** Remove the conditional at path (a condition segment). */
562
+ removeConditional: (path: PropertyPath) => void;
563
+ /** Write the `if` schema of the conditional at path. */
564
+ setCondition: (path: PropertyPath, ifSchema: JsonSchemaProperty) => void;
565
+ /** Add an empty `else` branch to the conditional at path. */
566
+ addElse: (path: PropertyPath) => void;
567
+ /** Remove the `else` branch from the conditional at path. */
568
+ removeElse: (path: PropertyPath) => void;
310
569
  deleteProperty: (path: PropertyPath) => void;
311
570
  renameProperty: (path: PropertyPath, nextKey: string) => void;
312
571
  moveProperty: (path: PropertyPath, direction: -1 | 1) => void;
313
572
  setRequired: (path: PropertyPath, required: boolean) => void;
314
573
  updateProperty: (path: PropertyPath, patch: Partial<JsonSchemaProperty>) => void;
315
- changePropertyType: (path: PropertyPath, nextType: JsonSchemaProperty["type"]) => void;
574
+ changePropertyType: (path: PropertyPath, next: PropertyTypeChoice) => void;
575
+ /** Point the property at path at a definition (writes a local `$ref`). */
576
+ setReference: (path: PropertyPath, name: string) => void;
577
+ /** Add a new empty object definition to `$defs`. Selects the new node. */
578
+ addDefinition: (name?: string) => void;
579
+ /** Rename a `$defs` entry; rewrites every local `$ref` that targets it. */
580
+ renameDefinition: (oldName: string, newName: string) => void;
581
+ /** Remove an unused `$defs` entry (blocked while any `$ref` targets it). */
582
+ removeDefinition: (name: string) => void;
583
+ /** Replace the whole JSON Schema (from the editable JSON Schema source tab). */
584
+ replaceSchema: (schema: JsonSchema) => void;
585
+ /** Replace the whole UI Schema map (from the editable UI Schema source tab). */
586
+ replaceUiSchema: (uiSchema: UiSchemaMap) => void;
316
587
  setEnum: (path: PropertyPath, choices: EnumChoice[]) => void;
317
588
  setUiEntry: (path: PropertyPath, entry: UISchema | undefined) => void;
318
589
  setTableHints: (path: PropertyPath, hints: TableHints) => void;
@@ -321,6 +592,29 @@ interface DesignerState {
321
592
  setRootLayoutRows: (rows: UILayoutConfig["rows"]) => void;
322
593
  setScopedLayoutRows: (scopePath: PropertyPath, rows: UILayoutConfig["rows"]) => void;
323
594
  setScopedLayoutOptions: (scopePath: PropertyPath, options: Pick<UILayoutConfig, "direction" | "gap" | "labels" | "compact">) => void;
595
+ /** Replace a scope's group definitions (empty clears groups -> flat rows). */
596
+ setScopedLayoutGroups: (scopePath: PropertyPath, groups: UILayoutConfig["groups"]) => void;
597
+ /** Replace the rows of one group within a scope. */
598
+ setScopedGroupRows: (scopePath: PropertyPath, groupIndex: number, rows: UILayoutRowConfig[]) => void;
599
+ /** Switch a scope between flat rows and groups, carrying placements over. */
600
+ setScopedLayoutMode: (scopePath: PropertyPath, mode: "rows" | "groups") => void;
601
+ /** Append an empty group to a scope. */
602
+ addLayoutGroup: (scopePath: PropertyPath, label?: string) => void;
603
+ /** Rename one group of a scope. */
604
+ renameLayoutGroup: (scopePath: PropertyPath, groupIndex: number, label: string) => void;
605
+ /** Remove one group; removing the last flattens its rows back to flat rows. */
606
+ removeLayoutGroup: (scopePath: PropertyPath, groupIndex: number) => void;
607
+ /** Move one group left (-1) or right (+1). */
608
+ moveLayoutGroup: (scopePath: PropertyPath, groupIndex: number, direction: -1 | 1) => void;
609
+ /** Set (or clear) a group's show/hide rule. */
610
+ setLayoutGroupRule: (scopePath: PropertyPath, groupIndex: number, rule: UILayoutGroupConfig["rule"]) => void;
611
+ /** Choose the group presentation ("tabs", "stepper", "sections", ...). */
612
+ setScopedLayoutVariant: (scopePath: PropertyPath, variant: UILayoutConfig["variant"]) => void;
613
+ /** Place a property into a group's row, or back in the pool (null target). */
614
+ placeFieldInGroup: (scopePath: PropertyPath, key: string, target: {
615
+ groupIndex: number;
616
+ rowIndex: number;
617
+ } | null) => void;
324
618
  setGlobalOptions: (options: UISchemaOptions | undefined) => void;
325
619
  }
326
620
  declare function useDesignerState(args: UseDesignerStateArgs): DesignerState;
@@ -359,6 +653,13 @@ interface SchemaDesignerProps {
359
653
  capabilities?: SchemaDesignerCapabilities;
360
654
  /** Option descriptors for custom widgets, keyed by widget name (merged over built-ins). */
361
655
  widgetOptions?: Record<string, WidgetOptionDef[]>;
656
+ /**
657
+ * Optional resolver for non-local `$ref`s (schema-registry id / canonical
658
+ * URI). Local `#/$defs` refs resolve automatically. When provided, ref nodes
659
+ * are expanded read-only in the tree. Synchronous -- pre-load referenced
660
+ * schemas and pass a lookup.
661
+ */
662
+ refResolver?: RefResolver;
362
663
  }
363
664
  declare function SchemaDesigner(props: SchemaDesignerProps): React.ReactElement;
364
665
 
@@ -528,4 +829,4 @@ interface FormSettingsSheetProps {
528
829
  }
529
830
  declare function FormSettingsSheet({ open, onOpenChange, state, }: FormSettingsSheetProps): React.ReactElement;
530
831
 
531
- export { type CapabilitiesValidation, DataTab, type DesignerModel, type DesignerState, type EnumChoice, EnumEditor, FormLayoutDesigner, FormSettingsSheet, Inspector, type LayoutScope, PreviewPane, type PropertyKind, type PropertyNode, type PropertyPath, PropertyTree, type ResolvedCapabilities, SchemaDesigner, type SchemaDesignerCapabilities, type SchemaDesignerProps, type TableHints, TableHintsTab, TablePreview, UITab, type UiSchemaMap, type UseDesignerStateArgs, type WidgetChoice, addProperty, buildPropertyTree, capabilitiesSchema, changePropertyType, childContainer, childrenOf, compatibleWidgets, deleteProperty, embedUiSchema, getProperty, getScopedLayout, getUiEntryAtPath, isContainer, layoutScopes, moveProperty, newProperty, orderedKeys, pathKey, propertyKind, readEnumChoices, readTableHints, renameProperty, resolveCapabilities, samePath, sampleRows, setEnum, setGlobalOptions, setPropertyLayout, setRequired, setRootLayout, setRootLayoutRows, setScopedLayoutOptions, setScopedLayoutRows, setTableHints, setUiEntry, updateProperty, useDesignerState, validateCapabilities };
832
+ export { type CapabilitiesValidation, type ChildSlot, type ConditionCombinator, DataTab, type DesignerModel, type DesignerState, type EnumChoice, EnumEditor, FormLayoutDesigner, FormSettingsSheet, Inspector, type LayoutScope, type NewPropertyKind, type PathSegment, type PathSlot, PreviewPane, type PropertyKind, type PropertyNode, type PropertyPath, PropertyTree, type PropertyTypeChoice, type ResolvedCapabilities, SchemaDesigner, type SchemaDesignerCapabilities, type SchemaDesignerProps, type SlotKind, type TableHints, TableHintsTab, TablePreview, UITab, type UiSchemaMap, type UseDesignerStateArgs, type WidgetChoice, addBranch, addConditional, addDefinition, addElse, addLayoutGroup, addProperty, branch, buildPropertyTree, capabilitiesSchema, changePropertyType, childContainer, childSlots, compatibleWidgets, condition, def, definitionUsageCount, definitionsOf, deleteProperty, embedUiSchema, getProperty, getScopedLayout, getUiEntryAtPath, isContainer, isReservedKey, layoutScopes, moveBranch, moveLayoutGroup, moveProperty, newBranch, newCondition, newProperty, orderedKeys, parsePathKey, pathKey, placeFieldInGroup, prop, propertyKind, readEnumChoices, readTableHints, removeBranch, removeConditional, removeDefinition, removeElse, removeLayoutGroup, renameDefinition, renameLayoutGroup, renameProperty, resolveCapabilities, samePath, sameSegment, sampleRows, schemaAsRootProp, setCondition, setConditionalBehavior, setEnum, setGlobalOptions, setLayoutGroupRule, setPropertyLayout, setReference, setRequired, setRootLayout, setRootLayoutRows, setScopedGroupRows, setScopedLayoutGroups, setScopedLayoutMode, setScopedLayoutOptions, setScopedLayoutRows, setScopedLayoutVariant, setTableHints, setUiEntry, slot, updateProperty, useDesignerState, validateCapabilities };