schema-components 2.0.2 → 2.1.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 (180) hide show
  1. package/README.md +98 -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 +81 -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 +3 -3
  39. package/dist/{inferValue-Ce-PviSD.d.mts → inferValue-eAnh50EM.d.mts} +3 -3
  40. package/dist/lit/SchemaComponent.d.mts +125 -0
  41. package/dist/lit/SchemaComponent.mjs +2 -0
  42. package/dist/lit/SchemaField.d.mts +65 -0
  43. package/dist/lit/SchemaField.mjs +2 -0
  44. package/dist/lit/SchemaView.d.mts +14 -0
  45. package/dist/lit/SchemaView.mjs +2 -0
  46. package/dist/lit/constructorTypes.d.mts +2 -0
  47. package/dist/lit/constructorTypes.mjs +1 -0
  48. package/dist/lit/contexts.d.mts +78 -0
  49. package/dist/lit/contexts.mjs +238 -0
  50. package/dist/lit/defaultResolver.d.mts +33 -0
  51. package/dist/lit/defaultResolver.mjs +2 -0
  52. package/dist/lit/registry.d.mts +66 -0
  53. package/dist/lit/registry.mjs +2 -0
  54. package/dist/lit/renderers/baseElement.d.mts +131 -0
  55. package/dist/lit/renderers/baseElement.mjs +109 -0
  56. package/dist/lit/renderers/recordHelpers.d.mts +25 -0
  57. package/dist/lit/renderers/recordHelpers.mjs +55 -0
  58. package/dist/lit/renderers/scArray.d.mts +14 -0
  59. package/dist/lit/renderers/scArray.mjs +86 -0
  60. package/dist/lit/renderers/scBoolean.d.mts +15 -0
  61. package/dist/lit/renderers/scBoolean.mjs +47 -0
  62. package/dist/lit/renderers/scConditional.d.mts +23 -0
  63. package/dist/lit/renderers/scConditional.mjs +65 -0
  64. package/dist/lit/renderers/scDiscriminated.d.mts +23 -0
  65. package/dist/lit/renderers/scDiscriminated.mjs +138 -0
  66. package/dist/lit/renderers/scEnum.d.mts +16 -0
  67. package/dist/lit/renderers/scEnum.mjs +66 -0
  68. package/dist/lit/renderers/scFile.d.mts +15 -0
  69. package/dist/lit/renderers/scFile.mjs +53 -0
  70. package/dist/lit/renderers/scLiteralNullNever.d.mts +30 -0
  71. package/dist/lit/renderers/scLiteralNullNever.mjs +57 -0
  72. package/dist/lit/renderers/scNumber.d.mts +15 -0
  73. package/dist/lit/renderers/scNumber.mjs +64 -0
  74. package/dist/lit/renderers/scObject.d.mts +14 -0
  75. package/dist/lit/renderers/scObject.mjs +57 -0
  76. package/dist/lit/renderers/scRecord.d.mts +14 -0
  77. package/dist/lit/renderers/scRecord.mjs +112 -0
  78. package/dist/lit/renderers/scString.d.mts +19 -0
  79. package/dist/lit/renderers/scString.mjs +165 -0
  80. package/dist/lit/renderers/scTuple.d.mts +14 -0
  81. package/dist/lit/renderers/scTuple.mjs +58 -0
  82. package/dist/lit/renderers/scUnion.d.mts +14 -0
  83. package/dist/lit/renderers/scUnion.mjs +44 -0
  84. package/dist/lit/renderers/scUnknown.d.mts +15 -0
  85. package/dist/lit/renderers/scUnknown.mjs +45 -0
  86. package/dist/lit/ssr.d.mts +37 -0
  87. package/dist/lit/ssr.mjs +9565 -0
  88. package/dist/lit/types.d.mts +2 -0
  89. package/dist/lit/types.mjs +1 -0
  90. package/dist/lit/widget.d.mts +71 -0
  91. package/dist/lit/widget.mjs +87 -0
  92. package/dist/openapi/ApiCallbacks.d.mts +1 -1
  93. package/dist/openapi/ApiLinks.d.mts +1 -1
  94. package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
  95. package/dist/openapi/ApiSecurity.d.mts +1 -1
  96. package/dist/openapi/components.d.mts +4 -4
  97. package/dist/openapi/parser.d.mts +2 -2
  98. package/dist/openapi/resolve.d.mts +1 -1
  99. package/dist/preact/SchemaComponent.d.mts +3 -0
  100. package/dist/preact/SchemaComponent.mjs +26 -0
  101. package/dist/preact/SchemaErrorBoundary.d.mts +2 -0
  102. package/dist/preact/SchemaErrorBoundary.mjs +20 -0
  103. package/dist/preact/SchemaView.d.mts +2 -0
  104. package/dist/preact/SchemaView.mjs +22 -0
  105. package/dist/preact/headless.d.mts +2 -0
  106. package/dist/preact/headless.mjs +18 -0
  107. package/dist/react/SchemaComponent.d.mts +3 -270
  108. package/dist/react/SchemaComponent.mjs +41 -32
  109. package/dist/react/SchemaView.d.mts +6 -6
  110. package/dist/react/SchemaView.mjs +32 -29
  111. package/dist/react/a11y.d.mts +2 -2
  112. package/dist/react/fieldShell.d.mts +1 -1
  113. package/dist/react/headless.d.mts +1 -1
  114. package/dist/react/headlessRenderers.d.mts +2 -2
  115. package/dist/{ref-DdsbekXX.d.mts → ref-DWrQG1Er.d.mts} +1 -1
  116. package/dist/renderer-ab9E52Bp.d.mts +245 -0
  117. package/dist/solid/SchemaComponent.d.mts +136 -0
  118. package/dist/solid/SchemaComponent.mjs +391 -0
  119. package/dist/solid/SchemaErrorBoundary.d.mts +38 -0
  120. package/dist/solid/SchemaErrorBoundary.mjs +57 -0
  121. package/dist/solid/SchemaField.d.mts +40 -0
  122. package/dist/solid/SchemaField.mjs +113 -0
  123. package/dist/solid/SchemaView.d.mts +54 -0
  124. package/dist/solid/SchemaView.mjs +168 -0
  125. package/dist/solid/a11y.d.mts +70 -0
  126. package/dist/solid/a11y.mjs +71 -0
  127. package/dist/solid/contexts.d.mts +37 -0
  128. package/dist/solid/contexts.mjs +66 -0
  129. package/dist/solid/headless.d.mts +10 -0
  130. package/dist/solid/headless.mjs +27 -0
  131. package/dist/solid/renderers.d.mts +79 -0
  132. package/dist/solid/renderers.mjs +840 -0
  133. package/dist/solid/types.d.mts +90 -0
  134. package/dist/solid/types.mjs +1 -0
  135. package/dist/solid/widget.d.mts +29 -0
  136. package/dist/solid/widget.mjs +35 -0
  137. package/dist/themes/mantine.d.mts +1 -1
  138. package/dist/themes/mui.d.mts +1 -1
  139. package/dist/themes/radix.d.mts +1 -1
  140. package/dist/themes/shadcn.d.mts +1 -1
  141. package/dist/typeInference-Y8tNEQJk.d.mts +983 -0
  142. package/dist/types-BCy7K3nk.d.mts +125 -0
  143. package/package.json +71 -1
  144. package/src/svelte/SchemaComponent.svelte +427 -0
  145. package/src/svelte/SchemaErrorBoundary.svelte +66 -0
  146. package/src/svelte/SchemaField.svelte +216 -0
  147. package/src/svelte/SchemaProvider.svelte +46 -0
  148. package/src/svelte/SchemaView.svelte +244 -0
  149. package/src/svelte/a11y.ts +112 -0
  150. package/src/svelte/contexts.ts +79 -0
  151. package/src/svelte/dispatch.ts +267 -0
  152. package/src/svelte/headless.ts +73 -0
  153. package/src/svelte/headlessFns.ts +124 -0
  154. package/src/svelte/renderers/Array.svelte +98 -0
  155. package/src/svelte/renderers/Boolean.svelte +43 -0
  156. package/src/svelte/renderers/Conditional.svelte +67 -0
  157. package/src/svelte/renderers/DiscriminatedUnion.svelte +197 -0
  158. package/src/svelte/renderers/Enum.svelte +53 -0
  159. package/src/svelte/renderers/Fallback.svelte +24 -0
  160. package/src/svelte/renderers/File.svelte +46 -0
  161. package/src/svelte/renderers/Literal.svelte +29 -0
  162. package/src/svelte/renderers/Mount.svelte +24 -0
  163. package/src/svelte/renderers/Negation.svelte +35 -0
  164. package/src/svelte/renderers/Never.svelte +24 -0
  165. package/src/svelte/renderers/Null.svelte +19 -0
  166. package/src/svelte/renderers/Number.svelte +68 -0
  167. package/src/svelte/renderers/Object.svelte +74 -0
  168. package/src/svelte/renderers/Record.svelte +134 -0
  169. package/src/svelte/renderers/RecursionSentinel.svelte +27 -0
  170. package/src/svelte/renderers/String.svelte +152 -0
  171. package/src/svelte/renderers/Tuple.svelte +84 -0
  172. package/src/svelte/renderers/Union.svelte +49 -0
  173. package/src/svelte/renderers/Unknown.svelte +42 -0
  174. package/src/svelte/svelte-modules.d.ts +25 -0
  175. package/src/svelte/types.ts +238 -0
  176. package/src/svelte/widget.ts +62 -0
  177. /package/dist/{diagnostics-BTrm3O6J.d.mts → diagnostics-mftUZI7c.d.mts} +0 -0
  178. /package/dist/{limits-x4OiyJxh.d.mts → limits-Vv9hUbI_.d.mts} +0 -0
  179. /package/dist/{types-BrYbjC7_.d.mts → types-BBQaEPfE.d.mts} +0 -0
  180. /package/dist/{version-DL8U5RuA.d.mts → version-BEBx10ND.d.mts} +0 -0
