schema-components 1.22.0 → 1.23.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 (82) hide show
  1. package/README.md +3 -1
  2. package/dist/core/adapter.d.mts +97 -3
  3. package/dist/core/adapter.mjs +260 -111
  4. package/dist/core/constraints.d.mts +2 -2
  5. package/dist/core/constraints.mjs +0 -7
  6. package/dist/core/cssClasses.d.mts +52 -0
  7. package/dist/core/cssClasses.mjs +51 -0
  8. package/dist/core/diagnostics.d.mts +1 -1
  9. package/dist/core/errors.d.mts +1 -1
  10. package/dist/core/errors.mjs +5 -13
  11. package/dist/core/fieldOrder.d.mts +1 -1
  12. package/dist/core/formats.d.mts +9 -2
  13. package/dist/core/formats.mjs +12 -1
  14. package/dist/core/idPath.d.mts +54 -0
  15. package/dist/core/idPath.mjs +66 -0
  16. package/dist/core/merge.d.mts +10 -1
  17. package/dist/core/merge.mjs +49 -10
  18. package/dist/core/normalise.d.mts +14 -3
  19. package/dist/core/normalise.mjs +2 -2
  20. package/dist/core/openapi30.d.mts +15 -1
  21. package/dist/core/openapi30.mjs +2 -2
  22. package/dist/core/openapiConstants.d.mts +67 -0
  23. package/dist/core/openapiConstants.mjs +90 -0
  24. package/dist/core/ref.d.mts +2 -2
  25. package/dist/core/ref.mjs +84 -6
  26. package/dist/core/refChain.d.mts +70 -0
  27. package/dist/core/refChain.mjs +44 -0
  28. package/dist/core/renderer.d.mts +1 -1
  29. package/dist/core/swagger2.d.mts +1 -1
  30. package/dist/core/swagger2.mjs +1 -1
  31. package/dist/core/typeInference.d.mts +982 -2
  32. package/dist/core/types.d.mts +1 -1
  33. package/dist/core/unionMatch.d.mts +36 -0
  34. package/dist/core/unionMatch.mjs +53 -0
  35. package/dist/core/version.d.mts +1 -1
  36. package/dist/core/version.mjs +29 -17
  37. package/dist/core/walkBuilders.d.mts +23 -4
  38. package/dist/core/walkBuilders.mjs +27 -7
  39. package/dist/core/walker.d.mts +1 -1
  40. package/dist/core/walker.mjs +44 -45
  41. package/dist/{diagnostics-D0QCYGv0.d.mts → diagnostics-BS2kaUyE.d.mts} +1 -1
  42. package/dist/{errors-DpFwqs5C.d.mts → errors-g_MCTQel.d.mts} +9 -15
  43. package/dist/html/a11y.d.mts +9 -4
  44. package/dist/html/a11y.mjs +10 -19
  45. package/dist/html/renderToHtml.d.mts +2 -2
  46. package/dist/html/renderToHtmlStream.d.mts +2 -2
  47. package/dist/html/renderToHtmlStream.mjs +12 -1
  48. package/dist/html/renderers.d.mts +43 -8
  49. package/dist/html/renderers.mjs +136 -111
  50. package/dist/html/streamRenderers.d.mts +4 -5
  51. package/dist/html/streamRenderers.mjs +40 -61
  52. package/dist/{normalise-DVEJQmF7.mjs → normalise-DCYp06Sr.mjs} +352 -162
  53. package/dist/openapi/ApiCallbacks.d.mts +1 -1
  54. package/dist/openapi/ApiLinks.d.mts +1 -1
  55. package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
  56. package/dist/openapi/ApiSecurity.d.mts +1 -1
  57. package/dist/openapi/components.d.mts +116 -37
  58. package/dist/openapi/components.mjs +54 -37
  59. package/dist/openapi/parser.d.mts +9 -8
  60. package/dist/openapi/parser.mjs +234 -84
  61. package/dist/openapi/resolve.d.mts +20 -11
  62. package/dist/openapi/resolve.mjs +133 -73
  63. package/dist/react/SchemaComponent.d.mts +32 -7
  64. package/dist/react/SchemaComponent.mjs +45 -21
  65. package/dist/react/SchemaView.d.mts +30 -10
  66. package/dist/react/a11y.d.mts +21 -0
  67. package/dist/react/a11y.mjs +24 -0
  68. package/dist/react/fieldPath.d.mts +1 -1
  69. package/dist/react/headless.d.mts +1 -1
  70. package/dist/react/headlessRenderers.d.mts +8 -9
  71. package/dist/react/headlessRenderers.mjs +41 -72
  72. package/dist/{ref-D-_JBZkF.d.mts → ref-DjLEKa_E.d.mts} +38 -3
  73. package/dist/{renderer-BaRlQIuN.d.mts → renderer-CXJ8y0qw.d.mts} +1 -1
  74. package/dist/themes/mantine.d.mts +1 -1
  75. package/dist/themes/mui.d.mts +1 -1
  76. package/dist/themes/radix.d.mts +1 -1
  77. package/dist/themes/shadcn.d.mts +1 -1
  78. package/dist/themes/shadcn.mjs +2 -1
  79. package/dist/{types-BrRMV0en.d.mts → types-BTB73MB8.d.mts} +32 -4
  80. package/dist/{version-D2jfdX6E.d.mts → version-BFTVLsdb.d.mts} +7 -1
  81. package/package.json +1 -1
  82. package/dist/typeInference-DkcUHfaM.d.mts +0 -982
