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,840 @@
1
+ import { isObject } from "../core/guards.mjs";
2
+ import { dateInputType } from "../core/formats.mjs";
3
+ import { isSafeHyperlink, isSafeMailtoAddress } from "../core/uri.mjs";
4
+ import { SC_CLASSES } from "../core/cssClasses.mjs";
5
+ import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
6
+ import { fieldDomId, panelIdFor, tabIdFor } from "../core/idPath.mjs";
7
+ import { matchUnionOption, resolveDiscriminatedActive } from "../core/unionMatch.mjs";
8
+ import { displayJsonValue } from "../core/walkBuilders.mjs";
9
+ import { ariaLabel, buildAriaAttrs, buildHintInfo } from "./a11y.mjs";
10
+ import { For, Show, createEffect, createSignal } from "solid-js";
11
+ import { Fragment, jsx, jsxs } from "solid-js/jsx-runtime";
12
+ //#region src/solid/renderers.tsx
13
+ /** @jsxImportSource solid-js */
14
+ /**
15
+ * Solid headless renderer functions — one per schema type.
16
+ *
17
+ * Mirrors `react/headlessRenderers.tsx` field-for-field, adapted to
18
+ * Solid's idiom. Key differences:
19
+ *
20
+ * - `<Show when={...}>` replaces `condition && <X />` so the
21
+ * conditional branch is reactive rather than re-evaluated by parent
22
+ * re-renders.
23
+ * - `<For each={...}>` replaces `.map(...)` so list children are
24
+ * tracked per-item — array mutations don't tear the rendered tree
25
+ * down and rebuild it.
26
+ * - No `useRef`/`useState`/`useCallback`/`useMemo` — Solid's
27
+ * reactivity model makes those redundant. Element refs use the
28
+ * `ref={el => ...}` callback (Solid's documented escape hatch);
29
+ * keyboard focus state in `DiscriminatedUnionTabs` is held in a
30
+ * plain array with no per-render allocation.
31
+ * - `onChange` semantics: Solid's `onInput` fires on every keystroke
32
+ * (matching React's `onChange` semantics), and `onChange` on Solid
33
+ * fires on commit (matching the DOM `change` event). The headless
34
+ * renderers wire `onInput` for text/number inputs so live state
35
+ * updates match the React adapter's behaviour; `onChange` is used
36
+ * for `<input type="checkbox">`, `<input type="file">`, and
37
+ * `<select>` where commit semantics are the right contract.
38
+ *
39
+ * Per-type schema data is read directly from the discriminated `tree`
40
+ * (mirroring the React adapter); the helpers from `core/walkBuilders.ts`,
41
+ * `core/idPath.ts`, `core/unionMatch.ts`, and `core/cssClasses.ts` are
42
+ * shared between adapters.
43
+ */
44
+ function formatDateTime(value) {
45
+ if (typeof value !== "string" || value.length === 0) return void 0;
46
+ const date = new Date(value);
47
+ if (isNaN(date.getTime())) return void 0;
48
+ return date.toLocaleString();
49
+ }
50
+ function formatDate(value) {
51
+ if (typeof value !== "string" || value.length === 0) return void 0;
52
+ const date = new Date(value);
53
+ if (isNaN(date.getTime())) return void 0;
54
+ return date.toLocaleDateString();
55
+ }
56
+ function formatTime(value) {
57
+ if (typeof value !== "string" || value.length === 0) return void 0;
58
+ const date = new Date(value);
59
+ if (isNaN(date.getTime())) return void 0;
60
+ return date.toLocaleTimeString();
61
+ }
62
+ /**
63
+ * Build a stable, unique input ID from the path. Re-exported alias for
64
+ * {@link fieldDomId} so the Solid adapter has the same import shape as
65
+ * the React adapter's `inputId`.
66
+ */
67
+ function inputId(path) {
68
+ return fieldDomId(path);
69
+ }
70
+ /** Headless renderer for `StringField` — plain `<input>` / `<span>`. */
71
+ function renderString(props) {
72
+ const id = inputId(props.path);
73
+ if (props.readOnly) {
74
+ const strValue = typeof props.value === "string" ? props.value : void 0;
75
+ if (strValue === void 0 || strValue.length === 0) return /* @__PURE__ */ jsx("span", {
76
+ id,
77
+ children: "—"
78
+ });
79
+ const format = props.constraints.format;
80
+ if (format === "email" && isSafeMailtoAddress(strValue)) return /* @__PURE__ */ jsx("a", {
81
+ href: `mailto:${strValue}`,
82
+ id,
83
+ "aria-readonly": "true",
84
+ children: strValue
85
+ });
86
+ if ((format === "uri" || format === "url") && isSafeHyperlink(strValue)) return /* @__PURE__ */ jsx("a", {
87
+ href: strValue,
88
+ id,
89
+ "aria-readonly": "true",
90
+ children: strValue
91
+ });
92
+ if (format === "date") return /* @__PURE__ */ jsx("span", {
93
+ id,
94
+ children: formatDate(strValue) ?? strValue
95
+ });
96
+ if (format === "time") return /* @__PURE__ */ jsx("span", {
97
+ id,
98
+ children: formatTime(strValue) ?? strValue
99
+ });
100
+ if (format === "date-time" || format === "datetime") return /* @__PURE__ */ jsx("span", {
101
+ id,
102
+ children: formatDateTime(strValue) ?? strValue
103
+ });
104
+ return /* @__PURE__ */ jsx("span", {
105
+ id,
106
+ children: strValue
107
+ });
108
+ }
109
+ const strValue = typeof props.value === "string" ? props.value : "";
110
+ const dateType = dateInputType(props.constraints.format);
111
+ const ariaAttrs = buildAriaAttrs(props.tree);
112
+ const hintInfo = buildHintInfo(id, props.constraints);
113
+ const hintElement = () => hintInfo === void 0 ? null : /* @__PURE__ */ jsx("small", {
114
+ id: hintInfo.id,
115
+ class: "sc-hint",
116
+ children: hintInfo.hint
117
+ });
118
+ if (dateType !== void 0) return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
119
+ id,
120
+ type: dateType,
121
+ value: props.writeOnly ? "" : strValue,
122
+ onInput: (e) => {
123
+ props.onChange(e.currentTarget.value);
124
+ },
125
+ "aria-describedby": hintInfo?.ariaDescribedBy,
126
+ ...ariaAttrs
127
+ }), hintElement()] });
128
+ if (props.tree.type === "enum" && props.tree.enumValues.length > 0) {
129
+ const enumValues = props.tree.enumValues;
130
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("select", {
131
+ id,
132
+ value: strValue,
133
+ onChange: (e) => {
134
+ props.onChange(e.currentTarget.value);
135
+ },
136
+ "aria-describedby": hintInfo?.ariaDescribedBy,
137
+ ...ariaAttrs,
138
+ children: [/* @__PURE__ */ jsxs("option", {
139
+ value: "",
140
+ children: ["Select", "…"]
141
+ }), /* @__PURE__ */ jsx(For, {
142
+ each: enumValues,
143
+ children: (v) => {
144
+ const display = displayJsonValue(v);
145
+ return /* @__PURE__ */ jsx("option", {
146
+ value: display,
147
+ children: display
148
+ });
149
+ }
150
+ })]
151
+ }), hintElement()] });
152
+ }
153
+ const isCredential = props.writeOnly && props.constraints.format === "password";
154
+ const inputType = isCredential ? "password" : props.constraints.format === "email" ? "email" : props.constraints.format === "uri" ? "url" : "text";
155
+ const autoComplete = isCredential ? strValue.length > 0 ? "current-password" : "new-password" : void 0;
156
+ const placeholder = typeof props.meta.description === "string" ? props.meta.description : void 0;
157
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
158
+ id,
159
+ type: inputType,
160
+ autocomplete: autoComplete,
161
+ value: props.writeOnly ? "" : strValue,
162
+ onInput: (e) => {
163
+ props.onChange(e.currentTarget.value);
164
+ },
165
+ placeholder,
166
+ minlength: props.constraints.minLength,
167
+ maxlength: props.constraints.maxLength,
168
+ "aria-describedby": hintInfo?.ariaDescribedBy,
169
+ ...ariaAttrs
170
+ }), hintElement()] });
171
+ }
172
+ /** Headless renderer for `NumberField` — plain `<input type="number">`. */
173
+ function renderNumber(props) {
174
+ const id = inputId(props.path);
175
+ if (props.readOnly) {
176
+ if (typeof props.value !== "number") return /* @__PURE__ */ jsx("span", {
177
+ id,
178
+ children: "—"
179
+ });
180
+ return /* @__PURE__ */ jsx("span", {
181
+ id,
182
+ children: props.value.toLocaleString()
183
+ });
184
+ }
185
+ const numValue = typeof props.value === "number" ? props.value : "";
186
+ const ariaAttrs = buildAriaAttrs(props.tree);
187
+ const hintInfo = buildHintInfo(id, props.constraints);
188
+ const isInteger = props.tree.type === "number" ? props.tree.isInteger : false;
189
+ const inputMode = isInteger ? "numeric" : "decimal";
190
+ const multipleOf = props.constraints.multipleOf;
191
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
192
+ id,
193
+ type: "number",
194
+ inputmode: inputMode,
195
+ step: multipleOf !== void 0 ? String(multipleOf) : isInteger ? "1" : void 0,
196
+ value: props.writeOnly ? "" : numValue,
197
+ onInput: (e) => {
198
+ props.onChange(Number(e.currentTarget.value));
199
+ },
200
+ min: props.constraints.minimum,
201
+ max: props.constraints.maximum,
202
+ "aria-describedby": hintInfo?.ariaDescribedBy,
203
+ ...ariaAttrs
204
+ }), /* @__PURE__ */ jsx(Show, {
205
+ when: hintInfo !== void 0,
206
+ children: /* @__PURE__ */ jsx("small", {
207
+ id: hintInfo?.id,
208
+ class: "sc-hint",
209
+ children: hintInfo?.hint
210
+ })
211
+ })] });
212
+ }
213
+ /** Headless renderer for `BooleanField` — plain `<input type="checkbox">`. */
214
+ function renderBoolean(props) {
215
+ const id = inputId(props.path);
216
+ if (props.readOnly) {
217
+ if (typeof props.value !== "boolean") return /* @__PURE__ */ jsx("span", {
218
+ id,
219
+ children: "—"
220
+ });
221
+ return /* @__PURE__ */ jsx("span", {
222
+ id,
223
+ children: props.value ? "Yes" : "No"
224
+ });
225
+ }
226
+ const ariaAttrs = buildAriaAttrs(props.tree, props.meta.description);
227
+ return /* @__PURE__ */ jsx("input", {
228
+ id,
229
+ type: "checkbox",
230
+ checked: props.writeOnly ? false : props.value === true,
231
+ onChange: (e) => {
232
+ props.onChange(e.currentTarget.checked);
233
+ },
234
+ ...ariaAttrs
235
+ });
236
+ }
237
+ /** Headless renderer for `EnumField` — plain `<select>` listing each option. */
238
+ function renderEnum(props) {
239
+ const id = inputId(props.path);
240
+ const enumValue = typeof props.value === "string" ? props.value : "";
241
+ if (props.readOnly) return /* @__PURE__ */ jsx("span", {
242
+ id,
243
+ children: enumValue.length === 0 ? "—" : enumValue
244
+ });
245
+ const ariaAttrs = buildAriaAttrs(props.tree);
246
+ const hintInfo = buildHintInfo(id, props.constraints);
247
+ const enumValues = props.tree.type === "enum" ? props.tree.enumValues : [];
248
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("select", {
249
+ id,
250
+ value: props.writeOnly ? "" : enumValue,
251
+ onChange: (e) => {
252
+ props.onChange(e.currentTarget.value);
253
+ },
254
+ "aria-describedby": hintInfo?.ariaDescribedBy,
255
+ ...ariaAttrs,
256
+ children: [/* @__PURE__ */ jsxs("option", {
257
+ value: "",
258
+ children: ["Select", "…"]
259
+ }), /* @__PURE__ */ jsx(For, {
260
+ each: enumValues,
261
+ children: (v) => {
262
+ const display = displayJsonValue(v);
263
+ return /* @__PURE__ */ jsx("option", {
264
+ value: display,
265
+ children: display
266
+ });
267
+ }
268
+ })]
269
+ }), /* @__PURE__ */ jsx(Show, {
270
+ when: hintInfo !== void 0,
271
+ children: /* @__PURE__ */ jsx("small", {
272
+ id: hintInfo?.id,
273
+ class: "sc-hint",
274
+ children: hintInfo?.hint
275
+ })
276
+ })] });
277
+ }
278
+ /**
279
+ * Compute the default value for a freshly added record entry based on
280
+ * the record's value-type schema. Mirrors the React headless
281
+ * implementation byte-for-byte so both adapters seed new entries the
282
+ * same way.
283
+ */
284
+ function defaultRecordValue(valueType) {
285
+ if (valueType.defaultValue !== void 0) return valueType.defaultValue;
286
+ switch (valueType.type) {
287
+ case "string": return "";
288
+ case "number": return 0;
289
+ case "boolean": return false;
290
+ case "array": return [];
291
+ case "object":
292
+ case "record": return {};
293
+ case "null": return null;
294
+ case "unknown":
295
+ case "enum":
296
+ case "literal":
297
+ case "tuple":
298
+ case "union":
299
+ case "discriminatedUnion":
300
+ case "conditional":
301
+ case "negation":
302
+ case "file":
303
+ case "never": return;
304
+ }
305
+ }
306
+ /**
307
+ * Generate a unique, currently-unused key for a new record entry.
308
+ * Picks the first of `key`, `key-1`, `key-2`, … not in `existing`.
309
+ */
310
+ function nextRecordKey(existing, base = "key") {
311
+ if (!existing.includes(base)) return base;
312
+ let i = 1;
313
+ while (existing.includes(`${base}-${String(i)}`)) i += 1;
314
+ return `${base}-${String(i)}`;
315
+ }
316
+ /**
317
+ * Rename a key in an object while preserving insertion order. Returns
318
+ * the original object reference when the rename is a no-op
319
+ * (oldKey === newKey) or when newKey collides with an existing key.
320
+ */
321
+ function renameRecordKey(obj, oldKey, newKey) {
322
+ if (oldKey === newKey) return obj;
323
+ if (newKey in obj && newKey !== oldKey) return obj;
324
+ const renamed = {};
325
+ for (const [k, v] of Object.entries(obj)) renamed[k === oldKey ? newKey : k] = v;
326
+ return renamed;
327
+ }
328
+ /** Headless renderer for `ObjectField` — `<fieldset>` per object. */
329
+ function renderObject(props) {
330
+ if (props.tree.type !== "object") return null;
331
+ const obj = isObject(props.value) ? props.value : {};
332
+ const fields = props.tree.fields;
333
+ const sortedEntries = sortFieldsByOrder(fields).filter(([, field]) => field.meta.visible !== false);
334
+ return /* @__PURE__ */ jsxs("fieldset", { children: [/* @__PURE__ */ jsx(Show, {
335
+ when: typeof props.meta.description === "string",
336
+ children: /* @__PURE__ */ jsx("legend", { children: props.meta.description })
337
+ }), /* @__PURE__ */ jsx(For, {
338
+ each: sortedEntries,
339
+ children: ([key, field]) => {
340
+ const childValue = obj[key];
341
+ const childId = inputId(`${props.path}.${key}`);
342
+ const childOnChange = (v) => {
343
+ const updated = {};
344
+ for (const [k, val] of Object.entries(obj)) updated[k] = val;
345
+ updated[key] = v;
346
+ props.onChange(updated);
347
+ };
348
+ const child = props.renderChild(field, childValue, childOnChange, key);
349
+ if (child === null || child === void 0) return null;
350
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("label", {
351
+ for: childId,
352
+ children: [typeof field.meta.description === "string" ? field.meta.description : key, /* @__PURE__ */ jsx(Show, {
353
+ when: field.isOptional === false,
354
+ children: /* @__PURE__ */ jsxs("span", {
355
+ "aria-hidden": "true",
356
+ style: { color: "#dc2626" },
357
+ children: [" ", "*"]
358
+ })
359
+ })]
360
+ }), child] });
361
+ }
362
+ })] });
363
+ }
364
+ /** Headless renderer for `RecordField` — editable key/value rows. */
365
+ function renderRecord(props) {
366
+ if (props.tree.type !== "record") return null;
367
+ const obj = isObject(props.value) ? props.value : {};
368
+ const valueType = props.tree.valueType;
369
+ const entries = Object.entries(obj);
370
+ if (props.readOnly) {
371
+ if (entries.length === 0) return /* @__PURE__ */ jsx("span", { children: "—" });
372
+ return /* @__PURE__ */ jsx("div", {
373
+ role: "group",
374
+ "aria-label": ariaLabel(props.meta.description),
375
+ children: /* @__PURE__ */ jsx(For, {
376
+ each: entries,
377
+ children: ([key, value]) => {
378
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
379
+ for: inputId(`${props.path}.${key}`),
380
+ children: key
381
+ }), props.renderChild(valueType, value, () => {}, key)] });
382
+ }
383
+ })
384
+ });
385
+ }
386
+ const handleRename = (oldKey, newKey) => {
387
+ const renamed = renameRecordKey(obj, oldKey, newKey);
388
+ if (renamed === obj) return;
389
+ props.onChange(renamed);
390
+ };
391
+ const handleValueChange = (key, nextValue) => {
392
+ const updated = {};
393
+ for (const [k, val] of Object.entries(obj)) updated[k] = val;
394
+ updated[key] = nextValue;
395
+ props.onChange(updated);
396
+ };
397
+ const handleRemove = (key) => {
398
+ const next = {};
399
+ for (const [k, v] of Object.entries(obj)) {
400
+ if (k === key) continue;
401
+ next[k] = v;
402
+ }
403
+ props.onChange(next);
404
+ };
405
+ const handleAdd = () => {
406
+ const newKey = nextRecordKey(Object.keys(obj));
407
+ const next = { ...obj };
408
+ next[newKey] = defaultRecordValue(valueType);
409
+ props.onChange(next);
410
+ };
411
+ return /* @__PURE__ */ jsxs("div", {
412
+ role: "group",
413
+ "aria-label": ariaLabel(props.meta.description),
414
+ children: [/* @__PURE__ */ jsx(For, {
415
+ each: entries,
416
+ children: ([key, value]) => {
417
+ return /* @__PURE__ */ jsxs("div", { children: [
418
+ /* @__PURE__ */ jsx("input", {
419
+ id: `${inputId(`${props.path}.${key}`)}-key`,
420
+ type: "text",
421
+ "aria-label": "Entry key",
422
+ value: key,
423
+ onChange: (e) => {
424
+ handleRename(key, e.currentTarget.value);
425
+ }
426
+ }),
427
+ props.renderChild(valueType, value, (nextValue) => {
428
+ handleValueChange(key, nextValue);
429
+ }, key),
430
+ /* @__PURE__ */ jsx("button", {
431
+ type: "button",
432
+ "aria-label": `Remove entry ${key}`,
433
+ onClick: () => {
434
+ handleRemove(key);
435
+ },
436
+ children: "Remove"
437
+ })
438
+ ] });
439
+ }
440
+ }), /* @__PURE__ */ jsx("button", {
441
+ type: "button",
442
+ "aria-label": "Add entry",
443
+ onClick: handleAdd,
444
+ children: "Add"
445
+ })]
446
+ });
447
+ }
448
+ /** Headless renderer for `ArrayField` — ordered list with add/remove controls. */
449
+ function renderArray(props) {
450
+ if (props.tree.type !== "array") return null;
451
+ const arr = Array.isArray(props.value) ? props.value : [];
452
+ const element = props.tree.element;
453
+ if (element === void 0) return null;
454
+ if (props.readOnly) {
455
+ if (arr.length === 0) return null;
456
+ return /* @__PURE__ */ jsx("ul", {
457
+ role: "group",
458
+ "aria-label": ariaLabel(props.meta.description),
459
+ children: /* @__PURE__ */ jsx(For, {
460
+ each: arr,
461
+ children: (item, i) => /* @__PURE__ */ jsx("li", { children: props.renderChild(element, item, () => {}, `[${String(i())}]`) })
462
+ })
463
+ });
464
+ }
465
+ const handleRemove = (index) => {
466
+ const next = arr.slice();
467
+ next.splice(index, 1);
468
+ props.onChange(next);
469
+ };
470
+ const handleAdd = () => {
471
+ const next = arr.slice();
472
+ next.push(defaultRecordValue(element));
473
+ props.onChange(next);
474
+ };
475
+ return /* @__PURE__ */ jsxs("div", {
476
+ role: "group",
477
+ "aria-label": ariaLabel(props.meta.description),
478
+ children: [/* @__PURE__ */ jsx("ul", { children: /* @__PURE__ */ jsx(For, {
479
+ each: arr,
480
+ children: (item, i) => {
481
+ const childOnChange = (v) => {
482
+ const nextArr = arr.slice();
483
+ nextArr[i()] = v;
484
+ props.onChange(nextArr);
485
+ };
486
+ return /* @__PURE__ */ jsxs("li", { children: [props.renderChild(element, item, childOnChange, `[${String(i())}]`), /* @__PURE__ */ jsx("button", {
487
+ type: "button",
488
+ "aria-label": `Remove item ${String(i())}`,
489
+ onClick: () => {
490
+ handleRemove(i());
491
+ },
492
+ children: "Remove"
493
+ })] });
494
+ }
495
+ }) }), /* @__PURE__ */ jsx("button", {
496
+ type: "button",
497
+ "aria-label": "Add item",
498
+ onClick: handleAdd,
499
+ children: "Add"
500
+ })]
501
+ });
502
+ }
503
+ /** Headless renderer for plain `UnionField` — picks the matching option. */
504
+ function renderUnion(props) {
505
+ const options = props.tree.type === "union" || props.tree.type === "discriminatedUnion" ? props.tree.options : void 0;
506
+ if (options === void 0 || options.length === 0) {
507
+ if (props.value === void 0 || props.value === null) return /* @__PURE__ */ jsx("span", { children: "—" });
508
+ return /* @__PURE__ */ jsx("span", { children: JSON.stringify(props.value) });
509
+ }
510
+ const matched = matchUnionOption(options, props.value);
511
+ if (matched !== void 0) return props.renderChild(matched, props.value, props.onChange);
512
+ const firstOption = options[0];
513
+ if (firstOption !== void 0) return props.renderChild(firstOption, props.value, props.onChange);
514
+ return /* @__PURE__ */ jsx("span", { children: "—" });
515
+ }
516
+ /**
517
+ * Pure helper: convert a tab index into the new value the discriminated
518
+ * union should emit. Returns `undefined` when the index is out of bounds.
519
+ *
520
+ * Extracted so the contract is unit-testable without rendering the tabs
521
+ * component. Mirrors the React adapter's `discriminatedUnionValueForTab`.
522
+ */
523
+ function discriminatedUnionValueForTab(optionLabels, discKey, newIndex) {
524
+ const label = optionLabels[newIndex];
525
+ if (label === void 0) return void 0;
526
+ return { [discKey]: label };
527
+ }
528
+ /** Headless renderer for `DiscriminatedUnionField` — tabbed UI. */
529
+ function renderDiscriminatedUnion(props) {
530
+ if (props.tree.type !== "discriminatedUnion") {
531
+ if (props.value === void 0 || props.value === null) return /* @__PURE__ */ jsx("span", { children: "—" });
532
+ return /* @__PURE__ */ jsx("span", { children: JSON.stringify(props.value) });
533
+ }
534
+ const { options, discriminator: discKey } = props.tree;
535
+ if (options.length === 0) {
536
+ if (props.value === void 0 || props.value === null) return /* @__PURE__ */ jsx("span", { children: "—" });
537
+ return /* @__PURE__ */ jsx("span", { children: JSON.stringify(props.value) });
538
+ }
539
+ const { optionLabels, activeIndex, activeOption } = resolveDiscriminatedActive(options, discKey, isObject(props.value) ? props.value : void 0);
540
+ if (props.readOnly) {
541
+ if (activeOption !== void 0) return props.renderChild(activeOption, props.value, props.onChange);
542
+ return /* @__PURE__ */ jsx("span", { children: "—" });
543
+ }
544
+ return /* @__PURE__ */ jsx(DiscriminatedUnionTabs, {
545
+ options,
546
+ optionLabels,
547
+ activeIndex,
548
+ path: props.path,
549
+ discKey,
550
+ props
551
+ });
552
+ }
553
+ /**
554
+ * WAI-ARIA tabs component for discriminated unions, Solid-flavoured.
555
+ *
556
+ * Implements the WAI-ARIA "Tabs with Automatic Activation" pattern:
557
+ * - ArrowRight / ArrowLeft move between tabs, wrapping at the extremes.
558
+ * - Home / End jump to the first / last tab.
559
+ * - `aria-selected`, `aria-controls`, `role="tablist" | "tab" | "tabpanel"`.
560
+ * - Roving tabindex: the active tab carries `tabindex=0`, the rest
561
+ * `tabindex=-1`.
562
+ *
563
+ * "Automatic activation" means each arrow key both moves focus and
564
+ * activates the new tab in one step — selection and focus stay aligned.
565
+ *
566
+ * The Solid implementation differs from the React equivalent in:
567
+ *
568
+ * - Element refs use Solid's `ref={el => ...}` callback rather than
569
+ * `useRef`. The refs array is module-local to the JSX closure — no
570
+ * `createSignal` needed because we never derive reactive state from
571
+ * the refs themselves, only the array's contents.
572
+ * - A `pendingFocus` signal tracks "the user just pressed an arrow key,
573
+ * focus should follow the next active index". `createEffect`
574
+ * consumes the signal — Solid runs the effect after the DOM update
575
+ * so `.focus()` lands on the freshly-active button.
576
+ * - The handler reads `props.activeIndex` reactively because the parent
577
+ * re-derives it from `props.props.value` on every tab change.
578
+ */
579
+ function DiscriminatedUnionTabs(props) {
580
+ const panelId = panelIdFor(props.path);
581
+ const tabRefs = [];
582
+ const [pendingFocus, setPendingFocus] = createSignal(false);
583
+ const handleTabChange = (newIndex) => {
584
+ const next = discriminatedUnionValueForTab(props.optionLabels, props.discKey, newIndex);
585
+ if (next === void 0) return;
586
+ props.props.onChange(next);
587
+ };
588
+ const wrapIndex = (index) => (index % props.options.length + props.options.length) % props.options.length;
589
+ const handleKeyDown = (e) => {
590
+ let target;
591
+ if (e.key === "ArrowRight") target = wrapIndex(props.activeIndex + 1);
592
+ else if (e.key === "ArrowLeft") target = wrapIndex(props.activeIndex - 1);
593
+ else if (e.key === "Home") target = 0;
594
+ else if (e.key === "End") target = props.options.length - 1;
595
+ if (target === void 0) return;
596
+ e.preventDefault();
597
+ if (target === props.activeIndex) return;
598
+ setPendingFocus(true);
599
+ handleTabChange(target);
600
+ };
601
+ createEffect(() => {
602
+ if (!pendingFocus()) return;
603
+ const idx = props.activeIndex;
604
+ setPendingFocus(false);
605
+ tabRefs[idx]?.focus();
606
+ });
607
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
608
+ role: "tablist",
609
+ "aria-label": "Select variant",
610
+ "aria-orientation": "horizontal",
611
+ style: {
612
+ display: "flex",
613
+ gap: "0.25rem",
614
+ "margin-bottom": "0.5rem"
615
+ },
616
+ onKeyDown: handleKeyDown,
617
+ children: /* @__PURE__ */ jsx(For, {
618
+ each: props.options,
619
+ children: (_opt, i) => {
620
+ const idx = i();
621
+ const isActive = () => idx === props.activeIndex;
622
+ const tabStyle = () => ({
623
+ padding: "0.25rem 0.75rem",
624
+ border: isActive() ? "1px solid #3b82f6" : "1px solid #d1d5db",
625
+ "border-radius": "0.25rem",
626
+ background: isActive() ? "#eff6ff" : "transparent",
627
+ cursor: "pointer",
628
+ "font-size": "0.875rem"
629
+ });
630
+ return /* @__PURE__ */ jsx("button", {
631
+ ref: (el) => {
632
+ tabRefs[idx] = el;
633
+ },
634
+ type: "button",
635
+ role: "tab",
636
+ id: tabIdFor(props.path, idx),
637
+ "aria-selected": isActive() ? "true" : "false",
638
+ "aria-controls": panelId,
639
+ tabindex: isActive() ? 0 : -1,
640
+ onClick: () => {
641
+ handleTabChange(idx);
642
+ },
643
+ style: tabStyle(),
644
+ children: props.optionLabels[idx]
645
+ });
646
+ }
647
+ })
648
+ }), /* @__PURE__ */ jsx("div", {
649
+ role: "tabpanel",
650
+ id: panelId,
651
+ "aria-labelledby": tabIdFor(props.path, props.activeIndex),
652
+ children: /* @__PURE__ */ jsx(Show, {
653
+ when: props.options[props.activeIndex],
654
+ children: (activeOption) => props.props.renderChild(activeOption(), props.props.value, props.props.onChange)
655
+ })
656
+ })] });
657
+ }
658
+ /** Headless renderer for `FileField` — plain `<input type="file">`. */
659
+ function renderFile(props) {
660
+ const id = inputId(props.path);
661
+ const accept = props.constraints.mimeTypes?.join(",");
662
+ if (props.readOnly) return /* @__PURE__ */ jsx("span", {
663
+ id,
664
+ children: "File field"
665
+ });
666
+ const ariaAttrs = buildAriaAttrs(props.tree, props.meta.description);
667
+ const hintInfo = buildHintInfo(id, props.constraints);
668
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
669
+ id,
670
+ type: "file",
671
+ accept,
672
+ onChange: (e) => {
673
+ const file = e.currentTarget.files?.[0];
674
+ if (file !== void 0) props.onChange(file);
675
+ },
676
+ "aria-describedby": hintInfo?.ariaDescribedBy,
677
+ ...ariaAttrs
678
+ }), /* @__PURE__ */ jsx(Show, {
679
+ when: hintInfo !== void 0,
680
+ children: /* @__PURE__ */ jsx("small", {
681
+ id: hintInfo?.id,
682
+ class: "sc-hint",
683
+ children: hintInfo?.hint
684
+ })
685
+ })] });
686
+ }
687
+ /**
688
+ * Render a literal field — `z.literal("a")` or `{ const: 5 }`.
689
+ *
690
+ * Literals are non-editable by nature; both read-only and editable modes
691
+ * display the literal value(s). Multiple literals (`z.literal(["a","b"])`)
692
+ * render comma-separated.
693
+ */
694
+ function renderLiteral(props) {
695
+ const id = inputId(props.path);
696
+ if (props.tree.type !== "literal") return null;
697
+ const values = props.tree.literalValues;
698
+ if (values.length === 0) return /* @__PURE__ */ jsx("span", {
699
+ id,
700
+ children: "—"
701
+ });
702
+ return /* @__PURE__ */ jsx("span", {
703
+ id,
704
+ children: values.map((v) => displayJsonValue(v)).join(", ")
705
+ });
706
+ }
707
+ /** Render a null field — `z.null()` or `{ type: "null" }`. */
708
+ function renderNull(props) {
709
+ return /* @__PURE__ */ jsx("span", {
710
+ id: inputId(props.path),
711
+ children: "—"
712
+ });
713
+ }
714
+ /** Render a never field — `z.never()` or `{ not: {} }` / `false` schema. */
715
+ function renderNever(props) {
716
+ return /* @__PURE__ */ jsx("span", {
717
+ id: inputId(props.path),
718
+ class: SC_CLASSES.never,
719
+ children: /* @__PURE__ */ jsx("em", { children: "never matches" })
720
+ });
721
+ }
722
+ /** Render a tuple field — positional rendering of each prefix item. */
723
+ function renderTuple(props) {
724
+ if (props.tree.type !== "tuple") return null;
725
+ const prefixItems = props.tree.prefixItems;
726
+ const restItems = props.tree.restItems;
727
+ const arr = Array.isArray(props.value) ? props.value : [];
728
+ if (prefixItems.length === 0 && restItems === void 0 && arr.length === 0) return null;
729
+ const restCount = restItems !== void 0 ? Math.max(arr.length - prefixItems.length, 0) : 0;
730
+ const restRange = Array.from({ length: restCount }, (_, j) => j);
731
+ return /* @__PURE__ */ jsxs("div", {
732
+ role: "group",
733
+ "aria-label": ariaLabel(props.meta.description),
734
+ children: [/* @__PURE__ */ jsx(For, {
735
+ each: prefixItems,
736
+ children: (element, i) => {
737
+ const idx = i();
738
+ const itemValue = arr[idx];
739
+ const childOnChange = (v) => {
740
+ const next = arr.slice();
741
+ next[idx] = v;
742
+ props.onChange(next);
743
+ };
744
+ return /* @__PURE__ */ jsx("div", { children: props.renderChild(element, itemValue, childOnChange, `[${String(idx)}]`) });
745
+ }
746
+ }), /* @__PURE__ */ jsx(Show, {
747
+ when: restItems,
748
+ children: (rest) => /* @__PURE__ */ jsx(For, {
749
+ each: restRange,
750
+ children: (j) => {
751
+ const idx = prefixItems.length + j;
752
+ const itemValue = arr[idx];
753
+ const childOnChange = (v) => {
754
+ const next = arr.slice();
755
+ next[idx] = v;
756
+ props.onChange(next);
757
+ };
758
+ return /* @__PURE__ */ jsx("div", { children: props.renderChild(rest(), itemValue, childOnChange, `[${String(idx)}]`) });
759
+ }
760
+ })
761
+ })]
762
+ });
763
+ }
764
+ /** Render a conditional field — JSON Schema `if`/`then`/`else`. */
765
+ function renderConditional(props) {
766
+ if (props.tree.type !== "conditional") return null;
767
+ const { ifClause, thenClause, elseClause } = props.tree;
768
+ return /* @__PURE__ */ jsxs("fieldset", {
769
+ class: SC_CLASSES.conditional,
770
+ children: [
771
+ /* @__PURE__ */ jsxs("div", {
772
+ class: SC_CLASSES.conditionalIf,
773
+ children: [
774
+ /* @__PURE__ */ jsx("strong", { children: "if:" }),
775
+ " ",
776
+ props.renderChild(ifClause, props.value, props.onChange)
777
+ ]
778
+ }),
779
+ /* @__PURE__ */ jsx(Show, {
780
+ when: thenClause,
781
+ children: (then) => /* @__PURE__ */ jsxs("div", {
782
+ class: SC_CLASSES.conditionalThen,
783
+ children: [
784
+ /* @__PURE__ */ jsx("strong", { children: "then:" }),
785
+ " ",
786
+ props.renderChild(then(), props.value, props.onChange)
787
+ ]
788
+ })
789
+ }),
790
+ /* @__PURE__ */ jsx(Show, {
791
+ when: elseClause,
792
+ children: (other) => /* @__PURE__ */ jsxs("div", {
793
+ class: SC_CLASSES.conditionalElse,
794
+ children: [
795
+ /* @__PURE__ */ jsx("strong", { children: "else:" }),
796
+ " ",
797
+ props.renderChild(other(), props.value, props.onChange)
798
+ ]
799
+ })
800
+ })
801
+ ]
802
+ });
803
+ }
804
+ /** Render a negation field — JSON Schema `{ not: { ... } }`. */
805
+ function renderNegation(props) {
806
+ if (props.tree.type !== "negation") return null;
807
+ return /* @__PURE__ */ jsxs("fieldset", {
808
+ class: SC_CLASSES.negation,
809
+ children: [
810
+ /* @__PURE__ */ jsx("strong", { children: "Must NOT match:" }),
811
+ " ",
812
+ props.renderChild(props.tree.negated, props.value, props.onChange)
813
+ ]
814
+ });
815
+ }
816
+ /** Headless renderer for `UnknownField` — JSON-encoded fallback. */
817
+ function renderUnknown(props) {
818
+ const id = inputId(props.path);
819
+ if (props.readOnly) {
820
+ if (props.value === void 0 || props.value === null) return /* @__PURE__ */ jsx("span", {
821
+ id,
822
+ children: "—"
823
+ });
824
+ return /* @__PURE__ */ jsx("span", {
825
+ id,
826
+ children: typeof props.value === "string" ? props.value : JSON.stringify(props.value)
827
+ });
828
+ }
829
+ const strValue = typeof props.value === "string" ? props.value : "";
830
+ return /* @__PURE__ */ jsx("input", {
831
+ id,
832
+ type: "text",
833
+ value: props.writeOnly ? "" : strValue,
834
+ onInput: (e) => {
835
+ props.onChange(e.currentTarget.value);
836
+ }
837
+ });
838
+ }
839
+ //#endregion
840
+ export { defaultRecordValue, discriminatedUnionValueForTab, inputId, nextRecordKey, renameRecordKey, renderArray, renderBoolean, renderConditional, renderDiscriminatedUnion, renderEnum, renderFile, renderLiteral, renderNegation, renderNever, renderNull, renderNumber, renderObject, renderRecord, renderString, renderTuple, renderUnion, renderUnknown };