@@ -0,0 +1,668 @@
1
+ import { isObject, toRecordOrUndefined } from "./core/guards.mjs";
2
+ import "./core/limits.mjs";
3
+ import { SchemaFieldError, SchemaNormalisationError, SchemaRenderError } from "./core/errors.mjs";
4
+ import { normaliseSchema } from "./core/adapter.mjs";
5
+ import { SC_CLASSES } from "./core/cssClasses.mjs";
6
+ import { buildRenderProps } from "./core/renderer.mjs";
7
+ import { walk } from "./core/walker.mjs";
8
+ import { ScString } from "./lit/renderers/scString.mjs";
9
+ import { ScNumber } from "./lit/renderers/scNumber.mjs";
10
+ import { ScBoolean } from "./lit/renderers/scBoolean.mjs";
11
+ import { ScEnum } from "./lit/renderers/scEnum.mjs";
12
+ import { ScObject } from "./lit/renderers/scObject.mjs";
13
+ import { ScArray } from "./lit/renderers/scArray.mjs";
14
+ import { ScTuple } from "./lit/renderers/scTuple.mjs";
15
+ import { ScRecord } from "./lit/renderers/scRecord.mjs";
16
+ import { ScUnion } from "./lit/renderers/scUnion.mjs";
17
+ import { ScDiscriminated } from "./lit/renderers/scDiscriminated.mjs";
18
+ import { ScFile } from "./lit/renderers/scFile.mjs";
19
+ import { ScUnknown } from "./lit/renderers/scUnknown.mjs";
20
+ import { ScLiteral, ScNever, ScNull } from "./lit/renderers/scLiteralNullNever.mjs";
21
+ import { ScConditional, ScNegation } from "./lit/renderers/scConditional.mjs";
22
+ import { resolveLitWidget } from "./lit/widget.mjs";
23
+ import { LitElement, html } from "lit";
24
+ //#region src/lit/SchemaView.ts
25
+ /**
26
+ * `<schema-view>` — read-only Lit Custom Element variant of
27
+ * `<schema-component>`.
28
+ *
29
+ * Parallel to React's `<SchemaView>`: renders the supplied schema +
30
+ * value in read-only mode, never emits a `change` event, and ignores
31
+ * any user input on a nested control. Subclasses
32
+ * `<schema-component>` so the implementation work is just forcing
33
+ * `readOnly = true` and refusing to propagate child change events.
34
+ *
35
+ * **SSR caveat.** This element ALSO runs under `@lit-labs/ssr` for
36
+ * the equivalent of React's server-rendered `<SchemaView>`. The
37
+ * server path uses Declarative Shadow DOM via the `renderToString`
38
+ * helper in `lit/ssr.ts`. See that module's docstring for the
39
+ * documented limitations: `@lit-labs/ssr` is labs status,
40
+ * `@lit/context` does not server-render, and light-DOM-only
41
+ * components are not supported.
42
+ *
43
+ * @packageDocumentation
44
+ */
45
+ /**
46
+ * Lit Custom Element rendering a schema in read-only mode.
47
+ *
48
+ * Tag: `<schema-view>` (registered by `registerSchemaComponents`).
49
+ */
50
+ var SchemaView = class extends SchemaComponent {
51
+ constructor() {
52
+ super();
53
+ this.readOnly = true;
54
+ }
55
+ connectedCallback() {
56
+ super.connectedCallback();
57
+ this.readOnly = true;
58
+ }
59
+ };
60
+ //#endregion
61
+ //#region src/lit/SchemaField.ts
62
+ /**
63
+ * `<schema-field>` — Lit Custom Element rendering a single field from
64
+ * a schema by dot-separated `path`.
65
+ *
66
+ * Parallel to React's `<SchemaField>`. The element walks the supplied
67
+ * schema, resolves the field at `path`, and renders just that branch.
68
+ * Useful for forms where the layout is hand-built and each field
69
+ * needs its own renderer slot.
70
+ *
71
+ * Implementation note: `<schema-field>` extends `<schema-component>`
72
+ * so the normalisation / dispatch logic is inherited. The override
73
+ * here intercepts the post-walk tree and substitutes the path-
74
+ * targeted branch.
75
+ *
76
+ * @packageDocumentation
77
+ */
78
+ /**
79
+ * Lit Custom Element rendering a single sub-field of a schema.
80
+ *
81
+ * Tag: `<schema-field>` (registered by `registerSchemaComponents`).
82
+ */
83
+ var SchemaField = class extends SchemaComponent {
84
+ static properties = {
85
+ ...SchemaComponent.properties,
86
+ path: { attribute: false }
87
+ };
88
+ constructor() {
89
+ super();
90
+ this.path = "";
91
+ }
92
+ render() {
93
+ if (this.schema === void 0 || this.path.length === 0) return html``;
94
+ let jsonSchema;
95
+ let rootMeta;
96
+ let rootDocument;
97
+ try {
98
+ const normalised = normaliseSchema(this.schema, this.ref);
99
+ jsonSchema = normalised.jsonSchema;
100
+ rootMeta = normalised.rootMeta;
101
+ rootDocument = normalised.rootDocument;
102
+ } catch (err) {
103
+ if (err instanceof SchemaNormalisationError) throw err;
104
+ throw new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", this.schema, "unknown");
105
+ }
106
+ const walkOptions = {
107
+ componentMeta: this.meta,
108
+ rootMeta,
109
+ fieldOverrides: toRecordOrUndefined(this.fields),
110
+ rootDocument
111
+ };
112
+ const root = walk(jsonSchema, walkOptions);
113
+ const located = locateField(root, this.path);
114
+ if (located === void 0) throw new SchemaFieldError(`No field at path ${this.path}`, root, this.path);
115
+ const { tree, value } = located;
116
+ const valueToRender = value ?? tree.defaultValue;
117
+ const userResolver = this.resolver ?? createDefaultLitResolver();
118
+ const renderChild = this.makeRenderChild(0, this.path, userResolver);
119
+ return this.renderField(tree, valueToRender, (next) => {
120
+ this.dispatchEvent(new CustomEvent("change", { detail: {
121
+ value: next,
122
+ path: this.path
123
+ } }));
124
+ }, userResolver, renderChild, this.path);
125
+ }
126
+ };
127
+ /**
128
+ * Resolve a dot-separated path through a walked field tree, also
129
+ * tracking the value at the same position. Mirrors
130
+ * `react/fieldPath.ts::resolvePath` + `resolveValue` rolled into one.
131
+ *
132
+ * @internal
133
+ */
134
+ function locateField(root, path) {
135
+ const segments = splitPath(path);
136
+ let currentTree = root;
137
+ let currentValue = void 0;
138
+ for (const segment of segments) {
139
+ const numericIndex = parseIndex(segment);
140
+ if (numericIndex !== void 0) {
141
+ if (currentTree.type === "array" && currentTree.element) {
142
+ currentTree = currentTree.element;
143
+ currentValue = Array.isArray(currentValue) ? currentValue[numericIndex] : void 0;
144
+ continue;
145
+ }
146
+ if (currentTree.type === "tuple") {
147
+ const next = currentTree.prefixItems[numericIndex];
148
+ if (next === void 0) return void 0;
149
+ currentTree = next;
150
+ currentValue = Array.isArray(currentValue) ? currentValue[numericIndex] : void 0;
151
+ continue;
152
+ }
153
+ return;
154
+ }
155
+ if (currentTree.type === "object") {
156
+ const next = currentTree.fields[segment];
157
+ if (next === void 0) return void 0;
158
+ currentTree = next;
159
+ currentValue = isObject(currentValue) ? currentValue[segment] : void 0;
160
+ continue;
161
+ }
162
+ if (currentTree.type === "record") {
163
+ currentTree = currentTree.valueType;
164
+ currentValue = isObject(currentValue) ? currentValue[segment] : void 0;
165
+ continue;
166
+ }
167
+ return;
168
+ }
169
+ return {
170
+ tree: currentTree,
171
+ value: currentValue
172
+ };
173
+ }
174
+ /**
175
+ * Split a dot-separated path with bracketed indices into its
176
+ * structural segments. `"a.b[0].c"` → `["a", "b", "[0]", "c"]`.
177
+ */
178
+ function splitPath(path) {
179
+ const out = [];
180
+ let current = "";
181
+ for (const ch of path) {
182
+ if (ch === ".") {
183
+ if (current.length > 0) {
184
+ out.push(current);
185
+ current = "";
186
+ }
187
+ continue;
188
+ }
189
+ if (ch === "[") {
190
+ if (current.length > 0) out.push(current);
191
+ current = "[";
192
+ continue;
193
+ }
194
+ if (ch === "]") {
195
+ current += "]";
196
+ out.push(current);
197
+ current = "";
198
+ continue;
199
+ }
200
+ current += ch;
201
+ }
202
+ if (current.length > 0) out.push(current);
203
+ return out;
204
+ }
205
+ /**
206
+ * Parse a `[i]` bracketed-index segment to a number. Returns
207
+ * `undefined` for non-numeric or non-bracketed input.
208
+ */
209
+ function parseIndex(segment) {
210
+ if (!segment.startsWith("[") || !segment.endsWith("]")) return void 0;
211
+ const inner = segment.slice(1, -1);
212
+ if (inner.length === 0) return void 0;
213
+ const n = Number(inner);
214
+ if (!Number.isInteger(n) || n < 0) return void 0;
215
+ return n;
216
+ }
217
+ //#endregion
218
+ //#region src/lit/registry.ts
219
+ /**
220
+ * Mapping from the canonical built-in tag (without prefix) to the
221
+ * `BaseScElement` subclass that backs it. Exported so consumers can
222
+ * introspect what {@link registerSchemaComponents} will register —
223
+ * useful for diagnostics and for building documentation surfaces.
224
+ *
225
+ * The top-level orchestrator elements (`schema-component`,
226
+ * `schema-view`, `schema-field`) are listed alongside the per-type
227
+ * `<sc-*>` elements; the structural type relaxes to `HTMLElement` so
228
+ * every constructor is assignable.
229
+ */
230
+ const BUILT_IN_ELEMENTS = Object.freeze({
231
+ "schema-component": SchemaComponent,
232
+ "schema-view": SchemaView,
233
+ "schema-field": SchemaField,
234
+ "sc-string": ScString,
235
+ "sc-number": ScNumber,
236
+ "sc-boolean": ScBoolean,
237
+ "sc-enum": ScEnum,
238
+ "sc-object": ScObject,
239
+ "sc-array": ScArray,
240
+ "sc-tuple": ScTuple,
241
+ "sc-record": ScRecord,
242
+ "sc-union": ScUnion,
243
+ "sc-discriminated": ScDiscriminated,
244
+ "sc-conditional": ScConditional,
245
+ "sc-negation": ScNegation,
246
+ "sc-literal": ScLiteral,
247
+ "sc-null": ScNull,
248
+ "sc-never": ScNever,
249
+ "sc-file": ScFile,
250
+ "sc-unknown": ScUnknown
251
+ });
252
+ /**
253
+ * Register every built-in `<sc-*>` Custom Element on the global
254
+ * `customElements` registry, optionally namespaced under `prefix`.
255
+ *
256
+ * Re-registering the same tag is a no-op — `customElements.get(tag)`
257
+ * is checked first so calling this function twice (or alongside
258
+ * another library that registered the same tag) does not throw.
259
+ *
260
+ * @param prefix - Optional prefix prepended to every built-in tag.
261
+ * E.g. `registerSchemaComponents("myapp-")` registers
262
+ * `<myapp-sc-string>`, `<myapp-sc-number>`, …, avoiding collisions
263
+ * with another library that may have shipped its own `<sc-*>`
264
+ * elements. Pass an empty string (the default) to use the
265
+ * canonical names.
266
+ * @returns A {@link RegistrationResult} carrying the canonical-tag →
267
+ * registered-tag map and the list of elements skipped because the
268
+ * tag was already registered. The map is used by the default
269
+ * resolver to look up the right tag when the consumer chose a
270
+ * custom prefix.
271
+ *
272
+ * @example
273
+ * ```ts
274
+ * // Default registration — tags are <sc-string>, <sc-number>, ...
275
+ * import { registerSchemaComponents } from "schema-components/lit/registry";
276
+ * const tags = registerSchemaComponents();
277
+ *
278
+ * // Namespaced registration — tags are <myapp-sc-string>, ...
279
+ * const namespaced = registerSchemaComponents("myapp-");
280
+ * ```
281
+ */
282
+ function registerSchemaComponents(prefix = "") {
283
+ const registered = {};
284
+ const skipped = [];
285
+ for (const [canonical, ctor] of Object.entries(BUILT_IN_ELEMENTS)) {
286
+ const tag = `${prefix}${canonical}`;
287
+ if (customElements.get(tag) !== void 0) {
288
+ registered[canonical] = tag;
289
+ skipped.push(tag);
290
+ continue;
291
+ }
292
+ customElements.define(tag, ctor);
293
+ registered[canonical] = tag;
294
+ }
295
+ return {
296
+ tags: registered,
297
+ skipped
298
+ };
299
+ }
300
+ //#endregion
301
+ //#region src/lit/defaultResolver.ts
302
+ /**
303
+ * Default Lit {@link LitComponentResolver} that dispatches every
304
+ * built-in schema type to the matching `<sc-*>` Custom Element.
305
+ *
306
+ * Where the React adapter's headless resolver composes per-type
307
+ * functions that return React elements, the Lit equivalent emits a
308
+ * `<sc-string>` / `<sc-number>` / … Custom Element with the per-field
309
+ * props attached. The element itself is responsible for rendering —
310
+ * the resolver is just a tag-name lookup with property assignment.
311
+ *
312
+ * When the consumer registered the elements with a non-empty prefix
313
+ * (`registerSchemaComponents("myapp-")`), the resolver looks up the
314
+ * prefixed tag from the {@link RegistrationResult.tags} map so the
315
+ * right element is instantiated. A consumer that never called
316
+ * `registerSchemaComponents` falls back to the canonical `sc-*`
317
+ * names — letting tests render the elements directly with
318
+ * `customElements.define` while keeping the production path
319
+ * consumer-controlled.
320
+ *
321
+ * Implementation note: because Lit's `html` tagged template does not
322
+ * support dynamically-named element tags, the resolver builds each
323
+ * Custom Element via `document.createElement` and interpolates the
324
+ * resulting `Node` into the template. This trades one shared cache
325
+ * entry for any tag prefix — Lit's template caching is keyed on the
326
+ * literal, so all 17 dispatches share the same cache slot — for the
327
+ * loss of strictly-typed attribute templating. Per-field props are
328
+ * still assigned through statically-typed property accessors below.
329
+ *
330
+ * @packageDocumentation
331
+ */
332
+ /**
333
+ * Map of every `WalkedField.type` to its matching canonical `<sc-*>`
334
+ * tag. Exhaustive over the discriminated union — adding a new variant
335
+ * to the walker forces a deliberate update here.
336
+ *
337
+ * Exported so theme adapters can introspect the mapping when building
338
+ * their own resolvers (e.g. a shadcn-flavoured Web Components theme
339
+ * that wraps `<sc-string>` in a `<sl-input>`-style shell).
340
+ */
341
+ const TYPE_TO_CANONICAL_TAG = Object.freeze({
342
+ string: "sc-string",
343
+ number: "sc-number",
344
+ boolean: "sc-boolean",
345
+ null: "sc-null",
346
+ enum: "sc-enum",
347
+ object: "sc-object",
348
+ array: "sc-array",
349
+ tuple: "sc-tuple",
350
+ record: "sc-record",
351
+ union: "sc-union",
352
+ discriminatedUnion: "sc-discriminated",
353
+ conditional: "sc-conditional",
354
+ negation: "sc-negation",
355
+ literal: "sc-literal",
356
+ file: "sc-file",
357
+ never: "sc-never",
358
+ unknown: "sc-unknown"
359
+ });
360
+ /**
361
+ * Build the default Lit resolver for the supplied
362
+ * {@link RegistrationResult}.
363
+ *
364
+ * Each render function emits a Lit `html` template whose body is a
365
+ * dynamically-created `<sc-*>` element with every field prop assigned.
366
+ * The change callback is forwarded directly so user input on a leaf
367
+ * renderer reaches the orchestrator without going through a Custom
368
+ * Event boundary on the fast path.
369
+ *
370
+ * When no `registration` is supplied, the resolver emits the
371
+ * canonical `sc-*` tags. Useful in tests where `customElements.define`
372
+ * may have been called separately and the consumer doesn't need a
373
+ * prefixed registration object.
374
+ */
375
+ function createDefaultLitResolver(registration) {
376
+ const tags = registration?.tags ?? Object.fromEntries(Object.keys(BUILT_IN_ELEMENTS).map((tag) => [tag, tag]));
377
+ function tagFor(type) {
378
+ const canonical = TYPE_TO_CANONICAL_TAG[type];
379
+ return tags[canonical] ?? canonical;
380
+ }
381
+ function elementRenderer(type) {
382
+ return (props) => renderTagged(tagFor(type), props);
383
+ }
384
+ return {
385
+ string: elementRenderer("string"),
386
+ number: elementRenderer("number"),
387
+ boolean: elementRenderer("boolean"),
388
+ null: elementRenderer("null"),
389
+ enum: elementRenderer("enum"),
390
+ object: elementRenderer("object"),
391
+ array: elementRenderer("array"),
392
+ tuple: elementRenderer("tuple"),
393
+ record: elementRenderer("record"),
394
+ union: elementRenderer("union"),
395
+ discriminatedUnion: elementRenderer("discriminatedUnion"),
396
+ conditional: elementRenderer("conditional"),
397
+ negation: elementRenderer("negation"),
398
+ literal: elementRenderer("literal"),
399
+ file: elementRenderer("file"),
400
+ never: elementRenderer("never"),
401
+ unknown: elementRenderer("unknown")
402
+ };
403
+ }
404
+ /**
405
+ * Build a Lit template fragment that renders a single Custom Element
406
+ * by tag name with every per-field prop attached.
407
+ *
408
+ * Pure DOM-side path. The `lit-labs/ssr` path (`renderToString` in
409
+ * `lit/ssr.ts`) takes a separate code path that emits Declarative
410
+ * Shadow DOM markup; this helper is for the browser render only.
411
+ */
412
+ function renderTagged(tag, props) {
413
+ if (typeof document === "undefined") return html``;
414
+ const el = document.createElement(tag);
415
+ applyProperties(el, props);
416
+ return html`${el}`;
417
+ }
418
+ /**
419
+ * Assign every prop from {@link LitRenderProps} onto the created
420
+ * element. Element constructors created with `document.createElement`
421
+ * are typed as `HTMLElement`; we narrow through the `BaseScElement`
422
+ * field shape (every built-in implements it) so the assignment is
423
+ * statically typed without an `as` cast.
424
+ *
425
+ * If the element turns out NOT to be a `BaseScElement` (a tag prefix
426
+ * collision with a consumer-registered third-party element, or a
427
+ * misconfigured override), the assignment still succeeds because the
428
+ * built-in field shape is structurally identical to a plain object —
429
+ * the consumer is responsible for matching the field surface.
430
+ */
431
+ function applyProperties(el, props) {
432
+ Reflect.set(el, "tree", props.tree);
433
+ Reflect.set(el, "value", props.value);
434
+ Reflect.set(el, "readOnly", props.readOnly);
435
+ Reflect.set(el, "writeOnly", props.writeOnly);
436
+ Reflect.set(el, "path", props.path);
437
+ Reflect.set(el, "meta", props.meta);
438
+ Reflect.set(el, "constraints", props.constraints);
439
+ if (props.examples !== void 0) Reflect.set(el, "examples", props.examples);
440
+ Reflect.set(el, "change", props.change);
441
+ Reflect.set(el, "renderChild", props.renderChild);
442
+ }
443
+ //#endregion
444
+ //#region src/lit/SchemaComponent.ts
445
+ /**
446
+ * `<schema-component>` — top-level Lit Custom Element for editable
447
+ * schema-driven UI.
448
+ *
449
+ * Parity with the React `<SchemaComponent>` for the rendering path:
450
+ *
451
+ * - Accepts a Zod schema, JSON Schema, or OpenAPI document via the
452
+ * `schema` property (NOT attribute — see "Property-only schema/
453
+ * value/resolver" in `lit/README.md`).
454
+ * - Walks the schema via `normaliseSchema` → `walk` from
455
+ * `core/walker.ts` and dispatches every node through a Lit
456
+ * resolver — by default, the {@link createDefaultLitResolver}
457
+ * resolver that renders the built-in `<sc-*>` Custom Elements.
458
+ * - Emits a public `change` Custom Event on every user edit, with
459
+ * the updated root value in `event.detail.value`. Cross-framework
460
+ * wrappers translate this into the host framework's event /
461
+ * binding primitive (React's `onChange`, Vue `@change`, Svelte
462
+ * `on:change`).
463
+ *
464
+ * The element is registered by {@link registerSchemaComponents}; tag
465
+ * name defaults to `<schema-component>`. Pass a non-empty prefix
466
+ * (`registerSchemaComponents("myapp-")`) to namespace the top-level
467
+ * tag alongside every `<sc-*>` child.
468
+ *
469
+ * @packageDocumentation
470
+ */
471
+ /**
472
+ * Lit Custom Element for editable schema-driven UI.
473
+ *
474
+ * Tag: `<schema-component>` (default) or `<{prefix}schema-component>`
475
+ * (when `registerSchemaComponents(prefix)` is called).
476
+ *
477
+ * **Required:** call {@link registerSchemaComponents} once at module
478
+ * setup before instantiating this element in HTML markup, otherwise
479
+ * none of the per-type `<sc-*>` children will upgrade and the tree
480
+ * will render as unknown elements.
481
+ */
482
+ var SchemaComponent = class extends LitElement {
483
+ /**
484
+ * Element property declarations.
485
+ *
486
+ * All four "data" properties (`schema`, `value`, `resolver`,
487
+ * `widgets`) carry `attribute: false`: Custom Element attributes
488
+ * are strings, and these payloads (an arbitrary Zod schema, an
489
+ * arbitrary JS value, a resolver function map, a widget tag map)
490
+ * cannot round-trip through attribute serialisation. Set them via
491
+ * direct property assignment.
492
+ *
493
+ * `readOnly` is a boolean attribute (and reflects to DOM) so the
494
+ * common "render read-only view" case is reachable from plain
495
+ * HTML markup (`<schema-component readonly></schema-component>`).
496
+ * The capitalisation is `readOnly` on the property and `readonly`
497
+ * on the attribute — matching the HTML `readonly` attribute on
498
+ * `<input>` / `<textarea>`.
499
+ */
500
+ static properties = {
501
+ schema: { attribute: false },
502
+ value: { attribute: false },
503
+ resolver: { attribute: false },
504
+ widgets: { attribute: false },
505
+ fields: { attribute: false },
506
+ meta: { attribute: false },
507
+ ref: { attribute: false },
508
+ io: { attribute: false },
509
+ idPrefix: { attribute: false },
510
+ onDiagnostic: { attribute: false },
511
+ readOnly: {
512
+ type: Boolean,
513
+ reflect: true,
514
+ attribute: "readonly"
515
+ },
516
+ strict: { type: Boolean }
517
+ };
518
+ constructor() {
519
+ super();
520
+ this.schema = void 0;
521
+ this.value = void 0;
522
+ this.readOnly = false;
523
+ this.strict = false;
524
+ }
525
+ render() {
526
+ if (this.schema === void 0) return html``;
527
+ let jsonSchema;
528
+ let rootMeta;
529
+ let rootDocument;
530
+ try {
531
+ const diagnosticsOptions = this.onDiagnostic !== void 0 || this.strict ? this.buildDiagnostics() : void 0;
532
+ const normaliseOptions = diagnosticsOptions !== void 0 || this.io !== void 0 ? {
533
+ ...diagnosticsOptions !== void 0 ? { diagnostics: diagnosticsOptions } : {},
534
+ ...this.io !== void 0 ? { io: this.io } : {}
535
+ } : void 0;
536
+ const normalised = normaliseSchema(this.schema, this.ref, normaliseOptions);
537
+ jsonSchema = normalised.jsonSchema;
538
+ rootMeta = normalised.rootMeta;
539
+ rootDocument = normalised.rootDocument;
540
+ } catch (err) {
541
+ if (err instanceof SchemaNormalisationError) throw err;
542
+ throw new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", this.schema, "unknown");
543
+ }
544
+ const mergedMeta = { ...this.meta };
545
+ if (this.readOnly) mergedMeta.readOnly = true;
546
+ const walkOptions = {
547
+ componentMeta: mergedMeta,
548
+ rootMeta,
549
+ fieldOverrides: toRecordOrUndefined(this.fields),
550
+ rootDocument,
551
+ ...this.onDiagnostic !== void 0 || this.strict ? { diagnostics: this.buildDiagnostics() } : {}
552
+ };
553
+ const tree = walk(jsonSchema, walkOptions);
554
+ const userResolver = this.resolver ?? createDefaultLitResolver();
555
+ const rootPath = this.idPrefix ?? "root";
556
+ const rootChange = (next) => {
557
+ this.value = next;
558
+ this.dispatchEvent(new CustomEvent("change", {
559
+ detail: { value: next },
560
+ bubbles: false,
561
+ composed: false
562
+ }));
563
+ this.requestUpdate();
564
+ };
565
+ const renderChild = this.makeRenderChild(0, rootPath, userResolver);
566
+ return this.renderField(tree, this.value ?? tree.defaultValue, rootChange, userResolver, renderChild, rootPath);
567
+ }
568
+ /**
569
+ * Build the recursive `renderChild` closure threaded through every
570
+ * container renderer.
571
+ */
572
+ makeRenderChild(currentDepth, parentPath, userResolver) {
573
+ const joinPath = (parent, suffix) => {
574
+ if (suffix === void 0) return parent;
575
+ return suffix.startsWith("[") ? `${parent}${suffix}` : `${parent}.${suffix}`;
576
+ };
577
+ return (childTree, childValue, childChange, pathSuffix) => {
578
+ const childPath = joinPath(parentPath, pathSuffix);
579
+ if (currentDepth >= 10) {
580
+ const label = typeof childTree.meta.description === "string" ? childTree.meta.description : "schema";
581
+ return html`<fieldset class=${SC_CLASSES.recursive}>
582
+ <em>${`↻ ${label} (recursive)`}</em>
583
+ </fieldset>`;
584
+ }
585
+ const grandChild = this.makeRenderChild(currentDepth + 1, childPath, userResolver);
586
+ return this.renderField(childTree, childValue, childChange, userResolver, grandChild, childPath);
587
+ };
588
+ }
589
+ /**
590
+ * Dispatch a single walked field through the resolver, widget
591
+ * registry, and recursion limit. Parallel to
592
+ * `renderField` in `react/SchemaComponent.tsx`.
593
+ */
594
+ renderField(tree, value, change, userResolver, renderChild, path) {
595
+ const componentHint = tree.meta.component;
596
+ if (typeof componentHint === "string") {
597
+ const widget = resolveLitWidget(componentHint, this.widgets);
598
+ if (widget !== void 0) {
599
+ if (typeof document === "undefined") return html``;
600
+ const el = document.createElement(widget);
601
+ this.applyWidgetProperties(el, tree, value, change, path);
602
+ return html`${el}`;
603
+ }
604
+ }
605
+ const renderFn = userResolver[litResolverKey(tree.type)];
606
+ if (renderFn !== void 0) {
607
+ const adaptedRenderChild = (childTree, childValue, childOnChange, pathSuffix) => renderChild(childTree, childValue, childOnChange, pathSuffix);
608
+ const coreProps = buildRenderProps(tree, value, change, adaptedRenderChild, path);
609
+ const litProps = {
610
+ value: coreProps.value,
611
+ readOnly: coreProps.readOnly,
612
+ writeOnly: coreProps.writeOnly,
613
+ meta: coreProps.meta,
614
+ constraints: coreProps.constraints,
615
+ path: coreProps.path,
616
+ tree: coreProps.tree,
617
+ change,
618
+ renderChild,
619
+ ...coreProps.examples !== void 0 ? { examples: coreProps.examples } : {}
620
+ };
621
+ try {
622
+ return renderFn(litProps);
623
+ } catch (err) {
624
+ throw new SchemaRenderError(err instanceof Error ? err.message : `Render function threw for type "${tree.type}"`, tree, tree.type, err);
625
+ }
626
+ }
627
+ if (value === void 0 || value === null) return html`<span>—</span>`;
628
+ return html`<span>${typeof value === "string" ? value : JSON.stringify(value)}</span>`;
629
+ }
630
+ applyWidgetProperties(el, tree, value, change, path) {
631
+ Reflect.set(el, "tree", tree);
632
+ Reflect.set(el, "value", value);
633
+ Reflect.set(el, "readOnly", this.readOnly);
634
+ Reflect.set(el, "path", path);
635
+ Reflect.set(el, "meta", tree.meta);
636
+ Reflect.set(el, "constraints", tree.constraints);
637
+ Reflect.set(el, "change", change);
638
+ }
639
+ buildDiagnostics() {
640
+ const opts = {};
641
+ if (this.onDiagnostic !== void 0) opts.diagnostics = this.onDiagnostic;
642
+ if (this.strict) opts.strict = true;
643
+ return opts;
644
+ }
645
+ };
646
+ function litResolverKey(type) {
647
+ switch (type) {
648
+ case "string":
649
+ case "number":
650
+ case "boolean":
651
+ case "null":
652
+ case "enum":
653
+ case "object":
654
+ case "array":
655
+ case "tuple":
656
+ case "record":
657
+ case "union":
658
+ case "discriminatedUnion":
659
+ case "conditional":
660
+ case "negation":
661
+ case "literal":
662
+ case "file":
663
+ case "never":
664
+ case "unknown": return type;
665
+ }
666
+ }
667
+ //#endregion
668
+ export { registerSchemaComponents as a, BUILT_IN_ELEMENTS as i, TYPE_TO_CANONICAL_TAG as n, SchemaField as o, createDefaultLitResolver as r, SchemaView as s, SchemaComponent as t };