@@ -1,2 +1,2 @@
1
- import { A as UnknownField, B as isNeverField, C as RecordField, D as StringField, E as StringConstraints, F as isDiscriminatedUnionField, G as isStringField, H as isNumberField, I as isEnumField, J as isUnknownField, K as isTupleField, L as isFileField, M as isArrayField, N as isBooleanField, O as TupleField, P as isConditionalField, R as isLiteralField, S as ObjectField, T as SchemaType, U as isObjectField, V as isNullField, W as isRecordField, Y as resolveEditability, _ as NeverField, a as DiscriminatedUnionField, b as NumberField, c as FieldBase, d as FieldOverrides, f as FileConstraints, g as NegationField, h as LiteralField, i as ConditionalField, j as WalkedField, k as UnionField, l as FieldConstraints, m as JsonObject, n as ArrayField, o as Editability, p as FileField, q as isUnionField, r as BooleanField, s as EnumField, t as ArrayConstraints, u as FieldOverride, v as NullField, w as SchemaMeta, x as ObjectConstraints, y as NumberConstraints, z as isNegationField } from "../types-BrRMV0en.mjs";
1
+ import { A as UnknownField, B as isNeverField, C as RecordField, D as StringField, E as StringConstraints, F as isDiscriminatedUnionField, G as isStringField, H as isNumberField, I as isEnumField, J as isUnknownField, K as isTupleField, L as isFileField, M as isArrayField, N as isBooleanField, O as TupleField, P as isConditionalField, R as isLiteralField, S as ObjectField, T as SchemaType, U as isObjectField, V as isNullField, W as isRecordField, Y as resolveEditability, _ as NeverField, a as DiscriminatedUnionField, b as NumberField, c as FieldBase, d as FieldOverrides, f as FileConstraints, g as NegationField, h as LiteralField, i as ConditionalField, j as WalkedField, k as UnionField, l as FieldConstraints, m as JsonObject, n as ArrayField, o as Editability, p as FileField, q as isUnionField, r as BooleanField, s as EnumField, t as ArrayConstraints, u as FieldOverride, v as NullField, w as SchemaMeta, x as ObjectConstraints, y as NumberConstraints, z as isNegationField } from "../types-BTB73MB8.mjs";
2
2
  export { ArrayConstraints, ArrayField, BooleanField, ConditionalField, DiscriminatedUnionField, Editability, EnumField, FieldBase, FieldConstraints, FieldOverride, FieldOverrides, FileConstraints, FileField, JsonObject, LiteralField, NegationField, NeverField, NullField, NumberConstraints, NumberField, ObjectConstraints, ObjectField, RecordField, SchemaMeta, SchemaType, StringConstraints, StringField, TupleField, UnionField, UnknownField, WalkedField, isArrayField, isBooleanField, isConditionalField, isDiscriminatedUnionField, isEnumField, isFileField, isLiteralField, isNegationField, isNeverField, isNullField, isNumberField, isObjectField, isRecordField, isStringField, isTupleField, isUnionField, isUnknownField, resolveEditability };
@@ -0,0 +1,36 @@
1
+ import { j as WalkedField } from "../types-BTB73MB8.mjs";
2
+
3
+ //#region src/core/unionMatch.d.ts
4
+ /**
5
+ * Pick the union option that structurally matches the supplied value.
6
+ *
7
+ * Heuristic only — picks by JavaScript typeof / array / object class. Returns
8
+ * `undefined` when the value's shape doesn't correspond to any option (for
9
+ * example a `null` value against a non-nullable union). Callers should
10
+ * fall back to the first option or render an empty state in that case.
11
+ */
12
+ declare function matchUnionOption(options: readonly WalkedField[], value: unknown): WalkedField | undefined;
13
+ /**
14
+ * Resolution of a discriminated union against a concrete value. The renderer
15
+ * uses `optionLabels` to title each tab, `activeIndex` to select the open
16
+ * tab, and `activeOption` as the field to render below.
17
+ */
18
+ interface DiscriminatedActive {
19
+ readonly optionLabels: readonly string[];
20
+ readonly activeIndex: number;
21
+ readonly activeOption: WalkedField | undefined;
22
+ }
23
+ /**
24
+ * Derive labels, active index, and active option for a discriminated union.
25
+ *
26
+ * For each option, the label is the discriminator property's `const` value
27
+ * (when the option is an object with a literal discriminator) or, failing
28
+ * that, the option's `meta.title` or its `type`. The active index is chosen
29
+ * from the discriminator's value on `valueObject`; missing or non-matching
30
+ * values fall back to index 0.
31
+ *
32
+ * Pure data transformation — no rendering concerns, no React imports.
33
+ */
34
+ declare function resolveDiscriminatedActive(options: readonly WalkedField[], discriminator: string, valueObject: Record<string, unknown> | undefined): DiscriminatedActive;
35
+ //#endregion
36
+ export { DiscriminatedActive, matchUnionOption, resolveDiscriminatedActive };
@@ -0,0 +1,53 @@
1
+ //#region src/core/unionMatch.ts
2
+ /**
3
+ * Pick the union option that structurally matches the supplied value.
4
+ *
5
+ * Heuristic only — picks by JavaScript typeof / array / object class. Returns
6
+ * `undefined` when the value's shape doesn't correspond to any option (for
7
+ * example a `null` value against a non-nullable union). Callers should
8
+ * fall back to the first option or render an empty state in that case.
9
+ */
10
+ function matchUnionOption(options, value) {
11
+ if (typeof value === "string") return options.find((o) => o.type === "string" || o.type === "enum");
12
+ if (typeof value === "number") return options.find((o) => o.type === "number");
13
+ if (typeof value === "boolean") return options.find((o) => o.type === "boolean");
14
+ if (Array.isArray(value)) return options.find((o) => o.type === "array");
15
+ if (typeof value === "object" && value !== null) return options.find((o) => o.type === "object");
16
+ }
17
+ /**
18
+ * Derive labels, active index, and active option for a discriminated union.
19
+ *
20
+ * For each option, the label is the discriminator property's `const` value
21
+ * (when the option is an object with a literal discriminator) or, failing
22
+ * that, the option's `meta.title` or its `type`. The active index is chosen
23
+ * from the discriminator's value on `valueObject`; missing or non-matching
24
+ * values fall back to index 0.
25
+ *
26
+ * Pure data transformation — no rendering concerns, no React imports.
27
+ */
28
+ function resolveDiscriminatedActive(options, discriminator, valueObject) {
29
+ const currentDiscriminatorValue = valueObject !== void 0 && typeof valueObject[discriminator] === "string" ? valueObject[discriminator] : void 0;
30
+ const optionLabels = options.map((opt) => {
31
+ if (opt.type === "object") {
32
+ const discriminatorField = opt.fields[discriminator];
33
+ if (discriminatorField?.type === "literal") {
34
+ const constVal = discriminatorField.literalValues[0];
35
+ if (typeof constVal === "string") return constVal;
36
+ }
37
+ }
38
+ if (typeof opt.meta.title === "string") return opt.meta.title;
39
+ return opt.type;
40
+ });
41
+ let activeIndex = 0;
42
+ if (currentDiscriminatorValue !== void 0) {
43
+ const found = optionLabels.indexOf(currentDiscriminatorValue);
44
+ if (found !== -1) activeIndex = found;
45
+ }
46
+ return {
47
+ optionLabels,
48
+ activeIndex,
49
+ activeOption: options[activeIndex]
50
+ };
51
+ }
52
+ //#endregion
53
+ export { matchUnionOption, resolveDiscriminatedActive };
@@ -1,2 +1,2 @@
1
- import { a as detectJsonSchemaDraft, c as inferJsonSchemaDraftWithReason, d as isSwagger2, f as matchJsonSchemaDraftUri, i as OpenApiVersionInfo, l as isOpenApi30, n as JsonSchemaDialectInfo, o as detectOpenApiVersion, p as readJsonSchemaDialect, r as JsonSchemaDraft, s as inferJsonSchemaDraft, t as InferredDraft, u as isOpenApi31 } from "../version-D2jfdX6E.mjs";
1
+ import { a as detectJsonSchemaDraft, c as inferJsonSchemaDraftWithReason, d as isSwagger2, f as matchJsonSchemaDraftUri, i as OpenApiVersionInfo, l as isOpenApi30, n as JsonSchemaDialectInfo, o as detectOpenApiVersion, p as readJsonSchemaDialect, r as JsonSchemaDraft, s as inferJsonSchemaDraft, t as InferredDraft, u as isOpenApi31 } from "../version-BFTVLsdb.mjs";
2
2
  export { InferredDraft, JsonSchemaDialectInfo, JsonSchemaDraft, OpenApiVersionInfo, detectJsonSchemaDraft, detectOpenApiVersion, inferJsonSchemaDraft, inferJsonSchemaDraftWithReason, isOpenApi30, isOpenApi31, isSwagger2, matchJsonSchemaDraftUri, readJsonSchemaDialect };
