1
- import type { JsfObjectSchema , JsfSchema , JsfSchemaType , NonBooleanJsfSchema } from '../types'
1
+ import type { JsfObjectSchema , JsfSchema , JsfSchemaType , NonBooleanJsfSchema , SchemaValue } from '../types'
2
2
import type { Field , FieldOption , FieldType } from './type'
3
3
import { setCustomOrder } from '../custom/order'
4
4
@@ -42,13 +42,15 @@ function addOptions(field: Field, schema: NonBooleanJsfSchema) {
42
42
* Add fields attribute to a field
43
43
* @param field - The field to add the fields to
44
44
* @param schema - The schema of the field
45
+ * @param originalSchema - The original schema (needed for calculating the original input type on conditionally hidden fields)
46
+ * @param strictInputType - Whether to strictly enforce the input type
45
47
* @description
46
48
* This adds the fields attribute to based on the schema's items.
47
49
* Since options and fields are mutually exclusive, we only add fields if no options were provided.
48
50
*/
49
- function addFields ( field : Field , schema : NonBooleanJsfSchema , strictInputType ?: boolean ) {
51
+ function addFields ( field : Field , schema : NonBooleanJsfSchema , originalSchema : JsfSchema , strictInputType ?: boolean ) {
50
52
if ( field . options === undefined ) {
51
- const fields = getFields ( schema , strictInputType )
53
+ const fields = getFields ( schema , originalSchema , strictInputType )
52
54
if ( fields ) {
53
55
field . fields = fields
54
56
}
@@ -129,8 +131,6 @@ You can fix the json schema or skip this error by calling createHeadlessForm(sch
129
131
if ( schema . properties ) {
130
132
return 'select'
131
133
}
132
-
133
- // Otherwise, assume "string" as the fallback type and get input from it
134
134
}
135
135
136
136
// Get input type from schema (fallback type is "string")
@@ -201,7 +201,7 @@ function getFieldOptions(schema: NonBooleanJsfSchema) {
201
201
if ( schema . enum ) {
202
202
const enumAsOneOf : JsfSchema [ 'oneOf' ] = schema . enum ?. map ( value => ( {
203
203
title : typeof value === 'string' ? value : JSON . stringify ( value ) ,
204
- const : value ,
204
+ const : value as SchemaValue ,
205
205
} ) ) || [ ]
206
206
return convertToOptions ( enumAsOneOf )
207
207
}
@@ -212,15 +212,22 @@ function getFieldOptions(schema: NonBooleanJsfSchema) {
212
212
/**
213
213
* Get the fields for an object schema
214
214
* @param schema - The schema of the field
215
+ * @param originalSchema - The original schema (needed for calculating the original input type on conditionally hidden fields)
215
216
* @param strictInputType - Whether to strictly enforce the input type
216
217
* @returns The fields for the schema or an empty array if the schema does not define any properties
217
218
*/
218
- function getObjectFields ( schema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] | null {
219
+ function getObjectFields ( schema : NonBooleanJsfSchema , originalSchema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] | null {
219
220
const fields : Field [ ] = [ ]
220
221
221
222
for ( const key in schema . properties ) {
222
223
const isRequired = schema . required ?. includes ( key ) || false
223
- const field = buildFieldSchema ( schema . properties [ key ] , key , isRequired , strictInputType )
224
+ const field = buildFieldSchema ( {
225
+ schema : schema . properties [ key ] ,
226
+ name : key ,
227
+ required : isRequired ,
228
+ originalSchema : originalSchema . properties ?. [ key ] || schema . properties [ key ] ,
229
+ strictInputType,
230
+ } )
224
231
if ( field ) {
225
232
fields . push ( field )
226
233
}
@@ -234,10 +241,11 @@ function getObjectFields(schema: NonBooleanJsfSchema, strictInputType?: boolean)
234
241
/**
235
242
* Get the fields for an array schema
236
243
* @param schema - The schema of the field
244
+ * @param originalSchema - The original schema (needed for calculating the original input type on conditionally hidden fields)
237
245
* @param strictInputType - Whether to strictly enforce the input type
238
246
* @returns The fields for the schema or an empty array if the schema does not define any items
239
247
*/
240
- function getArrayFields ( schema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] {
248
+ function getArrayFields ( schema : NonBooleanJsfSchema , originalSchema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] {
241
249
const fields : Field [ ] = [ ]
242
250
243
251
if ( typeof schema . items !== 'object' || schema . items === null ) {
@@ -249,15 +257,27 @@ function getArrayFields(schema: NonBooleanJsfSchema, strictInputType?: boolean):
249
257
250
258
for ( const key in objectSchema . properties ) {
251
259
const isFieldRequired = objectSchema . required ?. includes ( key ) || false
252
- const field = buildFieldSchema ( objectSchema . properties [ key ] , key , isFieldRequired , strictInputType )
260
+ const field = buildFieldSchema ( {
261
+ schema : objectSchema . properties [ key ] ,
262
+ name : key ,
263
+ required : isFieldRequired ,
264
+ originalSchema,
265
+ strictInputType,
266
+ } )
253
267
if ( field ) {
254
268
field . nameKey = key
255
269
fields . push ( field )
256
270
}
257
271
}
258
272
}
259
273
else {
260
- const field = buildFieldSchema ( schema . items , 'item' , false , strictInputType )
274
+ const field = buildFieldSchema ( {
275
+ schema : schema . items ,
276
+ name : 'item' ,
277
+ required : false ,
278
+ originalSchema,
279
+ strictInputType,
280
+ } )
261
281
if ( field ) {
262
282
fields . push ( field )
263
283
}
@@ -271,15 +291,16 @@ function getArrayFields(schema: NonBooleanJsfSchema, strictInputType?: boolean):
271
291
/**
272
292
* Get the fields for a schema from either `items` or `properties`
273
293
* @param schema - The schema of the field
294
+ * @param originalSchema - The original schema (needed for calculating the original input type on conditionally hidden fields)
274
295
* @param strictInputType - Whether to strictly enforce the input type
275
296
* @returns The fields for the schema
276
297
*/
277
- function getFields ( schema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] | null {
298
+ function getFields ( schema : NonBooleanJsfSchema , originalSchema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] | null {
278
299
if ( typeof schema . properties === 'object' && schema . properties !== null ) {
279
- return getObjectFields ( schema , strictInputType )
300
+ return getObjectFields ( schema , originalSchema , strictInputType )
280
301
}
281
302
else if ( typeof schema . items === 'object' && schema . items !== null ) {
282
- return getArrayFields ( schema , strictInputType )
303
+ return getArrayFields ( schema , originalSchema , strictInputType )
283
304
}
284
305
285
306
return null
@@ -298,26 +319,48 @@ const excludedSchemaProps = [
298
319
'properties' , // Handled separately
299
320
]
300
321
322
+ interface BuildFieldSchemaParams {
323
+ schema : JsfSchema
324
+ name : string
325
+ required ?: boolean
326
+ originalSchema : NonBooleanJsfSchema
327
+ strictInputType ?: boolean
328
+ type ?: JsfSchemaType
329
+ }
330
+
301
331
/**
302
332
* Build a field from any schema
333
+ * @param params - The parameters for building the field
334
+ * @param params.schema - The schema of the field
335
+ * @param params.name - The name of the field
336
+ * @param params.required - Whether the field is required
337
+ * @param params.originalSchema - The original schema (needed for calculating the original input type on conditionally hidden fields)
338
+ * @param params.strictInputType - Whether to strictly enforce the input type
339
+ * @param params.type - The schema type
340
+ * @returns The field
303
341
*/
304
- export function buildFieldSchema (
305
- schema : JsfSchema ,
306
- name : string ,
307
- required : boolean = false ,
308
- strictInputType : boolean = false ,
309
- type : JsfSchemaType = undefined ,
310
- ) : Field | null {
342
+ export function buildFieldSchema ( {
343
+ schema,
344
+ name,
345
+ required = false ,
346
+ originalSchema,
347
+ strictInputType = false ,
348
+ type = undefined ,
349
+ } : BuildFieldSchemaParams ) : Field | null {
311
350
// If schema is boolean false, return a field with isVisible=false
312
351
if ( schema === false ) {
313
- const inputType = getInputType ( type , name , schema , strictInputType )
352
+ // If the schema is false (hidden field), we use the original schema to get the input type
353
+ const inputType = getInputType ( type , name , originalSchema , strictInputType )
354
+ const inputHasInnerFields = [ 'fieldset' , 'group-array' ] . includes ( inputType )
355
+
314
356
return {
315
357
type : inputType ,
316
358
name,
317
359
inputType,
318
360
jsonType : 'boolean' ,
319
361
required,
320
362
isVisible : false ,
363
+ ...( inputHasInnerFields && { fields : [ ] } ) ,
321
364
}
322
365
}
323
366
@@ -369,7 +412,7 @@ export function buildFieldSchema(
369
412
}
370
413
371
414
addOptions ( field , schema )
372
- addFields ( field , schema )
415
+ addFields ( field , schema , originalSchema )
373
416
374
417
return field
375
418
}
0 commit comments