schema-components 1.18.1 → 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.
Files changed (49) hide show
  1. package/dist/core/adapter.d.mts +1 -1
  2. package/dist/core/adapter.mjs +77 -14
  3. package/dist/core/constraints.d.mts +1 -1
  4. package/dist/core/diagnostics.d.mts +1 -1
  5. package/dist/core/errors.d.mts +1 -1
  6. package/dist/core/errors.mjs +7 -1
  7. package/dist/core/formats.mjs +9 -1
  8. package/dist/core/merge.d.mts +1 -1
  9. package/dist/core/normalise.d.mts +38 -5
  10. package/dist/core/normalise.mjs +2 -2
  11. package/dist/core/openapi30.d.mts +33 -4
  12. package/dist/core/openapi30.mjs +2 -2
  13. package/dist/core/ref.d.mts +1 -1
  14. package/dist/core/renderer.d.mts +1 -1
  15. package/dist/core/renderer.mjs +7 -2
  16. package/dist/core/swagger2.d.mts +1 -1
  17. package/dist/core/swagger2.mjs +1 -1
  18. package/dist/core/version.d.mts +2 -2
  19. package/dist/core/version.mjs +19 -9
  20. package/dist/core/walkBuilders.d.mts +2 -2
  21. package/dist/{diagnostics-BYk63jsC.d.mts → diagnostics-VgEKI_Ct.d.mts} +1 -1
  22. package/dist/{errors-C5zRC2PU.d.mts → errors-CnGjT1cg.d.mts} +7 -2
  23. package/dist/html/a11y.d.mts +1 -1
  24. package/dist/html/renderToHtml.d.mts +1 -1
  25. package/dist/html/renderToHtmlStream.d.mts +1 -1
  26. package/dist/html/renderers.d.mts +1 -1
  27. package/dist/html/renderers.mjs +28 -0
  28. package/dist/html/streamRenderers.d.mts +1 -1
  29. package/dist/{normalise-tL9FckAk.mjs → normalise-C0ofw3W6.mjs} +418 -97
  30. package/dist/openapi/components.mjs +4 -0
  31. package/dist/openapi/parser.mjs +4 -1
  32. package/dist/openapi/resolve.d.mts +6 -5
  33. package/dist/openapi/resolve.mjs +7 -6
  34. package/dist/react/SchemaComponent.d.mts +3 -3
  35. package/dist/react/SchemaComponent.mjs +3 -13
  36. package/dist/react/SchemaView.d.mts +2 -2
  37. package/dist/react/SchemaView.mjs +1 -0
  38. package/dist/react/headless.d.mts +7 -1
  39. package/dist/react/headless.mjs +13 -1
  40. package/dist/react/headlessRenderers.d.mts +53 -2
  41. package/dist/react/headlessRenderers.mjs +139 -1
  42. package/dist/{ref-Ckt5liZs.d.mts → ref-Bb43ZURY.d.mts} +1 -1
  43. package/dist/{renderer-BAGoX4AK.d.mts → renderer-BQqiXUYP.d.mts} +8 -2
  44. package/dist/themes/mantine.d.mts +1 -1
  45. package/dist/themes/mui.d.mts +1 -1
  46. package/dist/themes/radix.d.mts +1 -1
  47. package/dist/themes/shadcn.d.mts +1 -1
  48. package/dist/{version-B5NV-35j.d.mts → version-XNH7PRGP.d.mts} +8 -1
  49. package/package.json +1 -1
@@ -184,6 +184,10 @@ function OperationHeader({ operation }) {
184
184
  operation.path
185
185
  ] }),
186
186
  operation.summary && /* @__PURE__ */ jsx("p", { children: operation.summary }),