@@ -116,27 +116,39 @@ function inferJsonSchemaDraftWithReason(schema) {
116
116
  }
117
117
  /**
118
118
  * Detect the OpenAPI/Swagger version from a document.
119
- * Returns `undefined` for documents that are not OpenAPI or Swagger.
119
+ *
120
+ * Returns `undefined` when the document declares neither `swagger` nor
121
+ * `openapi` strings, or when the declared version string is malformed
122
+ * (missing parts or non-numeric segments). `Number("abc")` yields `NaN`,
123
+ * which `parts[i] ?? default` does NOT replace — nullish coalescing only
124
+ * substitutes `null`/`undefined` — so any unparseable segment surfaces
125
+ * as `undefined` rather than a silent fabricated default.
120
126
  */
121
127
  function detectOpenApiVersion(doc) {
122
128
  const swagger = doc.swagger;
123
- if (typeof swagger === "string") {
124
- const parts = swagger.split(".").map(Number);
125
- return {
126
- major: parts[0] ?? 2,
127
- minor: parts[1] ?? 0,
128
- patch: parts[2] ?? 0
129
- };
130
- }
129
+ if (typeof swagger === "string") return parseVersionString(swagger);
131
130
  const openapi = doc.openapi;
132
- if (typeof openapi === "string") {
133
- const parts = openapi.split(".").map(Number);
134
- return {
135
- major: parts[0] ?? 3,
136
- minor: parts[1] ?? 0,
137
- patch: parts[2] ?? 0
138
- };
139
- }
131
+ if (typeof openapi === "string") return parseVersionString(openapi);
132
+ }
133
+ /**
134
+ * Parse a dotted version string into `{ major, minor, patch }`.
135
+ *
136
+ * Returns `undefined` when any required segment is missing or fails to
137
+ * parse as a finite number. A two-segment string ("3.1") fills `patch`
138
+ * with `0` because the spec treats the patch as optional, but a missing
139
+ * `major` or `minor` is a malformed declaration and yields `undefined`.
140
+ */
141
+ function parseVersionString(version) {
142
+ const parts = version.split(".").map(Number);
143
+ const major = parts[0];
144
+ const minor = parts[1];
145
+ const patch = parts[2] ?? 0;
146
+ if (major === void 0 || minor === void 0 || !Number.isFinite(major) || !Number.isFinite(minor) || !Number.isFinite(patch)) return;
147
+ return {
148
+ major,
149
+ minor,
150
+ patch
151
+ };
140
152
  }
