schema-components 2.0.2 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/README.md +133 -1
  2. package/dist/SchemaComponent-B__6-5-E.d.mts +277 -0
  3. package/dist/SchemaComponent-BxzzsHsK.mjs +668 -0
  4. package/dist/adapter-ktQaheWB.d.mts +213 -0
  5. package/dist/constructorTypes-BdCiMS6e.d.mts +30 -0
  6. package/dist/core/adapter.d.mts +3 -213
  7. package/dist/core/constraintHint.d.mts +1 -1
  8. package/dist/core/constraints.d.mts +2 -2
  9. package/dist/core/contexts.d.mts +71 -0
  10. package/dist/core/contexts.mjs +1 -0
  11. package/dist/core/diagnostics.d.mts +1 -1
  12. package/dist/core/errors.d.mts +1 -1
  13. package/dist/core/fieldOrder.d.mts +1 -1
  14. package/dist/{react → core}/fieldPath.d.mts +2 -2
  15. package/dist/{react → core}/fieldPath.mjs +3 -3
  16. package/dist/core/formats.d.mts +1 -1
  17. package/dist/core/inferValue.d.mts +1 -1
  18. package/dist/core/limits.d.mts +1 -1
  19. package/dist/core/merge.d.mts +1 -1
  20. package/dist/core/normalise.d.mts +2 -2
  21. package/dist/core/ref.d.mts +1 -1
  22. package/dist/core/renderField.d.mts +147 -0
  23. package/dist/core/renderField.mjs +115 -0
  24. package/dist/core/renderer.d.mts +2 -199
  25. package/dist/core/swagger2.d.mts +1 -1
  26. package/dist/core/typeInference.d.mts +1 -982
  27. package/dist/core/types.d.mts +1 -1
  28. package/dist/core/unionMatch.d.mts +1 -1
  29. package/dist/core/version.d.mts +1 -1
  30. package/dist/core/walkBuilders.d.mts +3 -3
  31. package/dist/core/walker.d.mts +1 -1
  32. package/dist/{errors-Dki7tji4.d.mts → errors-DbaI04x2.d.mts} +1 -1
  33. package/dist/html/a11y.d.mts +2 -2
  34. package/dist/html/renderToHtml.d.mts +5 -5
  35. package/dist/html/renderToHtml.mjs +33 -18
  36. package/dist/html/renderToHtmlStream.d.mts +5 -5
  37. package/dist/html/renderers.d.mts +1 -1
  38. package/dist/html/streamRenderers.d.mts +15 -6
  39. package/dist/html/streamRenderers.mjs +56 -10
  40. package/dist/{inferValue-Ce-PviSD.d.mts → inferValue-eAnh50EM.d.mts} +3 -3
  41. package/dist/lit/SchemaComponent.d.mts +125 -0
  42. package/dist/lit/SchemaComponent.mjs +2 -0
  43. package/dist/lit/SchemaField.d.mts +65 -0
  44. package/dist/lit/SchemaField.mjs +2 -0
  45. package/dist/lit/SchemaView.d.mts +14 -0
  46. package/dist/lit/SchemaView.mjs +2 -0
  47. package/dist/lit/constructorTypes.d.mts +2 -0
  48. package/dist/lit/constructorTypes.mjs +1 -0
  49. package/dist/lit/contexts.d.mts +78 -0
  50. package/dist/lit/contexts.mjs +238 -0
  51. package/dist/lit/defaultResolver.d.mts +33 -0
  52. package/dist/lit/defaultResolver.mjs +2 -0
  53. package/dist/lit/registry.d.mts +66 -0
  54. package/dist/lit/registry.mjs +2 -0
  55. package/dist/lit/renderers/baseElement.d.mts +131 -0
  56. package/dist/lit/renderers/baseElement.mjs +109 -0
  57. package/dist/lit/renderers/recordHelpers.d.mts +25 -0
  58. package/dist/lit/renderers/recordHelpers.mjs +55 -0
  59. package/dist/lit/renderers/scArray.d.mts +14 -0
  60. package/dist/lit/renderers/scArray.mjs +86 -0
  61. package/dist/lit/renderers/scBoolean.d.mts +15 -0
  62. package/dist/lit/renderers/scBoolean.mjs +47 -0
  63. package/dist/lit/renderers/scConditional.d.mts +23 -0
  64. package/dist/lit/renderers/scConditional.mjs +65 -0
  65. package/dist/lit/renderers/scDiscriminated.d.mts +23 -0
  66. package/dist/lit/renderers/scDiscriminated.mjs +138 -0
  67. package/dist/lit/renderers/scEnum.d.mts +16 -0
  68. package/dist/lit/renderers/scEnum.mjs +66 -0
  69. package/dist/lit/renderers/scFile.d.mts +15 -0
  70. package/dist/lit/renderers/scFile.mjs +53 -0
  71. package/dist/lit/renderers/scLiteralNullNever.d.mts +30 -0
  72. package/dist/lit/renderers/scLiteralNullNever.mjs +57 -0
  73. package/dist/lit/renderers/scNumber.d.mts +15 -0
  74. package/dist/lit/renderers/scNumber.mjs +64 -0
  75. package/dist/lit/renderers/scObject.d.mts +14 -0
  76. package/dist/lit/renderers/scObject.mjs +57 -0
  77. package/dist/lit/renderers/scRecord.d.mts +14 -0
  78. package/dist/lit/renderers/scRecord.mjs +112 -0
  79. package/dist/lit/renderers/scString.d.mts +19 -0
  80. package/dist/lit/renderers/scString.mjs +165 -0
  81. package/dist/lit/renderers/scTuple.d.mts +14 -0
  82. package/dist/lit/renderers/scTuple.mjs +58 -0
  83. package/dist/lit/renderers/scUnion.d.mts +14 -0
  84. package/dist/lit/renderers/scUnion.mjs +44 -0
  85. package/dist/lit/renderers/scUnknown.d.mts +15 -0
  86. package/dist/lit/renderers/scUnknown.mjs +45 -0
  87. package/dist/lit/ssr.d.mts +37 -0
  88. package/dist/lit/ssr.mjs +9565 -0
  89. package/dist/lit/types.d.mts +2 -0
  90. package/dist/lit/types.mjs +1 -0
  91. package/dist/lit/widget.d.mts +71 -0
  92. package/dist/lit/widget.mjs +87 -0
  93. package/dist/openapi/ApiCallbacks.d.mts +1 -1
  94. package/dist/openapi/ApiLinks.d.mts +1 -1
  95. package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
  96. package/dist/openapi/ApiSecurity.d.mts +1 -1
  97. package/dist/openapi/components.d.mts +4 -4
  98. package/dist/openapi/parser.d.mts +2 -2
  99. package/dist/openapi/resolve.d.mts +1 -1
  100. package/dist/preact/SchemaComponent.d.mts +3 -0
  101. package/dist/preact/SchemaComponent.mjs +26 -0
  102. package/dist/preact/SchemaErrorBoundary.d.mts +2 -0
  103. package/dist/preact/SchemaErrorBoundary.mjs +20 -0
  104. package/dist/preact/SchemaView.d.mts +2 -0
  105. package/dist/preact/SchemaView.mjs +22 -0
  106. package/dist/preact/headless.d.mts +2 -0
  107. package/dist/preact/headless.mjs +18 -0
  108. package/dist/react/SchemaComponent.d.mts +3 -270
  109. package/dist/react/SchemaComponent.mjs +41 -32
  110. package/dist/react/SchemaView.d.mts +6 -6
  111. package/dist/react/SchemaView.mjs +32 -29
  112. package/dist/react/a11y.d.mts +2 -2
  113. package/dist/react/fieldShell.d.mts +1 -1
  114. package/dist/react/headless.d.mts +1 -1
  115. package/dist/react/headlessRenderers.d.mts +2 -2
  116. package/dist/{ref-DdsbekXX.d.mts → ref-DWrQG1Er.d.mts} +1 -1
  117. package/dist/renderer-ab9E52Bp.d.mts +245 -0
  118. package/dist/solid/SchemaComponent.d.mts +136 -0
  119. package/dist/solid/SchemaComponent.mjs +391 -0
  120. package/dist/solid/SchemaErrorBoundary.d.mts +38 -0
  121. package/dist/solid/SchemaErrorBoundary.mjs +57 -0
  122. package/dist/solid/SchemaField.d.mts +40 -0
  123. package/dist/solid/SchemaField.mjs +113 -0
  124. package/dist/solid/SchemaView.d.mts +54 -0
  125. package/dist/solid/SchemaView.mjs +168 -0
  126. package/dist/solid/a11y.d.mts +70 -0
  127. package/dist/solid/a11y.mjs +71 -0
  128. package/dist/solid/contexts.d.mts +37 -0
  129. package/dist/solid/contexts.mjs +66 -0
  130. package/dist/solid/headless.d.mts +10 -0
  131. package/dist/solid/headless.mjs +27 -0
  132. package/dist/solid/renderers.d.mts +79 -0
  133. package/dist/solid/renderers.mjs +840 -0
  134. package/dist/solid/types.d.mts +90 -0
  135. package/dist/solid/types.mjs +1 -0
  136. package/dist/solid/widget.d.mts +29 -0
  137. package/dist/solid/widget.mjs +35 -0
  138. package/dist/themes/mantine.d.mts +1 -1
  139. package/dist/themes/mui.d.mts +1 -1
  140. package/dist/themes/radix.d.mts +1 -1
  141. package/dist/themes/shadcn.d.mts +1 -1
  142. package/dist/typeInference-Y8tNEQJk.d.mts +983 -0
  143. package/dist/types-BCy7K3nk.d.mts +125 -0
  144. package/package.json +73 -1
  145. package/src/svelte/SchemaComponent.svelte +427 -0
  146. package/src/svelte/SchemaErrorBoundary.svelte +66 -0
  147. package/src/svelte/SchemaField.svelte +216 -0
  148. package/src/svelte/SchemaProvider.svelte +46 -0
  149. package/src/svelte/SchemaView.svelte +244 -0
  150. package/src/svelte/a11y.ts +112 -0
  151. package/src/svelte/contexts.ts +79 -0
  152. package/src/svelte/dispatch.ts +267 -0
  153. package/src/svelte/headless.ts +73 -0
  154. package/src/svelte/headlessFns.ts +124 -0
  155. package/src/svelte/renderers/Array.svelte +98 -0
  156. package/src/svelte/renderers/Boolean.svelte +43 -0
  157. package/src/svelte/renderers/Conditional.svelte +67 -0
  158. package/src/svelte/renderers/DiscriminatedUnion.svelte +197 -0
  159. package/src/svelte/renderers/Enum.svelte +53 -0
  160. package/src/svelte/renderers/Fallback.svelte +24 -0
  161. package/src/svelte/renderers/File.svelte +46 -0
  162. package/src/svelte/renderers/Literal.svelte +29 -0
  163. package/src/svelte/renderers/Mount.svelte +24 -0
  164. package/src/svelte/renderers/Negation.svelte +35 -0
  165. package/src/svelte/renderers/Never.svelte +24 -0
  166. package/src/svelte/renderers/Null.svelte +19 -0
  167. package/src/svelte/renderers/Number.svelte +68 -0
  168. package/src/svelte/renderers/Object.svelte +74 -0
  169. package/src/svelte/renderers/Record.svelte +134 -0
  170. package/src/svelte/renderers/RecursionSentinel.svelte +27 -0
  171. package/src/svelte/renderers/String.svelte +152 -0
  172. package/src/svelte/renderers/Tuple.svelte +84 -0
  173. package/src/svelte/renderers/Union.svelte +49 -0
  174. package/src/svelte/renderers/Unknown.svelte +42 -0
  175. package/src/svelte/svelte-modules.d.ts +25 -0
  176. package/src/svelte/types.ts +238 -0
  177. package/src/svelte/widget.ts +62 -0
  178. package/src/vue/SchemaComponent.vue +274 -0
  179. package/src/vue/SchemaErrorBoundary.vue +60 -0
  180. package/src/vue/SchemaField.vue +178 -0
  181. package/src/vue/SchemaProvider.vue +39 -0
  182. package/src/vue/SchemaView.vue +198 -0
  183. package/src/vue/VNodeHost.ts +32 -0
  184. package/src/vue/contexts.ts +116 -0
  185. package/src/vue/eventTargets.ts +35 -0
  186. package/src/vue/headless.ts +61 -0
  187. package/src/vue/idPrefix.ts +79 -0
  188. package/src/vue/renderField.ts +182 -0
  189. package/src/vue/renderers.ts +1297 -0
  190. package/src/vue/resolver.ts +45 -0
  191. package/src/vue/types.ts +140 -0
  192. package/src/vue/vue-shim.d.ts +25 -0
  193. package/src/vue/widget.ts +51 -0
  194. /package/dist/{diagnostics-BTrm3O6J.d.mts → diagnostics-mftUZI7c.d.mts} +0 -0
  195. /package/dist/{limits-x4OiyJxh.d.mts → limits-Vv9hUbI_.d.mts} +0 -0
  196. /package/dist/{types-BrYbjC7_.d.mts → types-BBQaEPfE.d.mts} +0 -0
  197. /package/dist/{version-DL8U5RuA.d.mts → version-BEBx10ND.d.mts} +0 -0