187
+ operation.description && /* @__PURE__ */ jsx("p", {
188
+ "data-description": true,
189
+ children: operation.description
190
+ }),
187
191
  operation.deprecated && /* @__PURE__ */ jsx("span", {
188
192
  "data-deprecated": true,
189
193
  children: "Deprecated"
@@ -33,7 +33,10 @@ const METHODS = [
33
33
  "post",
34
34
  "put",
35
35
  "patch",
36
- "delete"
36
+ "delete",
37
+ "head",
38
+ "options",
39
+ "trace"
37
40
  ];
38
41
  /**
39
42
  * Resolve a path item, following a `$ref` to `components/pathItems/<Name>`
@@ -7,11 +7,12 @@ import { OpenApiDocument, OperationInfo, ParameterInfo, ResponseInfo, getRequest
7
7
  *
8
8
  * Before parsing, the document is run through the version-aware
9
9
  * normalisation pipeline (`normaliseOpenApiSchemas`) so OpenAPI 3.0.x
10
- * keywords (`nullable`, `discriminator`, `example`) and Swagger 2.0
11
- * documents are converted to canonical Draft 2020-12 form. The parser
12
- * and downstream extractors (`getRequestBody`, `getResponses`, etc.) then
13
- * observe schemas in the same form `<SchemaComponent>` does, keeping the
14
- * OpenAPI components on the same pipeline as the top-level adapter.
10
+ * keywords (`nullable`, `discriminator`, `example`), OpenAPI 3.1.x
11
+ * `discriminator`, and Swagger 2.0 documents are all converted to
12
+ * canonical Draft 2020-12 form. The parser and downstream extractors
13
+ * (`getRequestBody`, `getResponses`, etc.) then observe schemas in the
14
+ * same form `<SchemaComponent>` does, keeping the OpenAPI components on
15
+ * the same pipeline as the top-level adapter.
15
16
  *
16
17
  * The cache is keyed by the caller-supplied document so subsequent calls
17
18
  * with the same input bypass both normalisation and parsing.
@@ -1,6 +1,6 @@
1
1
  import { isObject } from "../core/guards.mjs";
2
2
  import { detectOpenApiVersion } from "../core/version.mjs";
3
- import { i as normaliseOpenApiSchemas } from "../normalise-tL9FckAk.mjs";
3
+ import { a as normaliseOpenApiSchemas } from "../normalise-C0ofw3W6.mjs";
4
4
  import { getParameters, getRequestBody, getResponses, listOperations, parseOpenApiDocument } from "./parser.mjs";
5
5
  //#region src/openapi/resolve.ts
6
6
  /**
@@ -17,11 +17,12 @@ const docCache = /* @__PURE__ */ new WeakMap();
17
17
  *
18
18
  * Before parsing, the document is run through the version-aware
19
19
  * normalisation pipeline (`normaliseOpenApiSchemas`) so OpenAPI 3.0.x
20
- * keywords (`nullable`, `discriminator`, `example`) and Swagger 2.0
21
- * documents are converted to canonical Draft 2020-12 form. The parser
22
- * and downstream extractors (`getRequestBody`, `getResponses`, etc.) then
23
- * observe schemas in the same form `<SchemaComponent>` does, keeping the
24
- * OpenAPI components on the same pipeline as the top-level adapter.
20
+ * keywords (`nullable`, `discriminator`, `example`), OpenAPI 3.1.x
21
+ * `discriminator`, and Swagger 2.0 documents are all converted to
22
+ * canonical Draft 2020-12 form. The parser and downstream extractors
23
+ * (`getRequestBody`, `getResponses`, etc.) then observe schemas in the
24
+ * same form `<SchemaComponent>` does, keeping the OpenAPI components on
25
+ * the same pipeline as the top-level adapter.
25
26
  *
26
27
  * The cache is keyed by the caller-supplied document so subsequent calls
27
28
  * with the same input bypass both normalisation and parsing.
@@ -1,7 +1,7 @@
1
1
  import { M as WalkedField, T as SchemaMeta, d as FieldOverrides, u as FieldOverride } from "../types-D_5ST7SS.mjs";
2
- import { t as Diagnostic } from "../diagnostics-BYk63jsC.mjs";
3
- import { t as SchemaError } from "../errors-C5zRC2PU.mjs";
4
- import { l as RenderProps, r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
2
+ import { t as Diagnostic } from "../diagnostics-VgEKI_Ct.mjs";
3
+ import { t as SchemaError } from "../errors-CnGjT1cg.mjs";
4
+ import { l as RenderProps, r as ComponentResolver } from "../renderer-BQqiXUYP.mjs";
5
5
  import { c as PathOfType, l as ResolveOpenAPIRef, n as FromJSONSchema } from "../typeInference-5JiqIZ8t.mjs";
6
6
  import { z } from "zod";
7
7
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
@@ -78,7 +78,7 @@ function SchemaComponent({ schema: schemaInput, ref: refInput, value, onChange,
78
78
  rootMeta = normalised.rootMeta;
79
79
  rootDocument = normalised.rootDocument;
80
80
  } catch (err) {
81
- const error = new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schemaInput, detectNormalisationKind(err));
81
+ const error = err instanceof SchemaNormalisationError ? err : new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schemaInput, "unknown");
82
82
  if (onError !== void 0) {
83
83
  onError(error);
84
84
  return null;
@@ -218,7 +218,8 @@ function SchemaField({ path, schema: schemaInput, ref: refInput, value, onChange
218
218
  rootMeta = normalised.rootMeta;
219
219
  rootDocument = normalised.rootDocument;
220
220
  } catch (err) {
221
- throw new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schemaInput, detectNormalisationKind(err));
221
+ if (err instanceof SchemaNormalisationError) throw err;
222
+ throw new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schemaInput, "unknown");
222
223
  }
223
224
  const fieldTree = resolvePath(walk(jsonSchema, {
224
225
  componentMeta: fieldMeta,
@@ -284,16 +285,5 @@ function isFieldErrorCallback(value) {
284
285
  function isCallable(value) {
285
286
  return typeof value === "function";
286
287
  }
287
- function detectNormalisationKind(err) {
288
- if (err instanceof Error) {
289
- const msg = err.message;
290
- if (msg.includes("Zod 3")) return "zod3-unsupported";
291
- if (msg.includes("Invalid Zod 4")) return "invalid-zod";
292
- if (msg.includes("OpenAPI ref not found")) return "openapi-missing-ref";
293
- if (msg.includes("OpenAPI")) return "openapi-invalid";
294
- if (msg.includes("JSON Schema")) return "invalid-json-schema";
295
- }
296
- return "unknown";
297
- }
298
288
  //#endregion
299
289
  export { ROOT_PATH, SchemaComponent, SchemaField, SchemaProvider, joinPath, registerWidget, renderField, sanitisePrefix };
@@ -1,6 +1,6 @@
1
1
  import { T as SchemaMeta } from "../types-D_5ST7SS.mjs";
2
- import { t as Diagnostic } from "../diagnostics-BYk63jsC.mjs";
3
- import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
2
+ import { t as Diagnostic } from "../diagnostics-VgEKI_Ct.mjs";
3
+ import { r as ComponentResolver } from "../renderer-BQqiXUYP.mjs";
4
4
  import { WidgetMap } from "./SchemaComponent.mjs";
5
5
  import { ReactNode } from "react";
6
6
 
@@ -62,6 +62,7 @@ function SchemaView({ schema: schemaInput, ref: refInput, value, fields, meta: c
62
62
  rootMeta = normalised.rootMeta;
63
63
  rootDocument = normalised.rootDocument;
64
64
  } catch (err) {
65
+ if (err instanceof SchemaNormalisationError) throw err;
65
66
  throw new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schemaInput, "unknown");
66
67
  }
67
68
  const walkOptions = {
@@ -1,10 +1,16 @@
1
- import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
1
+ import { r as ComponentResolver } from "../renderer-BQqiXUYP.mjs";
2
2
 
3
3
  //#region src/react/headless.d.ts
4
4
  /**
5
5
  * The headless resolver uses props.renderChild for recursive rendering.
6
6
  * No factory function needed — the renderChild is always available
7
7
  * on RenderProps.
8
+ *
9
+ * Every WalkedField variant the walker can emit has a registered renderer.
10
+ * Missing a registration causes `getRenderFunction` to return `undefined`
11
+ * and the field to render as nothing — silent invisibility. The
12
+ * `ComponentResolver` interface keeps each key optional for theme
13
+ * adapters, so the registration here is the single source of completeness.
8
14
  */
9
15
  declare const headlessResolver: ComponentResolver;
10
16
  //#endregion
@@ -1,22 +1,34 @@
1
- import { renderArray, renderBoolean, renderDiscriminatedUnion, renderEnum, renderFile, renderNumber, renderObject, renderRecord, renderRecursive, renderString, renderUnion, renderUnknown } from "./headlessRenderers.mjs";
1
+ import { renderArray, renderBoolean, renderConditional, renderDiscriminatedUnion, renderEnum, renderFile, renderLiteral, renderNegation, renderNever, renderNull, renderNumber, renderObject, renderRecord, renderRecursive, renderString, renderTuple, renderUnion, renderUnknown } from "./headlessRenderers.mjs";
2
2
  //#region src/react/headless.tsx
3
3
  /**
4
4
  * The headless resolver uses props.renderChild for recursive rendering.
5
5
  * No factory function needed — the renderChild is always available
6
6
  * on RenderProps.
7
+ *
8
+ * Every WalkedField variant the walker can emit has a registered renderer.
9
+ * Missing a registration causes `getRenderFunction` to return `undefined`
10
+ * and the field to render as nothing — silent invisibility. The
11
+ * `ComponentResolver` interface keeps each key optional for theme
12
+ * adapters, so the registration here is the single source of completeness.
7
13
  */
8
14
  const headlessResolver = {
9
15
  string: renderString,
10
16
  number: renderNumber,
11
17
  boolean: renderBoolean,
18
+ null: renderNull,
12
19
  enum: renderEnum,
13
20
  object: renderObject,
14
21
  record: renderRecord,
15
22
  array: renderArray,
23
+ tuple: renderTuple,
16
24
  union: renderUnion,
17
25
  discriminatedUnion: renderDiscriminatedUnion,
26
+ conditional: renderConditional,
27
+ negation: renderNegation,
28
+ literal: renderLiteral,
18
29
  file: renderFile,
19
30
  recursive: renderRecursive,
31
+ never: renderNever,
20
32
  unknown: renderUnknown
21
33
  };
22
34
  //#endregion
@@ -1,5 +1,5 @@
1
1
  import { M as WalkedField } from "../types-D_5ST7SS.mjs";
2
- import { l as RenderProps } from "../renderer-BAGoX4AK.mjs";
2
+ import { l as RenderProps } from "../renderer-BQqiXUYP.mjs";
3
3
  import { ReactNode } from "react";
4
4
 
5
5
  //#region src/react/headlessRenderers.d.ts
@@ -57,6 +57,57 @@ declare function renderDiscriminatedUnion(props: RenderProps): ReactNode;
57
57
  declare function discriminatedUnionValueForTab(optionLabels: readonly string[], discKey: string, newIndex: number): Record<string, string> | undefined;
58
58
  declare function renderFile(props: RenderProps): ReactNode;
59
59
  declare function renderRecursive(props: RenderProps): ReactNode;
60
+ /**
61
+ * Render a literal field — `z.literal("a")` or `{ const: 5 }`.
62
+ *
63
+ * Literals are non-editable by nature (the value is fixed at the schema
64
+ * level), so both read-only and editable modes display the literal value(s).
65
+ * Multiple literals (`z.literal(["a", "b"])`) render comma-separated.
66
+ */
67
+ declare function renderLiteral(props: RenderProps): ReactNode;
68
+ /**
69
+ * Render a null field — `z.null()` or `{ type: "null" }`.
70
+ *
71
+ * The only valid value is `null`, so render an em-dash placeholder
72
+ * regardless of mode. There is nothing the user can usefully change.
73
+ */
74
+ declare function renderNull(props: RenderProps): ReactNode;
75
+ /**
76
+ * Render a never field — `z.never()` or `{ not: {} }` / `false` schema.
77
+ *
78
+ * `never` indicates a position that cannot hold any value. We render a
79
+ * visible placeholder rather than throwing because some valid schemas
80
+ * intentionally contain `never` branches (e.g. exhaustive discriminated
81
+ * unions), and a runtime crash on render would be worse than a visible
82
+ * indicator.
83
+ */
84
+ declare function renderNever(props: RenderProps): ReactNode;
85
+ /**
86
+ * Render a tuple field — `z.tuple([z.string(), z.number()])` or
87
+ * `{ prefixItems: [...] }`.
88
+ *
89
+ * Positional rendering: each `prefixItems` entry is rendered at its index.
90
+ * The structural index (e.g. `[0]`) is passed as the path suffix so
91
+ * children get unique ids and labels.
92
+ */
93
+ declare function renderTuple(props: RenderProps): ReactNode;
94
+ /**
95
+ * Render a conditional field — JSON Schema `if`/`then`/`else`.
96
+ *
97
+ * Conditional schemas describe constraints rather than a single value
98
+ * shape, so the renderer surfaces each clause as a labelled fieldset.
99
+ * This mirrors the HTML renderer's annotation approach and gives a
100
+ * predictable structure for theme adapters that want to override it.
101
+ */
102
+ declare function renderConditional(props: RenderProps): ReactNode;
103
+ /**
104
+ * Render a negation field — JSON Schema `{ not: { ... } }`.
105
+ *
106
+ * Negation describes a constraint ("value must NOT match this schema")
107
+ * rather than a value shape. The renderer surfaces the negated schema
108
+ * beneath an explanatory preamble.
109
+ */
110
+ declare function renderNegation(props: RenderProps): ReactNode;
60
111
  declare function renderUnknown(props: RenderProps): ReactNode;
61
112
  //#endregion
62
- export { defaultRecordValue, discriminatedUnionValueForTab, inputId, nextRecordKey, renameRecordKey, renderArray, renderBoolean, renderDiscriminatedUnion, renderEnum, renderFile, renderNumber, renderObject, renderRecord, renderRecursive, renderString, renderUnion, renderUnknown, toReactNode };
113
+ 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 };
@@ -595,6 +595,144 @@ function renderRecursive(props) {
595
595
  " (recursive)"
596
596
  ] }) });
597
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
+ }
598
736
  function renderUnknown(props) {
599
737
  const id = inputId(props.path);
600
738
  if (props.readOnly) {
@@ -627,4 +765,4 @@ function matchUnionOption(options, value) {
627
765
  if (typeof value === "object" && value !== null) return options.find((o) => o.type === "object");
628
766
  }
629
767
  //#endregion
630
- 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 };
@@ -1,4 +1,4 @@
1
- import { i as DiagnosticsOptions } from "./diagnostics-BYk63jsC.mjs";
1
+ import { i as DiagnosticsOptions } from "./diagnostics-VgEKI_Ct.mjs";
2
2
 
3
3
  //#region src/core/ref.d.ts
4
4
  /**
@@ -98,6 +98,7 @@ interface ComponentResolver {
98
98
  string?: RenderFunction;
99
99
  number?: RenderFunction;
100
100
  boolean?: RenderFunction;
101
+ null?: RenderFunction;
101
102
  enum?: RenderFunction;
102
103
  object?: RenderFunction;
103
104
  array?: RenderFunction;
@@ -110,6 +111,7 @@ interface ComponentResolver {
110
111
  recursive?: RenderFunction;
111
112
  literal?: RenderFunction;
112
113
  file?: RenderFunction;
114
+ never?: RenderFunction;
113
115
  unknown?: RenderFunction;
114
116
  }
115
117
  /** An HTML render function returns a string. */
@@ -122,6 +124,7 @@ interface HtmlResolver {
122
124
  string?: HtmlRenderFunction;
123
125
  number?: HtmlRenderFunction;
124
126
  boolean?: HtmlRenderFunction;
127
+ null?: HtmlRenderFunction;
125
128
  enum?: HtmlRenderFunction;
126
129
  object?: HtmlRenderFunction;
127
130
  array?: HtmlRenderFunction;
@@ -134,13 +137,16 @@ interface HtmlResolver {
134
137
  recursive?: HtmlRenderFunction;
135
138
  literal?: HtmlRenderFunction;
136
139
  file?: HtmlRenderFunction;
140
+ never?: HtmlRenderFunction;
137
141
  unknown?: HtmlRenderFunction;
138
142
  }
139
- 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"];
140
144
  type ResolverKey = (typeof RESOLVER_KEYS)[number];
141
145
  /**
142
146
  * Map a schema type to the resolver key that handles it.
143
- * `discriminatedUnion` `union`. Unknown types `unknown`.
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".
144
150
  */
145
151
  declare function typeToKey(type: WalkedField["type"]): ResolverKey;
146
152
  /**
@@ -1,4 +1,4 @@
1
- import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
1
+ import { r as ComponentResolver } from "../renderer-BQqiXUYP.mjs";
2
2
 
3
3
  //#region src/themes/mantine.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
1
+ import { r as ComponentResolver } from "../renderer-BQqiXUYP.mjs";
2
2
 
3
3
  //#region src/themes/mui.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
1
+ import { r as ComponentResolver } from "../renderer-BQqiXUYP.mjs";
2
2
 
3
3
  //#region src/themes/radix.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { r as ComponentResolver } from "../renderer-BAGoX4AK.mjs";
1
+ import { r as ComponentResolver } from "../renderer-BQqiXUYP.mjs";
2
2
 
3
3
  //#region src/themes/shadcn.d.ts
4
4
  declare const shadcnResolver: ComponentResolver;
@@ -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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "schema-components",
3
- "version": "1.18.1",
3
+ "version": "1.19.0",
4
4
  "description": "React components that render UI from Zod schemas, JSON Schema, and OpenAPI documents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",