@uniform-ts/core 0.0.0 → 0.0.2
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.
- package/README.md +20 -1
- package/dist/index.d.mts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +46 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -468,7 +468,26 @@ const schema = z.object({
|
|
|
468
468
|
|
|
469
469
|
Zod still validates the array (`.min(1)` etc.) — only the _render_ is taken over by your component.
|
|
470
470
|
|
|
471
|
-
#### Option 2 —
|
|
471
|
+
#### Option 2 — String field as select
|
|
472
|
+
|
|
473
|
+
A `z.string()` field can be rendered as a select by setting `meta.component: 'select'` together with `meta.options`. UniForm treats it as type `"select"` during introspection:
|
|
474
|
+
|
|
475
|
+
```ts
|
|
476
|
+
const schema = z.object({
|
|
477
|
+
role: z.string().meta({
|
|
478
|
+
component: 'select',
|
|
479
|
+
options: [
|
|
480
|
+
{ label: 'User', value: 'user' },
|
|
481
|
+
{ label: 'Admin', value: 'admin' },
|
|
482
|
+
{ label: 'Editor', value: 'editor' },
|
|
483
|
+
],
|
|
484
|
+
}),
|
|
485
|
+
})
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
This is an alternative to `z.enum(...)` — useful when the option list is dynamic or when you need a plain `string` output type rather than a union literal.
|
|
489
|
+
|
|
490
|
+
#### Option 3 — Named key in the registry
|
|
472
491
|
|
|
473
492
|
Register a component under a custom string key — either in `createAutoForm` or the `components` prop — then reference it with `meta.component: 'yourKey'`:
|
|
474
493
|
|
package/dist/index.d.mts
CHANGED
|
@@ -181,6 +181,26 @@ type FieldConfigBase = {
|
|
|
181
181
|
required: boolean;
|
|
182
182
|
/** Merged UI metadata for the field. */
|
|
183
183
|
meta: FieldMeta;
|
|
184
|
+
/**
|
|
185
|
+
* The original Zod schema for this field, after transparent wrappers
|
|
186
|
+
* (`optional`, `nullable`, `default`, `pipe`) have been stripped.
|
|
187
|
+
*
|
|
188
|
+
* This is a general escape hatch for custom components that need to inspect
|
|
189
|
+
* the raw schema — for example, to read union variants, access custom Zod
|
|
190
|
+
* metadata not captured by introspection, or build schema-aware validation UI.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* function MyUnionInput({ field }: FieldProps) {
|
|
194
|
+
* // Inspect the original schema for any edge case
|
|
195
|
+
* const schema = field.schema
|
|
196
|
+
* if (schema._zod.def.type === 'union') {
|
|
197
|
+
* const variants = (schema._zod.def as z.$ZodUnionDef).options
|
|
198
|
+
* // render a type-switcher using the raw Zod variants
|
|
199
|
+
* }
|
|
200
|
+
* return <input ... />
|
|
201
|
+
* }
|
|
202
|
+
*/
|
|
203
|
+
schema: z.$ZodType;
|
|
184
204
|
};
|
|
185
205
|
/**
|
|
186
206
|
* The fully resolved configuration for a single form field, produced by
|
|
@@ -256,6 +276,12 @@ type FieldProps = {
|
|
|
256
276
|
options?: SelectOption[];
|
|
257
277
|
/** Full field metadata, including any custom keys. */
|
|
258
278
|
meta: FieldMeta;
|
|
279
|
+
/**
|
|
280
|
+
* The original Zod schema for this field (after transparent wrappers are stripped).
|
|
281
|
+
* Use this as an escape hatch when you need capabilities beyond what `FieldConfig`
|
|
282
|
+
* exposes — e.g. inspecting union variants, accessing custom Zod refinements, etc.
|
|
283
|
+
*/
|
|
284
|
+
schema: z.$ZodType;
|
|
259
285
|
};
|
|
260
286
|
/**
|
|
261
287
|
* A map of field type keys to React components used to render them.
|
package/dist/index.d.ts
CHANGED
|
@@ -181,6 +181,26 @@ type FieldConfigBase = {
|
|
|
181
181
|
required: boolean;
|
|
182
182
|
/** Merged UI metadata for the field. */
|
|
183
183
|
meta: FieldMeta;
|
|
184
|
+
/**
|
|
185
|
+
* The original Zod schema for this field, after transparent wrappers
|
|
186
|
+
* (`optional`, `nullable`, `default`, `pipe`) have been stripped.
|
|
187
|
+
*
|
|
188
|
+
* This is a general escape hatch for custom components that need to inspect
|
|
189
|
+
* the raw schema — for example, to read union variants, access custom Zod
|
|
190
|
+
* metadata not captured by introspection, or build schema-aware validation UI.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* function MyUnionInput({ field }: FieldProps) {
|
|
194
|
+
* // Inspect the original schema for any edge case
|
|
195
|
+
* const schema = field.schema
|
|
196
|
+
* if (schema._zod.def.type === 'union') {
|
|
197
|
+
* const variants = (schema._zod.def as z.$ZodUnionDef).options
|
|
198
|
+
* // render a type-switcher using the raw Zod variants
|
|
199
|
+
* }
|
|
200
|
+
* return <input ... />
|
|
201
|
+
* }
|
|
202
|
+
*/
|
|
203
|
+
schema: z.$ZodType;
|
|
184
204
|
};
|
|
185
205
|
/**
|
|
186
206
|
* The fully resolved configuration for a single form field, produced by
|
|
@@ -256,6 +276,12 @@ type FieldProps = {
|
|
|
256
276
|
options?: SelectOption[];
|
|
257
277
|
/** Full field metadata, including any custom keys. */
|
|
258
278
|
meta: FieldMeta;
|
|
279
|
+
/**
|
|
280
|
+
* The original Zod schema for this field (after transparent wrappers are stripped).
|
|
281
|
+
* Use this as an escape hatch when you need capabilities beyond what `FieldConfig`
|
|
282
|
+
* exposes — e.g. inspecting union variants, accessing custom Zod refinements, etc.
|
|
283
|
+
*/
|
|
284
|
+
schema: z.$ZodType;
|
|
259
285
|
};
|
|
260
286
|
/**
|
|
261
287
|
* A map of field type keys to React components used to render them.
|
package/dist/index.js
CHANGED
|
@@ -83,25 +83,30 @@ function introspectSchema(schema, name = "", parentPath = "") {
|
|
|
83
83
|
let maxItems;
|
|
84
84
|
try {
|
|
85
85
|
if (kind === "string") {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
mergedMeta["inputType"] = "email";
|
|
90
|
-
} else if (defFormat === "url") {
|
|
91
|
-
mergedMeta["inputType"] = "url";
|
|
92
|
-
} else if (defFormat === "uuid") {
|
|
93
|
-
mergedMeta["inputType"] = "uuid";
|
|
86
|
+
if (mergedMeta.component === "select" && Array.isArray(mergedMeta.options) && mergedMeta.options.length > 0) {
|
|
87
|
+
type = "select";
|
|
88
|
+
options = mergedMeta.options;
|
|
94
89
|
} else {
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
);
|
|
99
|
-
if (hasFormat("email")) {
|
|
90
|
+
type = "string";
|
|
91
|
+
const defFormat = def.format;
|
|
92
|
+
if (defFormat === "email") {
|
|
100
93
|
mergedMeta["inputType"] = "email";
|
|
101
|
-
} else if (
|
|
94
|
+
} else if (defFormat === "url") {
|
|
102
95
|
mergedMeta["inputType"] = "url";
|
|
103
|
-
} else if (
|
|
96
|
+
} else if (defFormat === "uuid") {
|
|
104
97
|
mergedMeta["inputType"] = "uuid";
|
|
98
|
+
} else {
|
|
99
|
+
const checks = def.checks ?? [];
|
|
100
|
+
const hasFormat = (fmt) => checks.some(
|
|
101
|
+
(c) => c._zod.def.check === "string_format" && c._zod.def.format === fmt
|
|
102
|
+
);
|
|
103
|
+
if (hasFormat("email")) {
|
|
104
|
+
mergedMeta["inputType"] = "email";
|
|
105
|
+
} else if (hasFormat("url")) {
|
|
106
|
+
mergedMeta["inputType"] = "url";
|
|
107
|
+
} else if (hasFormat("uuid")) {
|
|
108
|
+
mergedMeta["inputType"] = "uuid";
|
|
109
|
+
}
|
|
105
110
|
}
|
|
106
111
|
}
|
|
107
112
|
} else if (kind === "number") {
|
|
@@ -138,15 +143,24 @@ function introspectSchema(schema, name = "", parentPath = "") {
|
|
|
138
143
|
}
|
|
139
144
|
}
|
|
140
145
|
} else if (def.type === "union") {
|
|
141
|
-
type = "union";
|
|
142
146
|
const unionDef = def;
|
|
147
|
+
const variants = unionDef.options;
|
|
143
148
|
if ("discriminator" in unionDef) {
|
|
149
|
+
type = "union";
|
|
144
150
|
discriminatorKey = unionDef.discriminator;
|
|
151
|
+
unionVariants = variants.map(
|
|
152
|
+
(variant, i) => introspectSchema(variant, String(i), path)
|
|
153
|
+
);
|
|
154
|
+
} else {
|
|
155
|
+
const collapsed = introspectSchema(variants[0], name, parentPath);
|
|
156
|
+
return {
|
|
157
|
+
...collapsed,
|
|
158
|
+
name: path,
|
|
159
|
+
label,
|
|
160
|
+
meta: { ...collapsed.meta, ...mergedMeta },
|
|
161
|
+
schema: inner
|
|
162
|
+
};
|
|
145
163
|
}
|
|
146
|
-
const variants = unionDef.options;
|
|
147
|
-
unionVariants = variants.map(
|
|
148
|
-
(variant, i) => introspectSchema(variant, String(i), path)
|
|
149
|
-
);
|
|
150
164
|
}
|
|
151
165
|
} catch {
|
|
152
166
|
type = "unknown";
|
|
@@ -157,6 +171,7 @@ function introspectSchema(schema, name = "", parentPath = "") {
|
|
|
157
171
|
label,
|
|
158
172
|
required,
|
|
159
173
|
meta: mergedMeta,
|
|
174
|
+
schema: inner,
|
|
160
175
|
...options !== void 0 && { options },
|
|
161
176
|
...children !== void 0 && { children },
|
|
162
177
|
...itemConfig !== void 0 && { itemConfig },
|
|
@@ -195,6 +210,7 @@ function parseDiscriminatedUnionMeta(schema) {
|
|
|
195
210
|
label: deriveLabel(discriminatorKey),
|
|
196
211
|
required: true,
|
|
197
212
|
meta: {},
|
|
213
|
+
schema,
|
|
198
214
|
options: discriminatorOptions
|
|
199
215
|
};
|
|
200
216
|
return {
|
|
@@ -495,7 +511,7 @@ function ScalarField({
|
|
|
495
511
|
onChange: (value) => {
|
|
496
512
|
const coerced = coerceValue(field.type, value, coercions);
|
|
497
513
|
rhfField.onChange(coerced);
|
|
498
|
-
field.meta.onChange?.(coerced, formMethods);
|
|
514
|
+
void field.meta.onChange?.(coerced, formMethods);
|
|
499
515
|
},
|
|
500
516
|
onBlur: rhfField.onBlur,
|
|
501
517
|
ref: rhfField.ref,
|
|
@@ -505,7 +521,9 @@ function ScalarField({
|
|
|
505
521
|
error: fieldState.error?.message,
|
|
506
522
|
required: field.required,
|
|
507
523
|
disabled: field.meta.disabled || contextDisabled,
|
|
508
|
-
|
|
524
|
+
options: field.meta.options,
|
|
525
|
+
meta: field.meta,
|
|
526
|
+
schema: field.schema
|
|
509
527
|
}
|
|
510
528
|
)
|
|
511
529
|
}
|
|
@@ -537,7 +555,7 @@ function BooleanField({
|
|
|
537
555
|
value: rhfField.value ?? false,
|
|
538
556
|
onChange: (value) => {
|
|
539
557
|
rhfField.onChange(value);
|
|
540
|
-
field.meta.onChange?.(value, formMethods);
|
|
558
|
+
void field.meta.onChange?.(value, formMethods);
|
|
541
559
|
},
|
|
542
560
|
onBlur: rhfField.onBlur,
|
|
543
561
|
ref: rhfField.ref,
|
|
@@ -547,7 +565,8 @@ function BooleanField({
|
|
|
547
565
|
error: fieldState.error?.message,
|
|
548
566
|
required: field.required,
|
|
549
567
|
disabled: field.meta.disabled || rhfField.disabled || contextDisabled,
|
|
550
|
-
meta: field.meta
|
|
568
|
+
meta: field.meta,
|
|
569
|
+
schema: field.schema
|
|
551
570
|
}
|
|
552
571
|
)
|
|
553
572
|
}
|
|
@@ -579,7 +598,7 @@ function SelectField({
|
|
|
579
598
|
value: rhfField.value ?? "",
|
|
580
599
|
onChange: (value) => {
|
|
581
600
|
rhfField.onChange(value);
|
|
582
|
-
field.meta.onChange?.(value, formMethods);
|
|
601
|
+
void field.meta.onChange?.(value, formMethods);
|
|
583
602
|
},
|
|
584
603
|
onBlur: rhfField.onBlur,
|
|
585
604
|
ref: rhfField.ref,
|
|
@@ -590,7 +609,8 @@ function SelectField({
|
|
|
590
609
|
required: field.required,
|
|
591
610
|
disabled: field.meta.disabled || contextDisabled,
|
|
592
611
|
options: field.options,
|
|
593
|
-
meta: field.meta
|
|
612
|
+
meta: field.meta,
|
|
613
|
+
schema: field.schema
|
|
594
614
|
}
|
|
595
615
|
)
|
|
596
616
|
}
|