141
153
  /**
142
154
  * Check if an OpenAPI version is 3.0.x (uses modified Draft 04 schemas
@@ -1,6 +1,6 @@
1
- import { A as UnknownField, D as StringField, b as NumberField, c as FieldBase, j as WalkedField, o as Editability, p as FileField, r as BooleanField, v as NullField, w as SchemaMeta } from "../types-BrRMV0en.mjs";
2
- import { i as DiagnosticsOptions } from "../diagnostics-D0QCYGv0.mjs";
3
- import { t as ExternalResolver } from "../ref-D-_JBZkF.mjs";
1
+ import { A as UnknownField, D as StringField, b as NumberField, c as FieldBase, j as WalkedField, o as Editability, p as FileField, r as BooleanField, v as NullField, w as SchemaMeta } from "../types-BTB73MB8.mjs";
2
+ import { i as DiagnosticsOptions } from "../diagnostics-BS2kaUyE.mjs";
3
+ import { t as ExternalResolver } from "../ref-DjLEKa_E.mjs";
4
4
 
5
5
  //#region src/core/walkBuilders.d.ts
6
6
  declare function getString(obj: Record<string, unknown>, key: string): string | undefined;
@@ -70,5 +70,24 @@ declare function walkDependentRequiredMap(map: Record<string, unknown>): Record<
70
70
  */
71
71
  declare function withoutKeys(schema: Record<string, unknown>, keys: string[]): Record<string, unknown>;
72
72
  declare function isPrimitive(value: unknown): value is string | number | boolean | null;
73
+ /**
74
+ * Convert any JSON-shaped value to a display string suitable for
75
+ * form input attributes or text rendering.
76
+ *
77
+ * Centralises the conversion logic because `EnumField.enumValues` and
78
+ * `LiteralField.literalValues` are typed as `unknown[]` (Draft 2020-12
79
+ * permits any JSON value in `enum` / `const`). Renderers call this
80
+ * helper instead of inlining their own narrowing — the alternative
81
+ * `String(v)` on `unknown` trips `@typescript-eslint/no-base-to-string`.
82
+ *
83
+ * Inputs originate from parsed JSON (or runtime JSON-equivalents) so
84
+ * they are always `null | boolean | number | string | object | array`.
85
+ * Objects and arrays serialise via `JSON.stringify` so a discriminated
86
+ * union with object const values still produces a stable display key.
87
+ *
88
+ * Throws on non-JSON-shaped values (function, symbol, bigint, undefined)
89
+ * — their presence indicates the producer violated the JSON contract.
90
+ */
91
+ declare function displayJsonValue(value: unknown): string;
73
92
  //#endregion