@@ -0,0 +1,391 @@
1
+ import { isObject, toRecordOrUndefined } from "../core/guards.mjs";
2
+ import "../core/limits.mjs";
3
+ import { SchemaNormalisationError, SchemaRenderError } from "../core/errors.mjs";
4
+ import { isCodecSchema, normaliseSchema } from "../core/adapter.mjs";
5
+ import { walk } from "../core/walker.mjs";
6
+ import { UserResolverContext, WidgetsContext } from "./contexts.mjs";
7
+ import { headlessSolidResolver } from "./headless.mjs";
8
+ import { lookupGlobalSolidWidget } from "./widget.mjs";
9
+ import { z } from "zod";
10
+ import { createMemo, createUniqueId, splitProps, useContext } from "solid-js";
11
+ import { jsx, jsxs } from "solid-js/jsx-runtime";
12
+ //#region src/solid/SchemaComponent.tsx
13
+ /** @jsxImportSource solid-js */
14
+ /**
15
+ * `<SchemaComponent>` — Solid renderer for Zod, JSON Schema, or OpenAPI
16
+ * inputs.
17
+ *
18
+ * Auto-detects the input format, normalises it to canonical JSON Schema
19
+ * via the shared adapter, walks the JSON Schema tree, and delegates
20
+ * per-field rendering to the {@link SolidComponentResolver} supplied via
21
+ * {@link SchemaProvider} — falling back to the headless renderer when
22
+ * no provider sits above this component.
23
+ *
24
+ * Key differences from the React adapter:
25
+ *
26
+ * - State is held in plain Solid signals (`createSignal`) rather than
27
+ * React's `useState`; the renderer does not keep its own copy of
28
+ * `value` — controlled mode is the only supported pattern, matching
29
+ * the React surface.
30
+ * - There are no per-render hooks. `useId` is replaced by
31
+ * `createUniqueId()`; `useMemo` / `useCallback` are unnecessary
32
+ * because Solid's fine-grained reactivity already avoids the
33
+ * re-allocation costs they exist to mitigate in React.
34
+ * - `splitProps` separates the renderer-internal props from those
35
+ * forwarded to the host primitive.
36
+ * - Context propagation uses Solid's `createContext` /
37
+ * `<Context.Provider>` (re-exported via `solid/contexts.ts`) — the
38
+ * public API matches the React `<SchemaProvider>` shape.
39
+ */
40
+ /**
41
+ * Provide a theme resolver and scoped widgets to every
42
+ * `<SchemaComponent>` rendered inside the subtree.
43
+ *
44
+ * Wrap an application (or a region of it) with `<SchemaProvider>` so a
45
+ * single resolver — typically a custom Solid `SolidComponentResolver`
46
+ * — drives every schema render. Without a provider the headless
47
+ * resolver is used.
48
+ *
49
+ * @group Components
50
+ * @example
51
+ * ```tsx
52
+ * import { SchemaProvider, SchemaComponent } from "schema-components/solid/SchemaComponent";
53
+ *
54
+ * <SchemaProvider resolver={customResolver}>
55
+ * <SchemaComponent schema={userSchema} value={user} onChange={setUser} />
56
+ * </SchemaProvider>
57
+ * ```
58
+ */
59
+ function SchemaProvider(props) {
60
+ return /* @__PURE__ */ jsx(UserResolverContext.Provider, {
61
+ value: props.resolver,
62
+ children: /* @__PURE__ */ jsx(WidgetsContext.Provider, {
63
+ value: props.widgets,
64
+ children: props.children
65
+ })
66
+ });
67
+ }
68
+ /**
69
+ * Append a child path suffix to a parent path. When the suffix is
70
+ * omitted (e.g. transparent wrappers like union options) the parent
71
+ * path is returned unchanged so the child inherits the parent's id.
72
+ *
73
+ * Bracketed array indices like `"[0]"` append directly so `tags` +
74
+ * `"[0]"` becomes `tags[0]` rather than `tags.[0]` — matching the
75
+ * canonical form used by every shared id helper in `core/idPath.ts`.
76
+ */
77
+ function joinPath(parent, suffix) {
78
+ if (suffix === void 0 || suffix.length === 0) return parent;
79
+ if (parent.length === 0) return suffix;
80
+ if (suffix.startsWith("[")) return `${parent}${suffix}`;
81
+ return `${parent}.${suffix}`;
82
+ }
83
+ /**
84
+ * Normalise a `createUniqueId()` value into a DOM-id-safe prefix.
85
+ * Solid's `createUniqueId()` already returns a usable id, but consumers
86
+ * may also pass a label-derived string. Replace any run of
87
+ * non-alphanumeric characters with a single hyphen and trim leading
88
+ * and trailing hyphens.
89
+ */
90
+ function sanitisePrefix(value) {
91
+ const sanitised = value.replace(/[^a-zA-Z0-9_]+/g, "-").replace(/^-+|-+$/g, "");
92
+ if (sanitised.length === 0) throw new Error(`Cannot derive a DOM-safe id prefix from "${value}". Pass an explicit idPrefix prop.`);
93
+ return sanitised;
94
+ }
95
+ /**
96
+ * Render a single walked field through the resolved widget / resolver /
97
+ * headless pipeline. Used internally by {@link SchemaComponent} and
98
+ * exported so other Solid-side components (e.g. theme adapters) can
99
+ * dispatch into the same fallback chain.
100
+ */
101
+ function renderField(tree, value, onChange, userResolver, renderChild, path, instanceWidgets, contextWidgets, depth = 0) {
102
+ if (path.length === 0) throw new Error("renderField requires a non-empty path. Pass the root path (derived from `idPrefix` or `createUniqueId()`) for the root field, and use renderChild's pathSuffix to derive child paths.");
103
+ if (depth >= 10) return /* @__PURE__ */ jsx("fieldset", { children: /* @__PURE__ */ jsxs("em", { children: [
104
+ "↻ ",
105
+ typeof tree.meta.description === "string" ? tree.meta.description : "schema",
106
+ " (recursive)"
107
+ ] }) });
108
+ const componentHint = tree.meta.component;
109
+ if (typeof componentHint === "string") {
110
+ const widget = instanceWidgets?.get(componentHint) ?? contextWidgets?.get(componentHint) ?? lookupGlobalSolidWidget(componentHint);
111
+ if (widget !== void 0) {
112
+ const result = widget(buildSolidProps(tree, value, onChange, renderChild, path));
113
+ if (result !== null && result !== void 0) return result;
114
+ }
115
+ }
116
+ const resolver = userResolver !== void 0 ? mergeSolidResolvers(userResolver, headlessSolidResolver) : headlessSolidResolver;
117
+ const renderFn = getSolidRenderFunction(tree.type, resolver);
118
+ if (renderFn !== void 0) {
119
+ let result;
120
+ try {
121
+ result = renderFn(buildSolidProps(tree, value, onChange, renderChild, path));
122
+ } catch (err) {
123
+ throw new SchemaRenderError(err instanceof Error ? err.message : `Render function threw for type "${tree.type}"`, tree, tree.type, err);
124
+ }
125
+ if (result !== null && result !== void 0) return result;
126
+ }
127
+ if (value === void 0 || value === null) return /* @__PURE__ */ jsx("span", { children: "—" });
128
+ return /* @__PURE__ */ jsx("span", { children: typeof value === "string" ? value : JSON.stringify(value) });
129
+ }
130
+ /**
131
+ * Build the Solid render props for a single field. Inlines the
132
+ * editability resolution from `core/renderer.ts` `buildRenderProps`
133
+ * because the React variant of that helper types its `renderChild`
134
+ * parameter against React's `renderChild` signature (returns
135
+ * `unknown`); Solid's signature returns `JSX.Element`, so we
136
+ * compose the same shape locally rather than route through a function
137
+ * whose static type does not accept the Solid signature.
138
+ *
139
+ * Editability resolution matches `buildRenderProps`:
140
+ *
141
+ * - `readOnly` is forced to `true` if `onChange` was supplied as the
142
+ * no-op (i.e. the caller passed `undefined`); the dispatcher does
143
+ * not currently exercise the read-only path on this surface (the
144
+ * Solid `<SchemaView>` component handles that) but the contract is
145
+ * the same.
146
+ * - `writeOnly` is taken from `tree.editability === "input"`.
147
+ */
148
+ function buildSolidProps(tree, value, onChange, renderChild, path) {
149
+ const props = {
150
+ value,
151
+ readOnly: tree.editability === "presentation",
152
+ writeOnly: tree.editability === "input",
153
+ meta: tree.meta,
154
+ constraints: tree.constraints,
155
+ path,
156
+ tree,
157
+ onChange,
158
+ renderChild
159
+ };
160
+ if (tree.examples !== void 0) props.examples = tree.examples;
161
+ return props;
162
+ }
163
+ /**
164
+ * Merge two `SolidComponentResolver` instances — user values win,
165
+ * fallback fills gaps. Local parallel to `core/renderer.ts`
166
+ * `mergeResolvers` (which is typed against React's resolver shape).
167
+ */
168
+ function mergeSolidResolvers(user, fallback) {
169
+ const merged = {};
170
+ for (const key of [
171
+ "string",
172
+ "number",
173
+ "boolean",
174
+ "null",
175
+ "enum",
176
+ "object",
177
+ "array",
178
+ "tuple",
179
+ "record",
180
+ "union",
181
+ "discriminatedUnion",
182
+ "conditional",
183
+ "negation",
184
+ "literal",
185
+ "file",
186
+ "never",
187
+ "unknown"
188
+ ]) {
189
+ const fn = user[key] ?? fallback[key];
190
+ if (fn !== void 0) merged[key] = fn;
191
+ }
192
+ return merged;
193
+ }
194
+ /** Look up the render function for a schema type in a Solid resolver. */
195
+ function getSolidRenderFunction(type, resolver) {
196
+ return resolver[type];
197
+ }
198
+ /**
199
+ * Render an editable (or read-only) UI from a Zod schema, JSON Schema,
200
+ * or OpenAPI document.
201
+ *
202
+ * Auto-detects the input format, normalises to JSON Schema via the
203
+ * shared adapter, walks the JSON Schema tree, and delegates per-field
204
+ * rendering to the {@link SolidComponentResolver} supplied via
205
+ * {@link SchemaProvider} — falling back to the headless renderer when
206
+ * no provider is present.
207
+ *
208
+ * Pass `readOnly` to render a presentational view instead of inputs.
209
+ *
210
+ * @group Components
211
+ * @example
212
+ * ```tsx
213
+ * import { z } from "zod";
214
+ * import { SchemaComponent } from "schema-components/solid/SchemaComponent";
215
+ *
216
+ * const userSchema = z.object({ name: z.string(), email: z.email() });
217
+ *
218
+ * <SchemaComponent schema={userSchema} value={user} onChange={setUser} />
219
+ * ```
220
+ */
221
+ function SchemaComponent(props) {
222
+ const [, rest] = splitProps(props, ["schema"]);
223
+ const schemaInput = props.schema;
224
+ const generatedId = createUniqueId();
225
+ const userResolver = readUserResolver();
226
+ const contextWidgets = readWidgets();
227
+ const computed = createMemo(() => {
228
+ const componentMeta = rest.meta;
229
+ const readOnly = rest.readOnly;
230
+ const writeOnly = rest.writeOnly;
231
+ const description = rest.description;
232
+ const onDiagnostic = rest.onDiagnostic;
233
+ const strict = rest.strict;
234
+ const io = rest.io;
235
+ const refInput = rest.ref;
236
+ const onError = rest.onError;
237
+ const idPrefix = rest.idPrefix;
238
+ const mergedMeta = { ...componentMeta };
239
+ if (readOnly === true) mergedMeta.readOnly = true;
240
+ if (writeOnly === true) mergedMeta.writeOnly = true;
241
+ if (description !== void 0) mergedMeta.description = description;
242
+ const diagnostics = onDiagnostic !== void 0 || strict === true ? {
243
+ ...onDiagnostic !== void 0 ? { diagnostics: onDiagnostic } : {},
244
+ ...strict !== void 0 ? { strict } : {}
245
+ } : void 0;
246
+ let jsonSchema;
247
+ let zodSchema;
248
+ let rootMeta;
249
+ let rootDocument;
250
+ let normaliseError;
251
+ try {
252
+ const normalised = normaliseSchema(schemaInput, refInput, diagnostics !== void 0 || io !== void 0 ? {
253
+ ...diagnostics !== void 0 ? { diagnostics } : {},
254
+ ...io !== void 0 ? { io } : {}
255
+ } : void 0);
256
+ jsonSchema = normalised.jsonSchema;
257
+ zodSchema = normalised.zodSchema;
258
+ rootMeta = normalised.rootMeta;
259
+ rootDocument = normalised.rootDocument;
260
+ } catch (err) {
261
+ normaliseError = err instanceof SchemaNormalisationError ? err : new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schemaInput, "unknown");
262
+ }
263
+ const rootPath = idPrefix ?? sanitisePrefix(generatedId);
264
+ return {
265
+ jsonSchema,
266
+ zodSchema,
267
+ rootMeta,
268
+ rootDocument,
269
+ mergedMeta,
270
+ diagnostics,
271
+ normaliseError,
272
+ rootPath,
273
+ onError,
274
+ io
275
+ };
276
+ });
277
+ const renderTree = () => {
278
+ const { jsonSchema, zodSchema, rootMeta, rootDocument, mergedMeta, diagnostics, normaliseError, rootPath, onError, io } = computed();
279
+ if (normaliseError !== void 0) {
280
+ if (onError !== void 0) {
281
+ onError(normaliseError);
282
+ return null;
283
+ }
284
+ throw normaliseError;
285
+ }
286
+ if (jsonSchema === void 0 || rootDocument === void 0) return null;
287
+ const fieldsRecord = toRecordOrUndefined(rest.fields);
288
+ const tree = walk(jsonSchema, {
289
+ componentMeta: mergedMeta,
290
+ rootMeta,
291
+ fieldOverrides: fieldsRecord,
292
+ rootDocument,
293
+ ...diagnostics !== void 0 ? { diagnostics } : {}
294
+ });
295
+ const handleChange = (nextValue) => {
296
+ if (rest.validate === true) {
297
+ const error = runValidation(zodSchema, jsonSchema, nextValue, io, rest.onDiagnostic);
298
+ if (error !== void 0) {
299
+ rest.onValidationError?.(error);
300
+ dispatchFieldErrors(fieldsRecord, error);
301
+ }
302
+ }
303
+ if (rest.onChange !== void 0) rest.onChange(nextValue);
304
+ };
305
+ const makeRenderChild = (currentDepth, parentPath) => (childTree, childValue, childOnChange, pathSuffix) => {
306
+ const childPath = joinPath(parentPath, pathSuffix);
307
+ return renderField(childTree, childValue, childOnChange, userResolver, makeRenderChild(currentDepth + 1, childPath), childPath, rest.widgets, contextWidgets, currentDepth + 1);
308
+ };
309
+ const renderChild = makeRenderChild(0, rootPath);
310
+ return renderField(tree, rest.value ?? tree.defaultValue, handleChange, userResolver, renderChild, rootPath, rest.widgets, contextWidgets, 0);
311
+ };
312
+ return renderTree();
313
+ }
314
+ function readUserResolver() {
315
+ return useContext(UserResolverContext);
316
+ }
317
+ function readWidgets() {
318
+ return useContext(WidgetsContext);
319
+ }
320
+ /**
321
+ * Run validation against the supplied value.
322
+ *
323
+ * Mirrors the React adapter's `runValidation`. Returns the validation
324
+ * error on failure or `undefined` when the value is valid. Throws
325
+ * `SchemaNormalisationError` (kind `zod-conversion-failed`) when the
326
+ * `z.fromJSONSchema` fallback path is taken AND no diagnostic sink
327
+ * is wired up — mirroring the React adapter's no-silent-fallback
328
+ * contract.
329
+ */
330
+ function runValidation(zodSchema, jsonSchema, value, io, onDiagnostic) {
331
+ if (zodSchema !== void 0 && isObject(zodSchema)) {
332
+ const resolvedIo = io ?? "output";
333
+ const validateFn = isCodecSchema(zodSchema) && resolvedIo === "output" ? zodSchema.safeEncode : zodSchema.safeParse;
334
+ if (isCallable(validateFn)) {
335
+ const result = validateFn(value);
336
+ if (isObject(result) && "success" in result && result.success !== true) return result.error;
337
+ return;
338
+ }
339
+ }
340
+ let parsed;
341
+ try {
342
+ parsed = z.fromJSONSchema(jsonSchema);
343
+ } catch (err) {
344
+ if (onDiagnostic !== void 0) {
345
+ onDiagnostic({
346
+ code: "unsupported-type",
347
+ message: `Skipping fallback validation: z.fromJSONSchema could not round-trip the normalised JSON Schema. Original message: ${err instanceof Error ? err.message : "z.fromJSONSchema threw a non-Error value"}`,
348
+ pointer: "",
349
+ detail: { source: "z.fromJSONSchema" }
350
+ });
351
+ return;
352
+ }
353
+ throw new SchemaNormalisationError(`Fallback validation failed: z.fromJSONSchema could not round-trip the normalised JSON Schema. Original message: ${err instanceof Error ? err.message : "z.fromJSONSchema threw a non-Error value"}`, jsonSchema, "zod-conversion-failed", void 0, err);
354
+ }
355
+ if (isObject(parsed)) {
356
+ const safeParseFn = parsed.safeParse;
357
+ if (isCallable(safeParseFn)) {
358
+ const result = safeParseFn(value);
359
+ if (isObject(result) && "success" in result && result.success !== true) return result.error;
360
+ }
361
+ }
362
+ }
363
+ function isCallable(value) {
364
+ return typeof value === "function";
365
+ }
366
+ function dispatchFieldErrors(fields, error) {
367
+ if (fields === void 0 || !isObject(error)) return;
368
+ if (!("issues" in error)) return;
369
+ const issues = error.issues;
370
+ if (!Array.isArray(issues)) return;
371
+ for (const [key, override] of Object.entries(fields)) {
372
+ if (override === void 0 || typeof override !== "object") continue;
373
+ if (override === null) continue;
374
+ if (!("onValidationError" in override)) continue;
375
+ const fieldCallback = override.onValidationError;
376
+ if (typeof fieldCallback !== "function") continue;
377
+ const fieldErrors = issues.filter((issue) => {
378
+ if (!isObject(issue)) return false;
379
+ if (!("path" in issue)) return false;
380
+ const path = issue.path;
381
+ if (!Array.isArray(path)) return false;
382
+ return path[0] === key;
383
+ });
384
+ if (fieldErrors.length > 0 && isFieldErrorCallback(fieldCallback)) fieldCallback({ issues: fieldErrors });
385
+ }
386
+ }
387
+ function isFieldErrorCallback(value) {
388
+ return typeof value === "function";
389
+ }
390
+ //#endregion
391
+ export { SchemaComponent, SchemaProvider, joinPath, renderField, sanitisePrefix };
@@ -0,0 +1,38 @@
1
+ import { JSX } from "solid-js";
2
+
3
+ //#region src/solid/SchemaErrorBoundary.d.ts
4
+ /**
5
+ * Props accepted by {@link SchemaErrorBoundary}.
6
+ *
7
+ * @group Components
8
+ */
9
+ interface SchemaErrorBoundaryProps {
10
+ /**
11
+ * Called with the caught error and a `reset` callback that clears
12
+ * the error state so children can re-mount. Mirrors the React
13
+ * adapter's signature.
14
+ */
15
+ fallback: (error: Error, reset: () => void) => JSX.Element;
16
+ children: JSX.Element;
17
+ }
18
+ /**
19
+ * Catch rendering errors from `<SchemaComponent>`, theme adapters, and
20
+ * any descendant. Wraps Solid's built-in `<ErrorBoundary>` so the API
21
+ * shape matches `react/SchemaErrorBoundary.tsx`.
22
+ *
23
+ * Solid's `ErrorBoundary` accepts `unknown` errors. The wrapper
24
+ * coerces non-`Error` throws into a generic `Error` with the original
25
+ * value's stringified form so consumers always receive an `Error`
26
+ * instance.
27
+ *
28
+ * @group Components
29
+ * @example
30
+ * ```tsx
31
+ * <SchemaErrorBoundary fallback={(error) => <p>{error.message}</p>}>
32
+ * <SchemaComponent schema={userSchema} value={user} onChange={setUser} />
33
+ * </SchemaErrorBoundary>
34
+ * ```
35
+ */
36
+ declare function SchemaErrorBoundary(props: SchemaErrorBoundaryProps): JSX.Element;
37
+ //#endregion
38
+ export { SchemaErrorBoundary, SchemaErrorBoundaryProps };
@@ -0,0 +1,57 @@
1
+ import { SchemaError } from "../core/errors.mjs";
2
+ import { ErrorBoundary } from "solid-js";
3
+ import { jsx } from "solid-js/jsx-runtime";
4
+ //#region src/solid/SchemaErrorBoundary.tsx
5
+ /** @jsxImportSource solid-js */
6
+ /**
7
+ * Solid error boundary for schema-components.
8
+ *
9
+ * Wraps children in Solid's built-in `<ErrorBoundary>` and forwards the
10
+ * caught error to a consumer-supplied `fallback` callback. Catches
11
+ * render errors from `<SchemaComponent>`, theme adapters, and any
12
+ * descendant — without this boundary, a throwing render function
13
+ * propagates to the nearest enclosing root and tears down the entire
14
+ * subtree.
15
+ *
16
+ * `SchemaError` instances (the structured failures emitted by
17
+ * `<SchemaComponent>`'s normalisation and validation pipeline) are
18
+ * routed without console noise — the consumer's `onError` prop on the
19
+ * upstream `<SchemaComponent>` already handled them. Other errors are
20
+ * logged once to `console.error` for unhandled-failure visibility,
21
+ * matching the React adapter's behaviour.
22
+ *
23
+ * Does not catch:
24
+ * - Errors thrown from event handlers (onChange, etc.).
25
+ * - Asynchronous errors.
26
+ * - Errors in server-side rendering (Solid Start has its own model).
27
+ */
28
+ /**
29
+ * Catch rendering errors from `<SchemaComponent>`, theme adapters, and
30
+ * any descendant. Wraps Solid's built-in `<ErrorBoundary>` so the API
31
+ * shape matches `react/SchemaErrorBoundary.tsx`.
32
+ *
33
+ * Solid's `ErrorBoundary` accepts `unknown` errors. The wrapper
34
+ * coerces non-`Error` throws into a generic `Error` with the original
35
+ * value's stringified form so consumers always receive an `Error`
36
+ * instance.
37
+ *
38
+ * @group Components
39
+ * @example
40
+ * ```tsx
41
+ * <SchemaErrorBoundary fallback={(error) => <p>{error.message}</p>}>
42
+ * <SchemaComponent schema={userSchema} value={user} onChange={setUser} />
43
+ * </SchemaErrorBoundary>
44
+ * ```
45
+ */
46
+ function SchemaErrorBoundary(props) {
47
+ return /* @__PURE__ */ jsx(ErrorBoundary, {
48
+ fallback: (err, reset) => {
49
+ const error = err instanceof Error ? err : new Error(typeof err === "string" ? err : "Unknown render error");
50
+ if (!(error instanceof SchemaError)) console.error("[schema-components] Unhandled render error:", error);
51
+ return props.fallback(error, reset);
52
+ },
53
+ children: props.children
54
+ });
55
+ }
56
+ //#endregion
57
+ export { SchemaErrorBoundary };
@@ -0,0 +1,40 @@
1
+ import { w as SchemaMeta } from "../types-BBQaEPfE.mjs";
2
+ import { d as PathOfType, f as RejectUnrepresentableZod, r as FromJSONSchema } from "../typeInference-Y8tNEQJk.mjs";
3
+ import { z } from "zod";
4
+ import { JSX } from "solid-js";
5
+
6
+ //#region src/solid/SchemaField.d.ts
7
+ /**
8
+ * Infer the schema's output type for SchemaField path inference.
9
+ */
10
+ type InferSchemaType<T> = T extends z.ZodType ? z.infer<T> : T extends object ? unknown extends FromJSONSchema<T> ? unknown : FromJSONSchema<T> : unknown;
11
+ /**
12
+ * Props accepted by {@link SchemaField}. The generic `P` constrains
13
+ * `path` to dot-paths reachable through the schema's inferred value
14
+ * type — typed schemas get autocomplete; runtime schemas fall back to
15
+ * `string`.
16
+ *
17
+ * @group Components
18
+ */
19
+ interface SchemaFieldProps<T = unknown, Ref extends string | undefined = undefined, P extends string = PathOfType<InferSchemaType<T>> | (string extends PathOfType<InferSchemaType<T>> ? string : never)> {
20
+ path: P;
21
+ schema: RejectUnrepresentableZod<T>;
22
+ ref?: Ref;
23
+ value?: unknown;
24
+ onChange?: (value: unknown) => void;
25
+ meta?: SchemaMeta;
26
+ validate?: boolean;
27
+ onValidationError?: (error: unknown) => void;
28
+ }
29
+ /**
30
+ * Render a single field from a schema by dot-separated `path`.
31
+ *
32
+ * Walks the full schema tree, resolves the field at the supplied
33
+ * `path`, then renders only that field through the same resolver
34
+ * pipeline as `<SchemaComponent>`.
35
+ *
36
+ * @group Components
37
+ */
38
+ declare function SchemaField<T = unknown, Ref extends string | undefined = undefined, P extends string = PathOfType<InferSchemaType<T>> | (string extends PathOfType<InferSchemaType<T>> ? string : never)>(props: SchemaFieldProps<T, Ref, P>): JSX.Element;
39
+ //#endregion
40
+ export { SchemaField, SchemaFieldProps };
@@ -0,0 +1,113 @@
1
+ import { isObject } from "../core/guards.mjs";
2
+ import { SchemaFieldError, SchemaNormalisationError } from "../core/errors.mjs";
3
+ import { isCodecSchema, normaliseSchema } from "../core/adapter.mjs";
4
+ import { resolvePath, resolveValue, setNestedValue } from "../core/fieldPath.mjs";
5
+ import { walk } from "../core/walker.mjs";
6
+ import { UserResolverContext, WidgetsContext } from "./contexts.mjs";
7
+ import { joinPath, renderField, sanitisePrefix } from "./SchemaComponent.mjs";
8
+ import { z } from "zod";
9
+ import { createUniqueId, useContext } from "solid-js";
10
+ //#region src/solid/SchemaField.tsx
11
+ /** @jsxImportSource solid-js */
12
+ /**
13
+ * `<SchemaField>` — render a single field from a Solid schema by
14
+ * dot-separated `path`.
15
+ *
16
+ * Mirrors the React adapter's `<SchemaField>`. Walks the full schema
17
+ * tree, resolves the field at the supplied `path`, then renders only
18
+ * that field through the same resolver pipeline as `<SchemaComponent>`.
19
+ *
20
+ * Reads context bindings (`UserResolverContext`, `WidgetsContext`)
21
+ * exposed by `<SchemaProvider>`, so a single provider drives every
22
+ * `<SchemaField>` inside its subtree just as it does for
23
+ * `<SchemaComponent>`.
24
+ */
25
+ /**
26
+ * Render a single field from a schema by dot-separated `path`.
27
+ *
28
+ * Walks the full schema tree, resolves the field at the supplied
29
+ * `path`, then renders only that field through the same resolver
30
+ * pipeline as `<SchemaComponent>`.
31
+ *
32
+ * @group Components
33
+ */
34
+ function SchemaField(props) {
35
+ const generatedId = createUniqueId();
36
+ const userResolver = useContext(UserResolverContext);
37
+ const contextWidgets = useContext(WidgetsContext);
38
+ let jsonSchema;
39
+ let zodSchema;
40
+ let rootMeta;
41
+ let rootDocument;
42
+ try {
43
+ const normalised = normaliseSchema(props.schema, props.ref);
44
+ jsonSchema = normalised.jsonSchema;
45
+ zodSchema = normalised.zodSchema;
46
+ rootMeta = normalised.rootMeta;
47
+ rootDocument = normalised.rootDocument;
48
+ } catch (err) {
49
+ if (err instanceof SchemaNormalisationError) throw err;
50
+ throw new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", props.schema, "unknown");
51
+ }
52
+ const walkOptions = {
53
+ componentMeta: props.meta,
54
+ rootMeta,
55
+ rootDocument
56
+ };
57
+ const fieldTree = resolvePath(walk(jsonSchema, walkOptions), props.path);
58
+ if (fieldTree === void 0) throw new SchemaFieldError(`Field not found: ${props.path}`, props.schema, props.path);
59
+ const fieldValue = resolveValue(props.value, props.path);
60
+ const handleChange = (nextFieldValue) => {
61
+ const newRootValue = setNestedValue(props.value, props.path, nextFieldValue);
62
+ if (props.validate === true) {
63
+ const error = runFieldValidation(zodSchema, jsonSchema, newRootValue);
64
+ if (error !== void 0) props.onValidationError?.(error);
65
+ }
66
+ props.onChange?.(newRootValue);
67
+ };
68
+ const rootPath = joinPath(sanitisePrefix(generatedId), props.path);
69
+ const makeRenderChild = (currentDepth, parentPath) => (childTree, childValue, childOnChange, pathSuffix) => {
70
+ const childPath = joinPath(parentPath, pathSuffix);
71
+ return renderField(childTree, childValue, childOnChange, userResolver, makeRenderChild(currentDepth + 1, childPath), childPath, void 0, contextWidgets, currentDepth + 1);
72
+ };
73
+ return renderField(fieldTree, fieldValue, handleChange, userResolver, makeRenderChild(0, rootPath), rootPath, void 0, contextWidgets, 0);
74
+ }
75
+ function isCallable(value) {
76
+ return typeof value === "function";
77
+ }
78
+ function runFieldValidation(zodSchema, jsonSchema, value, io, onDiagnostic) {
79
+ if (zodSchema !== void 0 && isObject(zodSchema)) {
80
+ const resolvedIo = io ?? "output";
81
+ const validateFn = isCodecSchema(zodSchema) && resolvedIo === "output" ? zodSchema.safeEncode : zodSchema.safeParse;
82
+ if (isCallable(validateFn)) {
83
+ const result = validateFn(value);
84
+ if (isObject(result) && "success" in result && result.success !== true) return result.error;
85
+ return;
86
+ }
87
+ }
88
+ let parsed;
89
+ try {
90
+ parsed = z.fromJSONSchema(jsonSchema);
91
+ } catch (err) {
92
+ const message = err instanceof Error ? err.message : "z.fromJSONSchema threw a non-Error value";
93
+ if (onDiagnostic !== void 0) {
94
+ onDiagnostic({
95
+ code: "unsupported-type",
96
+ message: `Skipping fallback validation: z.fromJSONSchema could not round-trip the normalised JSON Schema. Original message: ${message}`,
97
+ pointer: "",
98
+ detail: { source: "z.fromJSONSchema" }
99
+ });
100
+ return;
101
+ }
102
+ throw new SchemaNormalisationError(`Fallback validation failed: z.fromJSONSchema could not round-trip the normalised JSON Schema. Original message: ${message}`, jsonSchema, "zod-conversion-failed", void 0, err);
103
+ }
104
+ if (isObject(parsed)) {
105
+ const safeParseFn = parsed.safeParse;
106
+ if (isCallable(safeParseFn)) {
107
+ const result = safeParseFn(value);
108
+ if (isObject(result) && "success" in result && result.success !== true) return result.error;
109
+ }
110
+ }
111
+ }
112
+ //#endregion
113
+ export { SchemaField };