schema-components 1.17.0 → 1.18.1

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.
Files changed (53) hide show
  1. package/dist/core/adapter.d.mts +1 -1
  2. package/dist/core/constraints.d.mts +1 -1
  3. package/dist/core/diagnostics.d.mts +1 -1
  4. package/dist/core/fieldOrder.d.mts +10 -0
  5. package/dist/core/fieldOrder.mjs +12 -0
  6. package/dist/core/merge.d.mts +14 -8
  7. package/dist/core/merge.mjs +109 -12
  8. package/dist/core/normalise.d.mts +1 -1
  9. package/dist/core/ref.d.mts +1 -1
  10. package/dist/core/renderer.d.mts +2 -2
  11. package/dist/core/renderer.mjs +31 -1
  12. package/dist/core/swagger2.d.mts +1 -1
  13. package/dist/core/typeInference.d.mts +2 -2
  14. package/dist/core/walkBuilders.d.mts +2 -2
  15. package/dist/core/walker.mjs +2 -2
  16. package/dist/{diagnostics-DzbZmcLI.d.mts → diagnostics-BYk63jsC.d.mts} +1 -1
  17. package/dist/html/a11y.d.mts +13 -2
  18. package/dist/html/a11y.mjs +26 -2
  19. package/dist/html/renderToHtml.d.mts +1 -1
  20. package/dist/html/renderToHtml.mjs +18 -33
  21. package/dist/html/renderToHtmlStream.d.mts +1 -1
  22. package/dist/html/renderers.d.mts +4 -3
  23. package/dist/html/renderers.mjs +37 -36
  24. package/dist/html/streamRenderers.d.mts +1 -1
  25. package/dist/html/streamRenderers.mjs +10 -21
  26. package/dist/openapi/ApiSecurity.mjs +1 -1
  27. package/dist/openapi/bundle.d.mts +9 -4
  28. package/dist/openapi/bundle.mjs +74 -15
  29. package/dist/openapi/components.d.mts +1 -1
  30. package/dist/openapi/components.mjs +20 -15
  31. package/dist/openapi/parser.d.mts +2 -2
  32. package/dist/openapi/parser.mjs +12 -12
  33. package/dist/openapi/resolve.d.mts +13 -2
  34. package/dist/openapi/resolve.mjs +19 -3
  35. package/dist/react/SchemaComponent.d.mts +3 -3
  36. package/dist/react/SchemaComponent.mjs +1 -30
  37. package/dist/react/SchemaView.d.mts +4 -3
  38. package/dist/react/SchemaView.mjs +12 -43
  39. package/dist/react/headless.d.mts +1 -1
  40. package/dist/react/headlessRenderers.d.mts +1 -1
  41. package/dist/react/headlessRenderers.mjs +37 -32
  42. package/dist/{ref-DvWoULcy.d.mts → ref-Ckt5liZs.d.mts} +1 -1
  43. package/dist/{renderer-B3s8o2B8.d.mts → renderer-BAGoX4AK.d.mts} +20 -26
  44. package/dist/themes/mantine.d.mts +1 -1
  45. package/dist/themes/mantine.mjs +6 -4
  46. package/dist/themes/mui.d.mts +1 -1
  47. package/dist/themes/mui.mjs +7 -5
  48. package/dist/themes/radix.d.mts +1 -1
  49. package/dist/themes/radix.mjs +5 -4
  50. package/dist/themes/shadcn.d.mts +1 -1
  51. package/dist/themes/shadcn.mjs +8 -6
  52. package/dist/{typeInference-k7FXfTVO.d.mts → typeInference-5JiqIZ8t.d.mts} +57 -4
  53. package/package.json +1 -1
@@ -2,7 +2,7 @@
2
2
  import { isObject, toRecordOrUndefined } from "../core/guards.mjs";
3
3
  import { SchemaFieldError, SchemaNormalisationError, SchemaRenderError } from "../core/errors.mjs";
4
4
  import { normaliseSchema } from "../core/adapter.mjs";
5
- import { getRenderFunction, mergeResolvers } from "../core/renderer.mjs";
5
+ import { buildRenderProps, getRenderFunction, mergeResolvers } from "../core/renderer.mjs";
6
6
  import { walk } from "../core/walker.mjs";
7
7
  import { headlessResolver } from "./headless.mjs";
8
8
  import { resolvePath, resolveValue, setNestedValue } from "./fieldPath.mjs";