74
- export { WalkContext, WalkOptions, buildBase, buildBooleanField, buildFileField, buildNullField, buildNumberField, buildStringField, buildUnknownField, extractChildOverride, extractMetaFromJson, extractSchemaMetaFields, getArray, getObject, getString, isPrimitive, walkDependentRequiredMap, walkSubSchemaMap, withoutKeys };
93
+ export { WalkContext, WalkOptions, buildBase, buildBooleanField, buildFileField, buildNullField, buildNumberField, buildStringField, buildUnknownField, displayJsonValue, extractChildOverride, extractMetaFromJson, extractSchemaMetaFields, getArray, getObject, getString, isPrimitive, walkDependentRequiredMap, walkSubSchemaMap, withoutKeys };
@@ -68,13 +68,8 @@ function buildBase(schema, ctx) {
68
68
  const defaultValue = "default" in schema ? schema.default : void 0;
69
69
  const examplesRaw = schema.examples;
70
70
  const examples = Array.isArray(examplesRaw) ? examplesRaw : void 0;
71
- const editability = resolveEditability(mergedMeta, ctx.componentMeta, ctx.rootMeta);
72
- if ((overrideMeta !== void 0 && ("readOnly" in overrideMeta || "writeOnly" in overrideMeta) || Boolean(propertyMeta.readOnly) || Boolean(propertyMeta.writeOnly)) && ctx.componentMeta !== void 0) ctx = {
73
- ...ctx,
74
- componentMeta: void 0
75
- };
76
71
  return {
77
- editability,
72
+ editability: resolveEditability(mergedMeta, ctx.componentMeta, ctx.rootMeta),
78
73
  meta: mergedMeta,
79
74
  isOptional: ctx.isOptional,
80
75
  isNullable: ctx.isNullable,
@@ -156,5 +151,30 @@ function withoutKeys(schema, keys) {
156
151
  function isPrimitive(value) {
157
152
  return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null;
158
153
  }
154
+ /**
155
+ * Convert any JSON-shaped value to a display string suitable for
156
+ * form input attributes or text rendering.
157
+ *
158
+ * Centralises the conversion logic because `EnumField.enumValues` and
159
+ * `LiteralField.literalValues` are typed as `unknown[]` (Draft 2020-12
160
+ * permits any JSON value in `enum` / `const`). Renderers call this
161
+ * helper instead of inlining their own narrowing — the alternative
162
+ * `String(v)` on `unknown` trips `@typescript-eslint/no-base-to-string`.
163
+ *
164
+ * Inputs originate from parsed JSON (or runtime JSON-equivalents) so
165
+ * they are always `null | boolean | number | string | object | array`.
166
+ * Objects and arrays serialise via `JSON.stringify` so a discriminated
167
+ * union with object const values still produces a stable display key.
168
+ *
169
+ * Throws on non-JSON-shaped values (function, symbol, bigint, undefined)
170
+ * — their presence indicates the producer violated the JSON contract.
171
+ */
172
+ function displayJsonValue(value) {
173
+ if (value === null) return "null";
174
+ if (typeof value === "string") return value;
175
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
176
+ if (typeof value === "object") return JSON.stringify(value);
177
+ throw new TypeError(`displayJsonValue: value of type ${typeof value} is not a JSON-shaped value`);
178
+ }
159
179
  //#endregion
160
- export { buildBase, buildBooleanField, buildFileField, buildNullField, buildNumberField, buildStringField, buildUnknownField, extractChildOverride, extractMetaFromJson, extractSchemaMetaFields, getArray, getObject, getString, isPrimitive, walkDependentRequiredMap, walkSubSchemaMap, withoutKeys };
180
+ export { buildBase, buildBooleanField, buildFileField, buildNullField, buildNumberField, buildStringField, buildUnknownField, displayJsonValue, extractChildOverride, extractMetaFromJson, extractSchemaMetaFields, getArray, getObject, getString, isPrimitive, walkDependentRequiredMap, walkSubSchemaMap, withoutKeys };
@@ -1,4 +1,4 @@
1
- import { j as WalkedField } from "../types-BrRMV0en.mjs";
1
+ import { j as WalkedField } from "../types-BTB73MB8.mjs";
2
2
  import { WalkOptions } from "./walkBuilders.mjs";
3
3
 
4
4
  //#region src/core/walker.d.ts
@@ -5,7 +5,7 @@ import { countDistinctRefs, resolveRef } from "./ref.mjs";
5
5
  import { matchJsonSchemaDraftUri } from "./version.mjs";
6
6
  import { extractArrayConstraints, extractObjectConstraints, stripInapplicableConstraints } from "./constraints.mjs";
7
7
  import { ANNOTATION_SIBLINGS, detectDiscriminated, mergeAllOf, mergeRefSiblings, normaliseAnyOf } from "./merge.mjs";
8
- import { buildBase, buildBooleanField, buildFileField, buildNullField, buildNumberField, buildStringField, buildUnknownField, extractChildOverride, extractSchemaMetaFields, getArray, getObject, getString, isPrimitive, walkDependentRequiredMap, walkSubSchemaMap, withoutKeys } from "./walkBuilders.mjs";
8
+ import { buildBase, buildBooleanField, buildFileField, buildNullField, buildNumberField, buildStringField, buildUnknownField, extractChildOverride, extractSchemaMetaFields, getArray, getObject, getString, walkDependentRequiredMap, walkSubSchemaMap, withoutKeys } from "./walkBuilders.mjs";
9
9
  //#region src/core/walker.ts
10
10
  /**
11
11
  * Handle JSON Schema boolean values (Draft 06+).
@@ -208,15 +208,7 @@ function walkNode(schema, ctx) {
208
208
  }
209
209
  const enumValues = getArray(schema, "enum");
210
210
  if (enumValues !== void 0) return walkEnum(schema, enumValues, ctx);
211
- if ("const" in schema) {
212
- if (!isPrimitive(schema.const)) emitDiagnostic(ctx.diagnostics, {
213
- code: "invalid-const",
214
- message: `const value is not a primitive: ${typeof schema.const}`,
215
- pointer: ctx.pointer,
216
- detail: { constValue: schema.const }
217
- });
218
- return walkLiteral(schema, ctx);
219
- }
211
+ if ("const" in schema) return walkLiteral(schema, ctx);
220
212
  const type = getString(schema, "type");
221
213
  const typeArray = getArray(schema, "type");
222
214
  if (type === void 0 && typeArray !== void 0) {
@@ -318,38 +310,19 @@ function walkBoolean(schema, ctx) {
318
310
  return buildBooleanField(schema, ctx);
319
311
  }
320
312
  function walkEnum(schema, enumValues, ctx) {
321
- const accepted = [];
322
- for (let i = 0; i < enumValues.length; i++) {
323
- const v = enumValues[i];
324
- if (isPrimitive(v)) {
325
- accepted.push(v);
326
- continue;
327
- }
328
- emitDiagnostic(ctx.diagnostics, {
329
- code: "enum-value-filtered",
330
- message: `enum value at index ${String(i)} is not a primitive (${v === void 0 ? "undefined" : typeof v}); dropping the entry`,
331
- pointer: appendPointer(ctx.pointer, `enum/${String(i)}`),
332
- detail: {
333
- index: i,
334
- value: v
335
- }
336
- });
337
- }
338
313
  return {
339
314
  ...buildBase(schema, ctx),
340
315
  type: "enum",
341
316
  constraints: {},
342
- enumValues: accepted
317
+ enumValues: [...enumValues]
343
318
  };
344
319
  }
345
320
  function walkLiteral(schema, ctx) {
346
- const constValue = schema.const;
347
- const values = isPrimitive(constValue) ? [constValue] : [];
348
321
  return {
349
322
  ...buildBase(schema, ctx),
350
323
  type: "literal",
351
324
  constraints: {},
352
- literalValues: values
325
+ literalValues: [schema.const]
353
326
  };
354
327
  }
355
328
  function walkObject(schema, properties, ctx) {
@@ -463,36 +436,61 @@ function walkRecord(schema, valueSchema, ctx) {
463
436
  valueType
464
437
  };
465
438
  }
439
+ /**
440
+ * Resolve the `unevaluatedItems` keyword into the structural shape the
441
+ * field consumes. Returns the walked schema (object form), the
442
+ * `unevaluatedItemsClosed` flag (`false` form), or both undefined
443
+ * (absent or `true` — `true` permits everything and so has no
444
+ * structural consequence beyond the absence of a constraint).
445
+ *
446
+ * Mirrors the equivalent dispatch in `walkObject` for
447
+ * `unevaluatedProperties` — the parallel keeps the array/tuple and
448
+ * object branches symmetrical.
449
+ */
450
+ function resolveUnevaluatedItems(schema, ctx) {
451
+ if (!("unevaluatedItems" in schema)) return {};
452
+ const value = schema.unevaluatedItems;
453
+ if (value === false) return { unevaluatedItemsClosed: true };
454
+ if (value === true) return { unevaluatedItems: {
455
+ type: "unknown",
456
+ editability: "editable",
457
+ meta: {},
458
+ constraints: {}
459
+ } };
460
+ if (isObject(value)) return { unevaluatedItems: walkNode(value, ctx) };
461
+ return {};
462
+ }
466
463
  function walkArray(schema, ctx) {
467
464
  const walkedContains = "contains" in schema ? walkSubSchema(schema.contains, ctx) : void 0;
465
+ const unevaluatedInfo = resolveUnevaluatedItems(schema, ctx);
468
466
  const prefixItems = getArray(schema, "prefixItems");
469
467
  if (prefixItems !== void 0) {
470
- const walkedItems = prefixItems.filter(isObject).map((item) => walkNode(item, ctx));
471
- const restSchema = getObject(schema, "items");
472
- const restItems = restSchema !== void 0 ? walkNode(restSchema, ctx) : void 0;
468
+ const walkedItems = prefixItems.map((item) => walkSubSchema(item, ctx));
469
+ const restItems = "items" in schema ? walkSubSchema(schema.items, ctx) : void 0;
473
470
  return {
474
471
  ...buildBase(schema, ctx),
475
472
  type: "tuple",
476
473
  constraints: extractArrayConstraints(schema),
477
474
  prefixItems: walkedItems,
478
475
  ...restItems !== void 0 ? { restItems } : {},
479
- ...walkedContains !== void 0 ? { contains: walkedContains } : {}
476
+ ...walkedContains !== void 0 ? { contains: walkedContains } : {},
477
+ ...unevaluatedInfo.unevaluatedItems !== void 0 ? { unevaluatedItems: unevaluatedInfo.unevaluatedItems } : {},
478
+ ...unevaluatedInfo.unevaluatedItemsClosed === true ? { unevaluatedItemsClosed: true } : {}
480
479
  };
481
480
  }
482
- const unevaluatedItemsSchema = getObject(schema, "unevaluatedItems");
483
- const walkedUnevaluatedItems = unevaluatedItemsSchema !== void 0 ? walkNode(unevaluatedItemsSchema, ctx) : void 0;
484
- const items = getObject(schema, "items");
485
- if (items !== void 0) {
481
+ if ("items" in schema) {
486
482
  const elementOverride = extractChildOverride(ctx.fieldOverrides, "[]");
483
+ const elementCtx = {
484
+ ...ctx,
485
+ fieldOverrides: elementOverride
486
+ };
487
487
  return {
488
488
  ...buildBase(schema, ctx),
489
489
  type: "array",
490
490
  constraints: extractArrayConstraints(schema),
491
- element: walkNode(items, {
492
- ...ctx,
493
- fieldOverrides: elementOverride
494
- }),
495
- ...walkedUnevaluatedItems !== void 0 ? { unevaluatedItems: walkedUnevaluatedItems } : {},
491
+ element: walkSubSchema(schema.items, elementCtx),
492
+ ...unevaluatedInfo.unevaluatedItems !== void 0 ? { unevaluatedItems: unevaluatedInfo.unevaluatedItems } : {},
493
+ ...unevaluatedInfo.unevaluatedItemsClosed === true ? { unevaluatedItemsClosed: true } : {},
496
494
  ...walkedContains !== void 0 ? { contains: walkedContains } : {}
497
495
  };
498
496
  }
@@ -500,7 +498,8 @@ function walkArray(schema, ctx) {
500
498
  ...buildBase(schema, ctx),
501
499
  type: "array",
502
500
  constraints: extractArrayConstraints(schema),
503
- ...walkedUnevaluatedItems !== void 0 ? { unevaluatedItems: walkedUnevaluatedItems } : {},
501
+ ...unevaluatedInfo.unevaluatedItems !== void 0 ? { unevaluatedItems: unevaluatedInfo.unevaluatedItems } : {},
502
+ ...unevaluatedInfo.unevaluatedItemsClosed === true ? { unevaluatedItemsClosed: true } : {},
504
503
  ...walkedContains !== void 0 ? { contains: walkedContains } : {}
505
504
  };
506
505
  }
@@ -16,7 +16,7 @@
16
16
  * Machine-readable codes identifying each class of diagnostic.
17
17
  * Stable across releases — consumers can pattern-match on these.
18
18
  */
19
- type DiagnosticCode = "unresolved-ref" | "unknown-keyword" | "unknown-format" | "invalid-const" | "invalid-id-fragment" | "unsupported-type" | "dropped-swagger-feature" | "dynamic-ref-degraded" | "external-ref" | "type-negation-fallback" | "conditional-fallback" | "assumed-draft" | "depth-exceeded" | "allof-conflict" | "discriminator-inconsistent" | "divisible-by-conflict" | "keyword-out-of-draft" | "legacy-dependencies-split" | "dependent-required-invalid" | "unknown-json-schema-dialect" | "unknown-openapi-version" | "relative-ref-resolved" | "bare-exclusive-bound" | "enum-value-filtered" | "required-non-string" | "pattern-invalid" | "duplicate-body-parameter" | "prototype-polluting-property" | "cross-schema-relative-ref-unsupported" | "cyclic-path-item-ref" | "doc-not-object" | "path-item-ref-too-deep" | "swagger-cyclic-parameter-ref" | "swagger-invalid-file-parameter" | "swagger-missing-consumes" | "swagger-missing-host" | "type-mismatch" | "unknown-security-scheme-type" | "zod-codec-output-only";
19
+ type DiagnosticCode = "allof-conflict" | "assumed-draft" | "bare-exclusive-bound" | "conditional-fallback" | "cross-schema-relative-ref-unsupported" | "cyclic-path-item-ref" | "dependencies-conflict" | "dependent-required-invalid" | "depth-exceeded" | "discriminator-inconsistent" | "divisible-by-conflict" | "doc-not-object" | "dropped-swagger-feature" | "duplicate-body-parameter" | "duplicate-operation-id" | "dynamic-ref-degraded" | "enum-value-filtered" | "external-ref" | "invalid-const" | "invalid-id-fragment" | "keyword-out-of-draft" | "legacy-dependencies-split" | "legacy-dependencies-split-2019" | "non-json-media-type-fallback" | "parameter-missing-schema" | "path-item-ref-too-deep" | "path-webhook-name-collision" | "pattern-invalid" | "prototype-polluting-property" | "recursive-anchor-collision" | "relative-ref-resolved" | "required-non-string" | "schema-allof-incompatible" | "swagger-collection-format-dropped" | "swagger-cyclic-parameter-ref" | "swagger-invalid-file-parameter" | "swagger-malformed-oauth-flow" | "swagger-missing-consumes" | "swagger-missing-host" | "type-mismatch" | "type-negation-fallback" | "unknown-format" | "unknown-json-schema-dialect" | "unknown-keyword" | "unknown-openapi-version" | "unknown-parameter-location" | "unknown-security-scheme-type" | "unresolved-ref" | "unsupported-type" | "zod-codec-nested-output-only" | "zod-codec-output-only" | "zod-preprocess-output-only" | "zod-promise-nested-unwrap";
20
20
  /**
21
21
  * A single diagnostic emitted during schema processing.
22
22
  */
@@ -1,16 +1,6 @@
1
+ import { T as SchemaType } from "./types-BTB73MB8.mjs";
2
+
1
3
  //#region src/core/errors.d.ts
2
- /**
3
- * Structured error types for schema-components.
4
- *
5
- * Every error produced by the library is one of these three types:
6
- *
7
- * - SchemaNormalisationError — the adapter failed to convert the input
8
- * to JSON Schema (invalid Zod, bad OpenAPI ref, malformed schema)
9
- * - SchemaRenderError — a theme adapter's render function threw
10
- * - SchemaFieldError — a field path couldn't be resolved
11
- *
12
- * All extend `SchemaError` so consumers can catch the base class.
13
- */
14
4
  /**
15
5
  * Base class for all schema-components errors.
16
6
  * Catch this to handle any library error uniformly.
@@ -46,9 +36,13 @@ declare class SchemaNormalisationError extends SchemaError {
46
36
  * The `cause` is the original error from the render function.
47
37
  */
48
38
  declare class SchemaRenderError extends SchemaError {
49
- /** The schema type being rendered when the error occurred. */
50
- readonly schemaType: string;
51
- constructor(message: string, schema: unknown, schemaType: string, cause: unknown);
39
+ /**
40
+ * The schema type being rendered when the error occurred. Drawn from
41
+ * the walker's discriminant union so consumers can switch on it
42
+ * exhaustively without a wider `string` fallback.
43
+ */
44
+ readonly schemaType: SchemaType;
45
+ constructor(message: string, schema: unknown, schemaType: SchemaType, cause: unknown);
52
46
  }
53
47
  /**
54
48
  * A field path couldn't be resolved against the walked schema tree.
@@ -1,5 +1,5 @@
1
- import { j as WalkedField } from "../types-BrRMV0en.mjs";
2
- import { t as AllConstraints } from "../renderer-BaRlQIuN.mjs";
1
+ import { j as WalkedField } from "../types-BTB73MB8.mjs";
2
+ import { t as AllConstraints } from "../renderer-CXJ8y0qw.mjs";
3
3
  import { HtmlAttributes, HtmlNode } from "./html.mjs";
4
4
 
5
5
  //#region src/html/a11y.d.ts
@@ -15,11 +15,16 @@ import { HtmlAttributes, HtmlNode } from "./html.mjs";
15
15
  */
16
16
  declare function joinPath(parent: string, suffix: string | undefined): string;
17
17
  /**
18
- * Build the input ID for a field at a given path.
18
+ * Build the input ID for a field at a given path. Joins `path` and `key`
19
+ * via `joinPath` then delegates to the canonical `fieldDomId` helper from
20
+ * `core/idPath.ts` so every render pipeline emits identical ids for the
21
+ * same structural position.
19
22
  */
20
23
  declare function buildInputId(path: string, key: string): string;
21
24
  /**
22
- * Derive the hint element ID from the input ID.
25
+ * Derive the hint element ID from the input ID. Thin re-export of the
26
+ * canonical helper so this module remains the one-stop a11y surface for
27
+ * the HTML renderers.
23
28
  */
24
29
  declare function buildHintId(inputId: string): string;
25
30
  /**
@@ -1,3 +1,4 @@
1
+ import { fieldDomId, hintIdFor } from "../core/idPath.mjs";
1
2
  import { h } from "./html.mjs";
2
3
  //#region src/html/a11y.ts
3
4
  /**
@@ -17,31 +18,21 @@ function joinPath(parent, suffix) {
17
18
  return `${parent}.${suffix}`;
18
19
  }
19
20
  /**
20
- * Normalise a path into the id segment used after the `sc-` prefix.
21
- *
22
- * Whitelist-based: every character outside `[A-Za-z0-9_-]` collapses to
23
- * a single hyphen. A blacklist that only stripped `.[]` would still leak
24
- * spaces, slashes, and other punctuation through into ids when a path
25
- * is sourced from a free-text field like `meta.description` — producing
26
- * structurally invalid CSS selectors and `aria-labelledby` references.
27
- *
28
- * Trailing hyphens are trimmed so e.g. `tags[0]` → `tags-0` (not
29
- * `tags-0-`).
30
- */
31
- function normaliseIdSegment(value) {
32
- return value.replace(/[^A-Za-z0-9_-]+/g, "-").replace(/-+$/g, "");
33
- }
34
- /**
35
- * Build the input ID for a field at a given path.
21
+ * Build the input ID for a field at a given path. Joins `path` and `key`
22
+ * via `joinPath` then delegates to the canonical `fieldDomId` helper from
23
+ * `core/idPath.ts` so every render pipeline emits identical ids for the
24
+ * same structural position.
36
25
  */
37
26
  function buildInputId(path, key) {
38
- return `sc-${normaliseIdSegment(joinPath(path, key))}`;
27
+ return fieldDomId(joinPath(path, key));
39
28
  }
40
29
  /**
41
- * Derive the hint element ID from the input ID.
30
+ * Derive the hint element ID from the input ID. Thin re-export of the
31
+ * canonical helper so this module remains the one-stop a11y surface for
32
+ * the HTML renderers.
42
33
  */
43
34
  function buildHintId(inputId) {
44
- return `${inputId}-hint`;
35
+ return hintIdFor(inputId);
45
36
  }
46
37
  /**
47
38
  * Build a human-readable constraint description string.
@@ -1,5 +1,5 @@
1
- import { w as SchemaMeta } from "../types-BrRMV0en.mjs";
2
- import { o as HtmlResolver } from "../renderer-BaRlQIuN.mjs";
1
+ import { w as SchemaMeta } from "../types-BTB73MB8.mjs";
2
+ import { o as HtmlResolver } from "../renderer-CXJ8y0qw.mjs";
3
3
 
4
4
  //#region src/html/renderToHtml.d.ts
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { w as SchemaMeta } from "../types-BrRMV0en.mjs";
2
- import { o as HtmlResolver } from "../renderer-BaRlQIuN.mjs";
1
+ import { w as SchemaMeta } from "../types-BTB73MB8.mjs";
2
+ import { o as HtmlResolver } from "../renderer-CXJ8y0qw.mjs";
3
3
 
4
4
  //#region src/html/renderToHtmlStream.d.ts
5
5
  interface StreamRenderOptions {
@@ -69,8 +69,19 @@ function prepareTree(schema, options) {
69
69
  resolver: options.resolver ?? defaultHtmlResolver
70
70
  };
71
71
  }
72
+ /**
73
+ * Cooperative scheduler yield used between async chunks. Resolves on the
74
+ * next microtask so the event loop can process queued I/O and timers
75
+ * without the four-millisecond clamp browsers apply to nested
76
+ * `setTimeout(..., 0)` calls. The cumulative cost of `setTimeout`-based
77
+ * yielding on a deep schema is measurable; the microtask form is free.
78
+ */
72
79
  function schedulerYield() {
73
- return new Promise((resolve) => setTimeout(resolve, 0));
80
+ return new Promise((resolve) => {
81
+ queueMicrotask(() => {
82
+ resolve(void 0);
83
+ });
84
+ });
74
85
  }
75
86
  //#endregion
76
87
  export { renderToHtmlChunks, renderToHtmlReadable, renderToHtmlStream };
@@ -1,15 +1,50 @@
1
- import { j as WalkedField } from "../types-BrRMV0en.mjs";
2
- import { o as HtmlResolver } from "../renderer-BaRlQIuN.mjs";
1
+ import { dateInputType } from "../core/formats.mjs";
2
+ import { o as HtmlResolver } from "../renderer-CXJ8y0qw.mjs";
3
+ import { matchUnionOption } from "../core/unionMatch.mjs";
3
4
 
4
5
  //#region src/html/renderers.d.ts
5
- declare function dateInputType(format: string | undefined): string | undefined;
6
6
  /**
7
- * Normalise a structural path into a valid, `sc-` prefixed HTML ID.
8
- * Dots (object nesting) and brackets (array indices) become hyphens so
9
- * the id remains a valid CSS selector and predictable in test queries.
7
+ * Thin wrapper over `fieldDomId` from `core/idPath.ts`. Every render
8
+ * pipeline must derive ids from the same canonical normaliser so that
9
+ * `aria-controls`, `aria-labelledby`, and `htmlFor` references resolve
10
+ * consistently across the React, sync-HTML, and streaming-HTML outputs.
11
+ *
12
+ * The wrapper tolerates an empty path here (returning `sc-`) for the
13
+ * sole reason that a leaf renderer at the schema root would otherwise
14
+ * throw — `renderToHtml(z.string())` is a rare but valid call shape.
15
+ * Container renderers thread a non-empty path through `renderChild`, so
16
+ * the empty-id fallback can never produce sibling collisions inside a
17
+ * structured form.
18
+ *
19
+ * TODO(round7-integration): once `renderToHtml` always threads a stable
20
+ * root path (e.g. `"$"`) into the leaf renderers, drop this wrapper and
21
+ * call `fieldDomId` directly so the throw fires as designed.
10
22
  */
11
23
  declare function fieldId(path: string): string;
12
- declare function matchUnionOption(options: WalkedField[], value: unknown): WalkedField | undefined;
24
+ /**
25
+ * Tab-panel id for a discriminated union at `path`. Delegates to the
26
+ * canonical `panelIdFor` from `core/idPath.ts` for the normal case so
27
+ * the sync, streaming, and React renderers all emit identical ids; falls
28
+ * back to a structurally-equivalent string when the renderer is invoked
29
+ * with an empty root path (a discriminated union at the schema root —
30
+ * see the `fieldId` doc comment for the wider context).
31
+ *
32
+ * Exported because `streamRenderers.ts` needs to derive identical ids
33
+ * — the panel id on the `<div role="tabpanel">` must match the
34
+ * `aria-controls` on every tab regardless of which pipeline rendered it.
35
+ *
36
+ * TODO(round7-integration): drop the empty-path branch once `renderToHtml`
37
+ * threads a stable root path so `panelIdFor` can be called directly.
38
+ */
39
+ declare function panelId(path: string): string;
40
+ /**
41
+ * Tab id for tab `i` within a discriminated union at `path`. Mirror of
42
+ * `panelId` above — see its comment.
43
+ *
44
+ * TODO(round7-integration): drop the empty-path branch once `renderToHtml`
45
+ * threads a stable root path so `tabIdFor` can be called directly.
46
+ */
47
+ declare function tabId(path: string, i: number): string;
13
48
  declare const defaultHtmlResolver: HtmlResolver;
14
49
  //#endregion
15
- export { dateInputType, defaultHtmlResolver, fieldId, matchUnionOption };
50
+ export { dateInputType, defaultHtmlResolver, fieldId, matchUnionOption, panelId, tabId };