schema-components 1.18.0 → 1.19.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/core/adapter.d.mts +1 -1
- package/dist/core/adapter.mjs +77 -14
- package/dist/core/constraints.d.mts +1 -1
- package/dist/core/diagnostics.d.mts +1 -1
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/errors.mjs +7 -1
- package/dist/core/fieldOrder.d.mts +10 -0
- package/dist/core/fieldOrder.mjs +12 -0
- package/dist/core/formats.mjs +9 -1
- package/dist/core/merge.d.mts +1 -1
- package/dist/core/merge.mjs +30 -2
- package/dist/core/normalise.d.mts +38 -5
- package/dist/core/normalise.mjs +2 -2
- package/dist/core/openapi30.d.mts +33 -4
- package/dist/core/openapi30.mjs +2 -2
- package/dist/core/ref.d.mts +1 -1
- package/dist/core/renderer.d.mts +1 -1
- package/dist/core/renderer.mjs +7 -21
- package/dist/core/swagger2.d.mts +1 -1
- package/dist/core/swagger2.mjs +1 -1
- package/dist/core/version.d.mts +2 -2
- package/dist/core/version.mjs +19 -9
- package/dist/core/walkBuilders.d.mts +2 -2
- package/dist/{diagnostics-BYk63jsC.d.mts → diagnostics-VgEKI_Ct.d.mts} +1 -1
- package/dist/{errors-C5zRC2PU.d.mts → errors-CnGjT1cg.d.mts} +7 -2
- package/dist/html/a11y.d.mts +1 -1
- package/dist/html/renderToHtml.d.mts +1 -1
- package/dist/html/renderToHtml.mjs +13 -30
- package/dist/html/renderToHtmlStream.d.mts +1 -1
- package/dist/html/renderers.d.mts +1 -1
- package/dist/html/renderers.mjs +56 -23
- package/dist/html/streamRenderers.d.mts +1 -1
- package/dist/html/streamRenderers.mjs +10 -21
- package/dist/{normalise-tL9FckAk.mjs → normalise-C0ofw3W6.mjs} +418 -97
- package/dist/openapi/ApiSecurity.mjs +1 -1
- package/dist/openapi/bundle.mjs +1 -0
- package/dist/openapi/components.mjs +6 -2
- package/dist/openapi/parser.d.mts +2 -2
- package/dist/openapi/parser.mjs +8 -5
- package/dist/openapi/resolve.d.mts +6 -5
- package/dist/openapi/resolve.mjs +7 -6
- package/dist/react/SchemaComponent.d.mts +4 -4
- package/dist/react/SchemaComponent.mjs +4 -14
- package/dist/react/SchemaView.d.mts +2 -2
- package/dist/react/SchemaView.mjs +2 -1
- package/dist/react/headless.d.mts +7 -1
- package/dist/react/headless.mjs +13 -1
- package/dist/react/headlessRenderers.d.mts +53 -2
- package/dist/react/headlessRenderers.mjs +175 -33
- package/dist/{ref-Ckt5liZs.d.mts → ref-Bb43ZURY.d.mts} +1 -1
- package/dist/{renderer-DXo-rXHJ.d.mts → renderer-BQqiXUYP.d.mts} +15 -32
- package/dist/themes/mantine.d.mts +1 -1
- package/dist/themes/mantine.mjs +2 -1
- package/dist/themes/mui.d.mts +1 -1
- package/dist/themes/mui.mjs +3 -2
- package/dist/themes/radix.d.mts +1 -1
- package/dist/themes/radix.mjs +2 -1
- package/dist/themes/shadcn.d.mts +1 -1
- package/dist/themes/shadcn.mjs +2 -1
- package/dist/{version-B5NV-35j.d.mts → version-XNH7PRGP.d.mts} +8 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isObject } from "../core/guards.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
|
|
3
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { isValidElement, useCallback, useEffect, useRef } from "react";
|
|
4
5
|
//#region src/react/headlessRenderers.tsx
|
|
5
6
|
/**
|
|
6
7
|
* Headless renderer functions — one per schema type.
|
|
@@ -128,24 +129,27 @@ function renderString(props) {
|
|
|
128
129
|
},
|
|
129
130
|
...ariaAttrs
|
|
130
131
|
});
|
|
131
|
-
if (props.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
children: ["
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
}),
|
|
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
|
-
|
|
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) });
|
|
@@ -584,13 +588,151 @@ function renderFile(props) {
|
|
|
584
588
|
});
|
|
585
589
|
}
|
|
586
590
|
function renderRecursive(props) {
|
|
587
|
-
const refTarget = props.refTarget
|
|
591
|
+
const refTarget = props.tree.type === "recursive" ? props.tree.refTarget : "";
|
|
588
592
|
return /* @__PURE__ */ jsx("fieldset", { children: /* @__PURE__ */ jsxs("em", { children: [
|
|
589
593
|
"↻ ",
|
|
590
594
|
typeof props.meta.description === "string" ? props.meta.description : refTarget,
|
|
591
595
|
" (recursive)"
|
|
592
596
|
] }) });
|
|
593
597
|
}
|
|
598
|
+
/**
|
|
599
|
+
* Render a literal field — `z.literal("a")` or `{ const: 5 }`.
|
|
600
|
+
*
|
|
601
|
+
* Literals are non-editable by nature (the value is fixed at the schema
|
|
602
|
+
* level), so both read-only and editable modes display the literal value(s).
|
|
603
|
+
* Multiple literals (`z.literal(["a", "b"])`) render comma-separated.
|
|
604
|
+
*/
|
|
605
|
+
function renderLiteral(props) {
|
|
606
|
+
const id = inputId(props.path);
|
|
607
|
+
if (props.tree.type !== "literal") return null;
|
|
608
|
+
const values = props.tree.literalValues;
|
|
609
|
+
if (values.length === 0) return /* @__PURE__ */ jsx("span", {
|
|
610
|
+
id,
|
|
611
|
+
"aria-readonly": "true",
|
|
612
|
+
children: "—"
|
|
613
|
+
});
|
|
614
|
+
return /* @__PURE__ */ jsx("span", {
|
|
615
|
+
id,
|
|
616
|
+
"aria-readonly": "true",
|
|
617
|
+
children: values.map((v) => v === null ? "null" : String(v)).join(", ")
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Render a null field — `z.null()` or `{ type: "null" }`.
|
|
622
|
+
*
|
|
623
|
+
* The only valid value is `null`, so render an em-dash placeholder
|
|
624
|
+
* regardless of mode. There is nothing the user can usefully change.
|
|
625
|
+
*/
|
|
626
|
+
function renderNull(props) {
|
|
627
|
+
return /* @__PURE__ */ jsx("span", {
|
|
628
|
+
id: inputId(props.path),
|
|
629
|
+
"aria-readonly": "true",
|
|
630
|
+
children: "—"
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Render a never field — `z.never()` or `{ not: {} }` / `false` schema.
|
|
635
|
+
*
|
|
636
|
+
* `never` indicates a position that cannot hold any value. We render a
|
|
637
|
+
* visible placeholder rather than throwing because some valid schemas
|
|
638
|
+
* intentionally contain `never` branches (e.g. exhaustive discriminated
|
|
639
|
+
* unions), and a runtime crash on render would be worse than a visible
|
|
640
|
+
* indicator.
|
|
641
|
+
*/
|
|
642
|
+
function renderNever(props) {
|
|
643
|
+
return /* @__PURE__ */ jsx("span", {
|
|
644
|
+
id: inputId(props.path),
|
|
645
|
+
"aria-readonly": "true",
|
|
646
|
+
className: "sc-never",
|
|
647
|
+
children: /* @__PURE__ */ jsx("em", { children: "never matches" })
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Render a tuple field — `z.tuple([z.string(), z.number()])` or
|
|
652
|
+
* `{ prefixItems: [...] }`.
|
|
653
|
+
*
|
|
654
|
+
* Positional rendering: each `prefixItems` entry is rendered at its index.
|
|
655
|
+
* The structural index (e.g. `[0]`) is passed as the path suffix so
|
|
656
|
+
* children get unique ids and labels.
|
|
657
|
+
*/
|
|
658
|
+
function renderTuple(props) {
|
|
659
|
+
if (props.tree.type !== "tuple") return null;
|
|
660
|
+
const prefixItems = props.tree.prefixItems;
|
|
661
|
+
if (prefixItems.length === 0) return null;
|
|
662
|
+
const arr = Array.isArray(props.value) ? props.value : [];
|
|
663
|
+
return /* @__PURE__ */ jsx("div", {
|
|
664
|
+
role: "group",
|
|
665
|
+
"aria-label": props.meta.description ?? void 0,
|
|
666
|
+
children: prefixItems.map((element, i) => {
|
|
667
|
+
const itemValue = arr[i];
|
|
668
|
+
const childOnChange = (v) => {
|
|
669
|
+
const next = arr.slice();
|
|
670
|
+
next[i] = v;
|
|
671
|
+
props.onChange(next);
|
|
672
|
+
};
|
|
673
|
+
return /* @__PURE__ */ jsx("div", { children: toReactNode(props.renderChild(element, itemValue, childOnChange, `[${String(i)}]`)) }, String(i));
|
|
674
|
+
})
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Render a conditional field — JSON Schema `if`/`then`/`else`.
|
|
679
|
+
*
|
|
680
|
+
* Conditional schemas describe constraints rather than a single value
|
|
681
|
+
* shape, so the renderer surfaces each clause as a labelled fieldset.
|
|
682
|
+
* This mirrors the HTML renderer's annotation approach and gives a
|
|
683
|
+
* predictable structure for theme adapters that want to override it.
|
|
684
|
+
*/
|
|
685
|
+
function renderConditional(props) {
|
|
686
|
+
if (props.tree.type !== "conditional") return null;
|
|
687
|
+
const { ifClause, thenClause, elseClause } = props.tree;
|
|
688
|
+
return /* @__PURE__ */ jsxs("fieldset", {
|
|
689
|
+
className: "sc-conditional",
|
|
690
|
+
children: [
|
|
691
|
+
/* @__PURE__ */ jsxs("div", {
|
|
692
|
+
className: "sc-conditional-if",
|
|
693
|
+
children: [
|
|
694
|
+
/* @__PURE__ */ jsx("strong", { children: "if:" }),
|
|
695
|
+
" ",
|
|
696
|
+
toReactNode(props.renderChild(ifClause, props.value, props.onChange))
|
|
697
|
+
]
|
|
698
|
+
}),
|
|
699
|
+
thenClause !== void 0 && /* @__PURE__ */ jsxs("div", {
|
|
700
|
+
className: "sc-conditional-then",
|
|
701
|
+
children: [
|
|
702
|
+
/* @__PURE__ */ jsx("strong", { children: "then:" }),
|
|
703
|
+
" ",
|
|
704
|
+
toReactNode(props.renderChild(thenClause, props.value, props.onChange))
|
|
705
|
+
]
|
|
706
|
+
}),
|
|
707
|
+
elseClause !== void 0 && /* @__PURE__ */ jsxs("div", {
|
|
708
|
+
className: "sc-conditional-else",
|
|
709
|
+
children: [
|
|
710
|
+
/* @__PURE__ */ jsx("strong", { children: "else:" }),
|
|
711
|
+
" ",
|
|
712
|
+
toReactNode(props.renderChild(elseClause, props.value, props.onChange))
|
|
713
|
+
]
|
|
714
|
+
})
|
|
715
|
+
]
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Render a negation field — JSON Schema `{ not: { ... } }`.
|
|
720
|
+
*
|
|
721
|
+
* Negation describes a constraint ("value must NOT match this schema")
|
|
722
|
+
* rather than a value shape. The renderer surfaces the negated schema
|
|
723
|
+
* beneath an explanatory preamble.
|
|
724
|
+
*/
|
|
725
|
+
function renderNegation(props) {
|
|
726
|
+
if (props.tree.type !== "negation") return null;
|
|
727
|
+
return /* @__PURE__ */ jsxs("fieldset", {
|
|
728
|
+
className: "sc-negation",
|
|
729
|
+
children: [
|
|
730
|
+
/* @__PURE__ */ jsx("strong", { children: "Must NOT match:" }),
|
|
731
|
+
" ",
|
|
732
|
+
toReactNode(props.renderChild(props.tree.negated, props.value, props.onChange))
|
|
733
|
+
]
|
|
734
|
+
});
|
|
735
|
+
}
|
|
594
736
|
function renderUnknown(props) {
|
|
595
737
|
const id = inputId(props.path);
|
|
596
738
|
if (props.readOnly) {
|
|
@@ -623,4 +765,4 @@ function matchUnionOption(options, value) {
|
|
|
623
765
|
if (typeof value === "object" && value !== null) return options.find((o) => o.type === "object");
|
|
624
766
|
}
|
|
625
767
|
//#endregion
|
|
626
|
-
export { defaultRecordValue, discriminatedUnionValueForTab, inputId, nextRecordKey, renameRecordKey, renderArray, renderBoolean, renderDiscriminatedUnion, renderEnum, renderFile, renderNumber, renderObject, renderRecord, renderRecursive, renderString, renderUnion, renderUnknown, toReactNode };
|
|
768
|
+
export { defaultRecordValue, discriminatedUnionValueForTab, inputId, nextRecordKey, renameRecordKey, renderArray, renderBoolean, renderConditional, renderDiscriminatedUnion, renderEnum, renderFile, renderLiteral, renderNegation, renderNever, renderNull, renderNumber, renderObject, renderRecord, renderRecursive, renderString, renderTuple, renderUnion, renderUnknown, toReactNode };
|
|
@@ -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. */
|
|
@@ -109,11 +91,6 @@ interface HtmlRenderProps extends BaseFieldProps {
|
|
|
109
91
|
* a noop `onChange` is wired up, `readOnly` is forced to `true`, and
|
|
110
92
|
* `writeOnly` is forced to `false`. Otherwise the editability is taken
|
|
111
93
|
* from `tree.editability`.
|
|
112
|
-
*
|
|
113
|
-
* The duplicate sibling fields (`enumValues`, `element`, `fields`, etc.)
|
|
114
|
-
* are populated for backwards compatibility with renderers that have not
|
|
115
|
-
* yet migrated to reading from `tree` directly. New renderers should
|
|
116
|
-
* narrow on `tree.type` and read from `tree`.
|
|
117
94
|
*/
|
|
118
95
|
declare function buildRenderProps(tree: WalkedField, value: unknown, onChange: ((next: unknown) => void) | undefined, renderChild: RenderProps["renderChild"], path: string): RenderProps;
|
|
119
96
|
type RenderFunction = (props: RenderProps) => unknown;
|
|
@@ -121,6 +98,7 @@ interface ComponentResolver {
|
|
|
121
98
|
string?: RenderFunction;
|
|
122
99
|
number?: RenderFunction;
|
|
123
100
|
boolean?: RenderFunction;
|
|
101
|
+
null?: RenderFunction;
|
|
124
102
|
enum?: RenderFunction;
|
|
125
103
|
object?: RenderFunction;
|
|
126
104
|
array?: RenderFunction;
|
|
@@ -133,6 +111,7 @@ interface ComponentResolver {
|
|
|
133
111
|
recursive?: RenderFunction;
|
|
134
112
|
literal?: RenderFunction;
|
|
135
113
|
file?: RenderFunction;
|
|
114
|
+
never?: RenderFunction;
|
|
136
115
|
unknown?: RenderFunction;
|
|
137
116
|
}
|
|
138
117
|
/** An HTML render function returns a string. */
|
|
@@ -145,6 +124,7 @@ interface HtmlResolver {
|
|
|
145
124
|
string?: HtmlRenderFunction;
|
|
146
125
|
number?: HtmlRenderFunction;
|
|
147
126
|
boolean?: HtmlRenderFunction;
|
|
127
|
+
null?: HtmlRenderFunction;
|
|
148
128
|
enum?: HtmlRenderFunction;
|
|
149
129
|
object?: HtmlRenderFunction;
|
|
150
130
|
array?: HtmlRenderFunction;
|
|
@@ -157,13 +137,16 @@ interface HtmlResolver {
|
|
|
157
137
|
recursive?: HtmlRenderFunction;
|
|
158
138
|
literal?: HtmlRenderFunction;
|
|
159
139
|
file?: HtmlRenderFunction;
|
|
140
|
+
never?: HtmlRenderFunction;
|
|
160
141
|
unknown?: HtmlRenderFunction;
|
|
161
142
|
}
|
|
162
|
-
declare const RESOLVER_KEYS: readonly ["string", "number", "boolean", "enum", "object", "array", "tuple", "record", "union", "discriminatedUnion", "conditional", "negation", "recursive", "literal", "file", "unknown"];
|
|
143
|
+
declare const RESOLVER_KEYS: readonly ["string", "number", "boolean", "null", "enum", "object", "array", "tuple", "record", "union", "discriminatedUnion", "conditional", "negation", "recursive", "literal", "file", "never", "unknown"];
|
|
163
144
|
type ResolverKey = (typeof RESOLVER_KEYS)[number];
|
|
164
145
|
/**
|
|
165
146
|
* Map a schema type to the resolver key that handles it.
|
|
166
|
-
*
|
|
147
|
+
* Every WalkedField variant has a direct resolver key — exhaustive switch
|
|
148
|
+
* ensures new variants surface as a type error rather than silently
|
|
149
|
+
* falling through to "unknown".
|
|
167
150
|
*/
|
|
168
151
|
declare function typeToKey(type: WalkedField["type"]): ResolverKey;
|
|
169
152
|
/**
|
package/dist/themes/mantine.mjs
CHANGED
|
@@ -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";
|
|
@@ -123,7 +124,7 @@ function renderObjectContainer(props) {
|
|
|
123
124
|
const obj = isObject(props.value) ? props.value : {};
|
|
124
125
|
return /* @__PURE__ */ jsx(MantineFieldset, {
|
|
125
126
|
legend: getLabel(props),
|
|
126
|
-
children:
|
|
127
|
+
children: sortFieldsByOrder(fields).filter(([, field]) => field.meta.visible !== false).map(([key, field]) => {
|
|
127
128
|
const childValue = obj[key];
|
|
128
129
|
const childOnChange = (v) => {
|
|
129
130
|
const updated = {};
|
package/dist/themes/mui.d.mts
CHANGED
package/dist/themes/mui.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
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
|
-
import { isValidElement } from "react";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { isValidElement } from "react";
|
|
6
7
|
//#region src/themes/mui.tsx
|
|
7
8
|
function ariaRequired(tree) {
|
|
8
9
|
return { required: tree.isOptional === false };
|
|
@@ -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
|
-
}),
|
|
140
|
+
}), sortFieldsByOrder(fields).map(([key, field]) => {
|
|
140
141
|
const childValue = obj[key];
|
|
141
142
|
const childOnChange = (v) => {
|
|
142
143
|
const updated = {};
|
package/dist/themes/radix.d.mts
CHANGED
package/dist/themes/radix.mjs
CHANGED
|
@@ -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";
|
|
@@ -161,7 +162,7 @@ function renderObjectContainer(props) {
|
|
|
161
162
|
}), /* @__PURE__ */ jsx(RadixFlex, {
|
|
162
163
|
direction: "column",
|
|
163
164
|
gap: "3",
|
|
164
|
-
children:
|
|
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 = {};
|
package/dist/themes/shadcn.d.mts
CHANGED
package/dist/themes/shadcn.mjs
CHANGED
|
@@ -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";
|
|
@@ -102,7 +103,7 @@ function renderObjectContainer(props) {
|
|
|
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
|
-
}),
|
|
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) => {
|
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
* before the walker processes the schema.
|
|
8
8
|
*/
|
|
9
9
|
type JsonSchemaDraft = "draft-04" | "draft-06" | "draft-07" | "draft-2019-09" | "draft-2020-12";
|
|
10
|
+
/**
|
|
11
|
+
* Match a `$schema` URI string to a known draft. Returns `undefined`
|
|
12
|
+
* when the URI matches none of the documented Draft 04 – Draft 2020-12
|
|
13
|
+
* schema URIs (including the known prefix patterns) — callers can use
|
|
14
|
+
* this to distinguish an authoritative match from a silent fallback.
|
|
15
|
+
*/
|
|
16
|
+
declare function matchJsonSchemaDraftUri(uri: string): JsonSchemaDraft | undefined;
|
|
10
17
|
/**
|
|
11
18
|
* Detect the JSON Schema draft version from a schema's `$schema` URI.
|
|
12
19
|
* When `$schema` is absent, uses heuristic keyword detection via
|
|
@@ -66,4 +73,4 @@ declare function isOpenApi31(version: OpenApiVersionInfo): boolean;
|
|
|
66
73
|
*/
|
|
67
74
|
declare function isSwagger2(version: OpenApiVersionInfo): boolean;
|
|
68
75
|
//#endregion
|
|
69
|
-
export { detectOpenApiVersion as a, isOpenApi30 as c, detectJsonSchemaDraft as i, isOpenApi31 as l, JsonSchemaDraft as n, inferJsonSchemaDraft as o, OpenApiVersionInfo as r, inferJsonSchemaDraftWithReason as s, InferredDraft as t, isSwagger2 as u };
|
|
76
|
+
export { detectOpenApiVersion as a, isOpenApi30 as c, matchJsonSchemaDraftUri as d, detectJsonSchemaDraft as i, isOpenApi31 as l, JsonSchemaDraft as n, inferJsonSchemaDraft as o, OpenApiVersionInfo as r, inferJsonSchemaDraftWithReason as s, InferredDraft as t, isSwagger2 as u };
|