@@ -203,35 +203,6 @@ function renderField(tree, value, onChange, userResolver, renderChild, path, ins
203
203
  if (value === void 0 || value === null) return /* @__PURE__ */ jsx("span", { children: "—" });
204
204
  return /* @__PURE__ */ jsx("span", { children: typeof value === "string" ? value : JSON.stringify(value) });
205
205
  }
206
- function buildRenderProps(tree, value, onChange, renderChild, path) {
207
- const props = {
208
- value,
209
- onChange,
210
- readOnly: tree.editability === "presentation",
211
- writeOnly: tree.editability === "input",
212
- meta: tree.meta,
213
- constraints: tree.constraints,
214
- path,
215
- tree,
216
- renderChild
217
- };
218
- if (tree.type === "enum") props.enumValues = tree.enumValues;
219
- if (tree.type === "array" && tree.element !== void 0) props.element = tree.element;
220
- if (tree.type === "object") props.fields = tree.fields;
221
- if (tree.type === "union" || tree.type === "discriminatedUnion") props.options = tree.options;
222
- if (tree.type === "discriminatedUnion") props.discriminator = tree.discriminator;
223
- if (tree.type === "record") props.keyType = tree.keyType;
224
- if (tree.type === "record") props.valueType = tree.valueType;
225
- if (tree.type === "tuple") props.prefixItems = tree.prefixItems;
226
- if (tree.type === "conditional") props.ifClause = tree.ifClause;
227
- if (tree.type === "conditional" && tree.thenClause !== void 0) props.thenClause = tree.thenClause;
228
- if (tree.type === "conditional" && tree.elseClause !== void 0) props.elseClause = tree.elseClause;
229
- if (tree.type === "negation") props.negated = tree.negated;
230
- if (tree.type === "recursive") props.refTarget = tree.refTarget;
231
- if (tree.type === "literal") props.literalValues = tree.literalValues;
232
- if (tree.examples !== void 0) props.examples = tree.examples;
233
- return props;
234
- }
235
206
  function SchemaField({ path, schema: schemaInput, ref: refInput, value, onChange, meta: fieldMeta, validate, onValidationError }) {
236
207
  const userResolver = useContext(UserResolverContext);
237
208
  const contextWidgets = useContext(WidgetsContext);
@@ -1,6 +1,6 @@
1
1
  import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
2
- import { t as Diagnostic } from "../diagnostics-DzbZmcLI.mjs";
3
- import { r as ComponentResolver } from "../renderer-B3s8o2B8.mjs";
2
+ import { t as Diagnostic } from "../diagnostics-BYk63jsC.mjs";
3
+ import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
4
4
  import { WidgetMap } from "./SchemaComponent.mjs";
5
5
  import { ReactNode } from "react";
6
6
 
@@ -38,7 +38,8 @@ interface SchemaViewProps {
38
38
  idPrefix?: string;
39
39
  }
40
40
  /**
41
- * Server-safe schema renderer — no hooks, no context, no state.
41
+ * Server-safe schema renderer — no context and no state. The only hook
42
+ * called is `useId()`, which is RSC-safe.
42
43
  *
43
44
  * Always renders in read-only mode. For editable forms, use
44
45
  * `<SchemaComponent>` with `"use client"`.
@@ -1,6 +1,6 @@
1
1
  import { SchemaNormalisationError, SchemaRenderError } from "../core/errors.mjs";
2
2
  import { normaliseSchema } from "../core/adapter.mjs";
3
- import { getRenderFunction, mergeResolvers } from "../core/renderer.mjs";
3
+ import { buildRenderProps, getRenderFunction, mergeResolvers } from "../core/renderer.mjs";
4
4
  import { walk } from "../core/walker.mjs";
5
5
  import { headlessResolver } from "./headless.mjs";
6
6
  import { joinPath, sanitisePrefix } from "./SchemaComponent.mjs";
@@ -10,9 +10,12 @@ import { createElement, isValidElement, useId } from "react";
10
10
  /**
11
11
  * React Server Component for read-only schema rendering.
12
12
  *
13
- * This component has zero hooks — no `useContext`, no `useMemo`,
14
- * no `useCallback`. It can run in a React Server Component environment
15
- * without the `"use client"` directive.
13
+ * Uses no React state, context, or effects — no `useContext`, `useMemo`,
14
+ * `useCallback`, `useState`, or `useEffect`. The single hook called is
15
+ * `useId()`, which is one of the few hooks permitted inside a React
16
+ * Server Component (it is RSC-safe by design) and is used solely to
17
+ * derive a stable per-instance `idPrefix`. The component therefore runs
18
+ * in an RSC environment without the `"use client"` directive.
16
19
  *
17
20
  * **Read-only only.** For interactive forms with `onChange`, use
18
21
  * `<SchemaComponent>` (which requires `"use client"`).
@@ -31,9 +34,9 @@ import { createElement, isValidElement, useId } from "react";
31
34
  * Server Components cannot use React context, so the resolver
32
35
  * is passed explicitly.
33
36
  */
34
- function noop() {}
35
37
  /**
36
- * Server-safe schema renderer — no hooks, no context, no state.
38
+ * Server-safe schema renderer — no context and no state. The only hook
39
+ * called is `useId()`, which is RSC-safe.
37
40
  *
38
41
  * Always renders in read-only mode. For editable forms, use
39
42
  * `<SchemaComponent>` with `"use client"`.
@@ -81,22 +84,12 @@ function SchemaView({ schema: schemaInput, ref: refInput, value, fields, meta: c
81
84
  }
82
85
  function renderFieldServer(tree, value, resolver, renderChild, path, widgets) {
83
86
  if (path.length === 0) throw new Error("renderFieldServer requires a non-empty path. Pass ROOT_PATH at the root and join children via joinPath().");
87
+ const adaptedRenderChild = (childTree, childValue, _childOnChange, pathSuffix) => renderChild(childTree, childValue, pathSuffix);
84
88
  const componentHint = tree.meta.component;
85
89
  if (typeof componentHint === "string") {
86
90
  const widget = widgets?.get(componentHint);
87
91
  if (widget !== void 0) {
88
- const wrapRenderChild = (childTree, childValue, _childOnChange, pathSuffix) => renderChild(childTree, childValue, pathSuffix);
89
- const result = widget({
90
- value,
91
- onChange: noop,
92
- readOnly: true,
93
- writeOnly: false,
94
- meta: tree.meta,
95
- constraints: tree.constraints,
96
- path,
97
- tree,
98
- renderChild: wrapRenderChild
99
- });
92
+ const result = widget(buildRenderProps(tree, value, void 0, adaptedRenderChild, path));
100
93
  if (result !== void 0 && result !== null) {
101
94
  if (isValidElement(result)) return result;
102
95
  if (typeof result === "string" || typeof result === "number") return result;
@@ -105,31 +98,7 @@ function renderFieldServer(tree, value, resolver, renderChild, path, widgets) {
105
98
  }
106
99
  const renderFn = getRenderFunction(tree.type, resolver);
107
100
  if (renderFn !== void 0) {
108
- const props = {
109
- value,
110
- onChange: noop,
111
- readOnly: true,
112
- writeOnly: false,
113
- meta: tree.meta,
114
- constraints: tree.constraints,
115
- path,
116
- tree,
117
- renderChild: (childTree, childValue, _childOnChange, pathSuffix) => renderChild(childTree, childValue, pathSuffix)
118
- };
119
- if (tree.type === "enum") props.enumValues = tree.enumValues;
120
- if (tree.type === "array" && tree.element !== void 0) props.element = tree.element;
121
- if (tree.type === "object") props.fields = tree.fields;
122
- if (tree.type === "union" || tree.type === "discriminatedUnion") props.options = tree.options;
123
- if (tree.type === "discriminatedUnion") props.discriminator = tree.discriminator;
124
- if (tree.type === "record") props.keyType = tree.keyType;
125
- if (tree.type === "record") props.valueType = tree.valueType;
126
- if (tree.type === "tuple") props.prefixItems = tree.prefixItems;
127
- if (tree.type === "conditional") props.ifClause = tree.ifClause;
128
- if (tree.type === "conditional" && tree.thenClause !== void 0) props.thenClause = tree.thenClause;
129
- if (tree.type === "conditional" && tree.elseClause !== void 0) props.elseClause = tree.elseClause;
130
- if (tree.type === "negation") props.negated = tree.negated;
131
- if (tree.type === "recursive") props.refTarget = tree.refTarget;
132
- if (tree.type === "literal") props.literalValues = tree.literalValues;
101
+ const props = buildRenderProps(tree, value, void 0, adaptedRenderChild, path);
133
102
  try {
134
103
  const result = renderFn(props);
135
104
  if (result !== void 0 && result !== null) {
@@ -1,4 +1,4 @@
1
- import { r as ComponentResolver } from "../renderer-B3s8o2B8.mjs";
1
+ import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
2
2
 
3
3
  //#region src/react/headless.d.ts
4
4
  /**
@@ -1,5 +1,5 @@
1
1
  import { M as WalkedField } from "../types-D_5ST7SS.mjs";
2
- import { l as RenderProps } from "../renderer-B3s8o2B8.mjs";
2
+ import { l as RenderProps } from "../renderer-BAGoX4AK.mjs";
3
3
  import { ReactNode } from "react";
4
4
 
5
5
  //#region src/react/headlessRenderers.d.ts
@@ -1,4 +1,5 @@
1
1
  import { isObject } from "../core/guards.mjs";
2
+ import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
2
3
  import { jsx, jsxs } from "react/jsx-runtime";
3
4
  import { isValidElement, useCallback, useEffect, useRef } from "react";
4
5
  //#region src/react/headlessRenderers.tsx
@@ -128,24 +129,27 @@ function renderString(props) {
128
129
  },
129
130
  ...ariaAttrs
130
131
  });
131
- if (props.enumValues !== void 0 && props.enumValues.length > 0) return /* @__PURE__ */ jsxs("select", {
132
- id,
133
- value: strValue,
134
- onChange: (e) => {
135
- props.onChange(e.target.value);
136
- },
137
- ...ariaAttrs,
138
- children: [/* @__PURE__ */ jsxs("option", {
139
- value: "",
140
- children: ["Select", "…"]
141
- }), props.enumValues.map((v) => {
142
- const display = v === null ? "null" : typeof v === "string" ? v : String(v);
143
- return /* @__PURE__ */ jsx("option", {
144
- value: display,
145
- children: display
146
- }, display);
147
- })]
148
- });
132
+ if (props.tree.type === "enum" && props.tree.enumValues.length > 0) {
133
+ const enumValues = props.tree.enumValues;
134
+ return /* @__PURE__ */ jsxs("select", {
135
+ id,
136
+ value: strValue,
137
+ onChange: (e) => {
138
+ props.onChange(e.target.value);
139
+ },
140
+ ...ariaAttrs,
141
+ children: [/* @__PURE__ */ jsxs("option", {
142
+ value: "",
143
+ children: ["Select", ""]
144
+ }), enumValues.map((v) => {
145
+ const display = v === null ? "null" : typeof v === "string" ? v : String(v);
146
+ return /* @__PURE__ */ jsx("option", {
147
+ value: display,
148
+ children: display
149
+ }, display);
150
+ })]
151
+ });
152
+ }
149
153
  return /* @__PURE__ */ jsx("input", {
150
154
  id,
151
155
  type: props.constraints.format === "email" ? "email" : props.constraints.format === "uri" ? "url" : "text",
@@ -225,6 +229,7 @@ function renderEnum(props) {
225
229
  });
226
230
  const ariaAttrs = {};
227
231
  if (props.tree.isOptional === false) ariaAttrs["aria-required"] = "true";
232
+ const enumValues = props.tree.type === "enum" ? props.tree.enumValues : [];
228
233
  return /* @__PURE__ */ jsxs("select", {
229
234
  id,
230
235
  value: props.writeOnly ? "" : enumValue,
@@ -235,7 +240,7 @@ function renderEnum(props) {
235
240
  children: [/* @__PURE__ */ jsxs("option", {
236
241
  value: "",
237
242
  children: ["Select", "…"]
238
- }), props.enumValues?.map((v) => {
243
+ }), enumValues.map((v) => {
239
244
  const display = v === null ? "null" : typeof v === "string" ? v : String(v);
240
245
  return /* @__PURE__ */ jsx("option", {
241
246
  value: display,
@@ -245,12 +250,10 @@ function renderEnum(props) {
245
250
  });
246
251
  }
247
252
  function renderObject(props) {
253
+ if (props.tree.type !== "object") return null;
248
254
  const obj = isObject(props.value) ? props.value : {};
249
- const fields = props.fields;
250
- if (fields === void 0) return null;
251
- const sortedEntries = Object.entries(fields).sort((a, b) => {
252
- return (typeof a[1].meta.order === "number" ? a[1].meta.order : Infinity) - (typeof b[1].meta.order === "number" ? b[1].meta.order : Infinity);
253
- });
255
+ const fields = props.tree.fields;
256
+ const sortedEntries = sortFieldsByOrder(fields);
254
257
  return /* @__PURE__ */ jsxs("fieldset", { children: [typeof props.meta.description === "string" && /* @__PURE__ */ jsx("legend", { children: props.meta.description }), sortedEntries.filter(([, field]) => field.meta.visible !== false).map(([key, field]) => {
255
258
  const childValue = obj[key];
256
259
  const childId = inputId(`${props.path}.${key}`);
@@ -312,9 +315,9 @@ function renameRecordKey(obj, oldKey, newKey) {
312
315
  return renamed;
313
316
  }
314
317
  function renderRecord(props) {
318
+ if (props.tree.type !== "record") return null;
315
319
  const obj = isObject(props.value) ? props.value : {};
316
- const valueType = props.valueType;
317
- if (valueType === void 0) return null;
320
+ const valueType = props.tree.valueType;
318
321
  const entries = Object.entries(obj);
319
322
  if (props.readOnly) {
320
323
  if (entries.length === 0) return /* @__PURE__ */ jsx("span", {
@@ -392,8 +395,9 @@ function renderRecord(props) {
392
395
  });
393
396
  }
394
397
  function renderArray(props) {
398
+ if (props.tree.type !== "array") return null;
395
399
  const arr = Array.isArray(props.value) ? props.value : [];
396
- const element = props.element;
400
+ const element = props.tree.element;
397
401
  if (element === void 0) return null;
398
402
  if (arr.length === 0) return null;
399
403
  return /* @__PURE__ */ jsx("div", {
@@ -410,7 +414,7 @@ function renderArray(props) {
410
414
  });
411
415
  }
412
416
  function renderUnion(props) {
413
- const options = props.options;
417
+ const options = props.tree.type === "union" || props.tree.type === "discriminatedUnion" ? props.tree.options : void 0;
414
418
  if (options === void 0 || options.length === 0) {
415
419
  if (props.value === void 0 || props.value === null) return /* @__PURE__ */ jsx("span", { children: "—" });
416
420
  return /* @__PURE__ */ jsx("span", { children: JSON.stringify(props.value) });
@@ -422,8 +426,8 @@ function renderUnion(props) {
422
426
  return /* @__PURE__ */ jsx("span", { children: "—" });
423
427
  }
424
428
  function renderDiscriminatedUnion(props) {
425
- const options = props.options;
426
- const discriminator = props.discriminator;
429
+ const options = props.tree.type === "discriminatedUnion" ? props.tree.options : void 0;
430
+ const discriminator = props.tree.type === "discriminatedUnion" ? props.tree.discriminator : void 0;
427
431
  if (options === void 0 || options.length === 0) {
428
432
  if (props.value === void 0 || props.value === null) return /* @__PURE__ */ jsx("span", { children: "—" });
429
433
  return /* @__PURE__ */ jsx("span", { children: JSON.stringify(props.value) });
@@ -496,7 +500,7 @@ function DiscriminatedUnionTabs({ options, optionLabels, activeIndex, panelId, d
496
500
  }, [
497
501
  optionLabels,
498
502
  discKey,
499
- props
503
+ props.onChange
500
504
  ]);
501
505
  const wrapIndex = useCallback((index) => (index % options.length + options.length) % options.length, [options.length]);
502
506
  const handleKeyDown = useCallback((e) => {
@@ -537,6 +541,7 @@ function DiscriminatedUnionTabs({ options, optionLabels, activeIndex, panelId, d
537
541
  },
538
542
  type: "button",
539
543
  role: "tab",
544
+ id: `${panelId}-tab-${String(i)}`,
540
545
  "aria-selected": i === activeIndex ? "true" : void 0,
541
546
  "aria-controls": `${panelId}-panel`,
542
547
  tabIndex: i === activeIndex ? 0 : -1,
@@ -583,7 +588,7 @@ function renderFile(props) {
583
588
  });
584
589
  }
585
590
  function renderRecursive(props) {
586
- const refTarget = props.refTarget ?? "";
591
+ const refTarget = props.tree.type === "recursive" ? props.tree.refTarget : "";
587
592
  return /* @__PURE__ */ jsx("fieldset", { children: /* @__PURE__ */ jsxs("em", { children: [
588
593
  "↻ ",
589
594
  typeof props.meta.description === "string" ? props.meta.description : refTarget,
@@ -1,4 +1,4 @@
1
- import { i as DiagnosticsOptions } from "./diagnostics-DzbZmcLI.mjs";
1
+ import { i as DiagnosticsOptions } from "./diagnostics-BYk63jsC.mjs";
2
2
 
3
3
  //#region src/core/ref.d.ts
4
4
  /**
@@ -13,6 +13,13 @@ type AllConstraints = StringConstraints & NumberConstraints & ArrayConstraints &
13
13
  /**
14
14
  * Properties available on every schema field, regardless of rendering target.
15
15
  * Both React and HTML renderers receive these.
16
+ *
17
+ * Per-type schema data — enum values, object fields, array element schema,
18
+ * union options, record key/value types, tuple `prefixItems`, conditional
19
+ * if/then/else clauses, negation `negated`, recursive `refTarget`, literal
20
+ * values — lives on the discriminated `tree`. Renderers narrow on
21
+ * `tree.type` and read from the matching variant; there are no duplicate
22
+ * sibling fields on these props.
16
23
  */
17
24
  interface BaseFieldProps {
18
25
  /** Current field value. */
@@ -27,31 +34,6 @@ interface BaseFieldProps {
27
34
  constraints: AllConstraints;
28
35
  /** Dot-separated path from root (e.g. "address.city"). */
29
36
  path: string;
30
- /** For enums: the allowed values. */
31
- enumValues?: (string | number | boolean | null)[];
32
- /** For arrays: the element schema. */
33
- element?: WalkedField;
34
- /** For tuples: positional element schemas from prefixItems. */
35
- prefixItems?: WalkedField[];
36
- /** For conditionals: the if/then/else sub-schemas. */
37
- ifClause?: WalkedField;
38
- thenClause?: WalkedField;
39
- elseClause?: WalkedField;
40
- /** For negations: the negated sub-schema. */
41
- negated?: WalkedField;
42
- /** For recursive fields: the $ref string that would create the cycle. */
43
- refTarget?: string;
44
- /** For objects: map of field name → WalkedField. */
45
- fields?: Record<string, WalkedField>;
46
- /** For unions: the option schemas. */
47
- options?: WalkedField[];
48
- /** For discriminated unions: the discriminator key. */
49
- discriminator?: string;
50
- /** For records: key and value schemas. */
51
- keyType?: WalkedField;
52
- valueType?: WalkedField;
53
- /** For literals: the literal value(s). */
54
- literalValues?: (string | number | boolean | null)[];
55
37
  /** Example values from the schema's `examples` keyword. */
56
38
  examples?: unknown[];
57
39
  /** Walked field tree for recursive rendering. */
@@ -99,6 +81,18 @@ interface HtmlRenderProps extends BaseFieldProps {
99
81
  */
100
82
  renderChild: (tree: WalkedField, value: unknown, pathSuffix?: string) => string;
101
83
  }
84
+ /**
85
+ * Build the `RenderProps` object handed to a resolver render function or a
86
+ * widget. Used by both the server-side `<SchemaView>` (which has no
87
+ * `onChange`) and the client-side `<SchemaComponent>` (which threads an
88
+ * `onChange` callback).
89
+ *
90
+ * When `onChange` is `undefined` the caller is rendering in read-only mode:
91
+ * a noop `onChange` is wired up, `readOnly` is forced to `true`, and
92
+ * `writeOnly` is forced to `false`. Otherwise the editability is taken
93
+ * from `tree.editability`.
94
+ */
95
+ declare function buildRenderProps(tree: WalkedField, value: unknown, onChange: ((next: unknown) => void) | undefined, renderChild: RenderProps["renderChild"], path: string): RenderProps;
102
96
  type RenderFunction = (props: RenderProps) => unknown;
103
97
  interface ComponentResolver {
104
98
  string?: RenderFunction;
@@ -166,4 +160,4 @@ declare function mergeResolvers(user: ComponentResolver, fallback: ComponentReso
166
160
  */
167
161
  declare function mergeHtmlResolvers(user: HtmlResolver, fallback: HtmlResolver): HtmlResolver;
168
162
  //#endregion
169
- export { HtmlRenderProps as a, RenderFunction as c, getRenderFunction as d, mergeHtmlResolvers as f, HtmlRenderFunction as i, RenderProps as l, typeToKey as m, BaseFieldProps as n, HtmlResolver as o, mergeResolvers as p, ComponentResolver as r, RESOLVER_KEYS as s, AllConstraints as t, getHtmlRenderFn as u };
163
+ export { HtmlRenderProps as a, RenderFunction as c, getHtmlRenderFn as d, getRenderFunction as f, typeToKey as h, HtmlRenderFunction as i, RenderProps as l, mergeResolvers as m, BaseFieldProps as n, HtmlResolver as o, mergeHtmlResolvers as p, ComponentResolver as r, RESOLVER_KEYS as s, AllConstraints as t, buildRenderProps as u };
@@ -1,4 +1,4 @@
1
- import { r as ComponentResolver } from "../renderer-B3s8o2B8.mjs";
1
+ import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
2
2
 
3
3
  //#region src/themes/mantine.d.ts
4
4
  /**
@@ -1,4 +1,5 @@
1
1
  import { isObject } from "../core/guards.mjs";
2
+ import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
2
3
  import { inputId, toReactNode } from "../react/headlessRenderers.mjs";
3
4
  import { headlessResolver } from "../react/headless.mjs";
4
5
  import { jsx } from "react/jsx-runtime";
@@ -103,6 +104,7 @@ function renderEnumInput(props) {
103
104
  id,
104
105
  children: enumValue || "—"
105
106
  });
107
+ const enumValues = props.tree.type === "enum" ? props.tree.enumValues : [];
106
108
  return /* @__PURE__ */ jsx(MantineSelect, {
107
109
  id,
108
110
  label,
@@ -110,19 +112,19 @@ function renderEnumInput(props) {
110
112
  onChange: (v) => {
111
113
  if (typeof v === "string") props.onChange(v);
112
114
  },
113
- data: (props.enumValues ?? []).map((v) => ({
115
+ data: enumValues.map((v) => ({
114
116
  value: v,
115
117
  label: v
116
118
  }))
117
119
  });
118
120
  }
119
121
  function renderObjectContainer(props) {
120
- const fields = props.fields;
121
- if (fields === void 0) return null;
122
+ if (props.tree.type !== "object") return null;
123
+ const fields = props.tree.fields;
122
124
  const obj = isObject(props.value) ? props.value : {};
123
125
  return /* @__PURE__ */ jsx(MantineFieldset, {
124
126
  legend: getLabel(props),
125
- children: Object.entries(fields).filter(([, field]) => field.meta.visible !== false).map(([key, field]) => {
127
+ children: sortFieldsByOrder(fields).filter(([, field]) => field.meta.visible !== false).map(([key, field]) => {
126
128
  const childValue = obj[key];
127
129
  const childOnChange = (v) => {
128
130
  const updated = {};
@@ -1,4 +1,4 @@
1
- import { r as ComponentResolver } from "../renderer-B3s8o2B8.mjs";
1
+ import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
2
2
 
3
3
  //#region src/themes/mui.d.ts
4
4
  /**
@@ -1,4 +1,5 @@
1
1
  import { isObject } from "../core/guards.mjs";
2
+ import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
2
3
  import { inputId, toReactNode } from "../react/headlessRenderers.mjs";
3
4
  import { headlessResolver } from "../react/headless.mjs";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -117,15 +118,15 @@ function renderEnumInput(props) {
117
118
  children: [/* @__PURE__ */ jsxs(MuiMenuItem, {
118
119
  value: "",
119
120
  children: ["Select", "…"]
120
- }), (props.enumValues ?? []).map((v) => /* @__PURE__ */ jsx(MuiMenuItem, {
121
+ }), (props.tree.type === "enum" ? props.tree.enumValues : []).map((v) => /* @__PURE__ */ jsx(MuiMenuItem, {
121
122
  value: v,
122
123
  children: v
123
124
  }, v))]
124
125
  });
125
126
  }
126
127
  function renderObjectContainer(props) {
127
- const fields = props.fields;
128
- if (fields === void 0) return null;
128
+ if (props.tree.type !== "object") return null;
129
+ const fields = props.tree.fields;
129
130
  const obj = isObject(props.value) ? props.value : {};
130
131
  return /* @__PURE__ */ jsxs(MuiBox, {
131
132
  sx: {
@@ -136,7 +137,7 @@ function renderObjectContainer(props) {
136
137
  children: [typeof props.meta.description === "string" && /* @__PURE__ */ jsx(MuiTypography, {
137
138
  variant: "h6",
138
139
  children: props.meta.description
139
- }), Object.entries(fields).map(([key, field]) => {
140
+ }), sortFieldsByOrder(fields).map(([key, field]) => {
140
141
  const childValue = obj[key];
141
142
  const childOnChange = (v) => {
142
143
  const updated = {};
@@ -150,7 +151,8 @@ function renderObjectContainer(props) {
150
151
  }
151
152
  function renderArrayContainer(props) {
152
153
  const arr = Array.isArray(props.value) ? props.value : [];
153
- const element = props.element;
154
+ if (props.tree.type !== "array") return null;
155
+ const element = props.tree.element;
154
156
  if (element === void 0) return null;
155
157
  return /* @__PURE__ */ jsx(MuiBox, {
156
158
  sx: {
@@ -1,4 +1,4 @@
1
- import { r as ComponentResolver } from "../renderer-B3s8o2B8.mjs";
1
+ import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
2
2
 
3
3
  //#region src/themes/radix.d.ts
4
4
  /**
@@ -1,4 +1,5 @@
1
1
  import { isObject } from "../core/guards.mjs";
2
+ import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
2
3
  import { inputId, toReactNode } from "../react/headlessRenderers.mjs";
3
4
  import { headlessResolver } from "../react/headless.mjs";
4
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -142,15 +143,15 @@ function renderEnumInput(props) {
142
143
  children: [/* @__PURE__ */ jsx(RadixSelectTrigger, {
143
144
  id,
144
145
  mt: "1"
145
- }), /* @__PURE__ */ jsx(RadixSelectContent, { children: (props.enumValues ?? []).map((value) => /* @__PURE__ */ jsx(RadixSelectItem, {
146
+ }), /* @__PURE__ */ jsx(RadixSelectContent, { children: (props.tree.type === "enum" ? props.tree.enumValues : []).map((value) => /* @__PURE__ */ jsx(RadixSelectItem, {
146
147
  value,
147
148
  children: value
148
149
  }, value)) })]
149
150
  })] });
150
151
  }
151
152
  function renderObjectContainer(props) {
152
- const fields = props.fields;
153
- if (fields === void 0) return null;
153
+ if (props.tree.type !== "object") return null;
154
+ const fields = props.tree.fields;
154
155
  const obj = isObject(props.value) ? props.value : {};
155
156
  return /* @__PURE__ */ jsxs(RadixBox, { children: [typeof props.meta.description === "string" && /* @__PURE__ */ jsx(RadixText, {
156
157
  as: "div",
@@ -161,7 +162,7 @@ function renderObjectContainer(props) {
161
162
  }), /* @__PURE__ */ jsx(RadixFlex, {
162
163
  direction: "column",
163
164
  gap: "3",
164
- children: Object.entries(fields).filter(([, field]) => field.meta.visible !== false).map(([key, field]) => {
165
+ children: sortFieldsByOrder(fields).filter(([, field]) => field.meta.visible !== false).map(([key, field]) => {
165
166
  const childValue = obj[key];
166
167
  const childOnChange = (v) => {
167
168
  const updated = {};
@@ -1,4 +1,4 @@
1
- import { r as ComponentResolver } from "../renderer-B3s8o2B8.mjs";
1
+ import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
2
2
 
3
3
  //#region src/themes/shadcn.d.ts
4
4
  declare const shadcnResolver: ComponentResolver;
@@ -1,4 +1,5 @@
1
1
  import { toRecord } from "../core/guards.mjs";
2
+ import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
2
3
  import { inputId, toReactNode } from "../react/headlessRenderers.mjs";
3
4
  import { headlessResolver } from "../react/headless.mjs";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -94,15 +95,15 @@ function renderBooleanInput(props) {
94
95
  });
95
96
  }
96
97
  function renderObjectContainer(props) {
97
- const fields = props.fields;
98
- if (fields === void 0) return null;
98
+ if (props.tree.type !== "object") return null;
99
+ const fields = props.tree.fields;
99
100
  const obj = typeof props.value === "object" && props.value !== null && !Array.isArray(props.value) ? props.value : {};
100
101
  return /* @__PURE__ */ jsxs("div", {
101
102
  className: "space-y-4",
102
103
  children: [typeof props.meta.description === "string" && /* @__PURE__ */ jsx("h3", {
103
104
  className: "text-lg font-medium",
104
105
  children: props.meta.description
105
- }), Object.entries(fields).map(([key, field]) => {
106
+ }), sortFieldsByOrder(fields).map(([key, field]) => {
106
107
  const childValue = toRecord(obj)[key];
107
108
  const childId = inputId(`${props.path}.${key}`);
108
109
  const childOnChange = (v) => {
@@ -124,7 +125,8 @@ function renderObjectContainer(props) {
124
125
  }
125
126
  function renderArrayContainer(props) {
126
127
  const arr = Array.isArray(props.value) ? props.value : [];
127
- const element = props.element;
128
+ if (props.tree.type !== "array") return null;
129
+ const element = props.tree.element;
128
130
  if (element === void 0) return null;
129
131
  return /* @__PURE__ */ jsx("div", {
130
132
  className: "space-y-2",
@@ -157,13 +159,13 @@ function renderEnumInput(props) {
157
159
  children: [/* @__PURE__ */ jsxs("option", {
158
160
  value: "",
159
161
  children: ["Select", "…"]
160
- }), props.enumValues?.map((v) => {
162
+ }), props.tree.type === "enum" ? props.tree.enumValues.map((v) => {
161
163
  const display = v === null ? "null" : typeof v === "string" ? v : String(v);
162
164
  return /* @__PURE__ */ jsx("option", {
163
165
  value: display,
164
166
  children: display
165
167
  }, display);
166
- })]
168
+ }) : null]
167
169
  });
168
170
  }
169
171
  function buildResolver() {