1- import type { JsfObjectSchema , JsfSchema , JsfSchemaType , NonBooleanJsfSchema } from '../types'
1+ import type { JsfObjectSchema , JsfSchema , JsfSchemaType , NonBooleanJsfSchema , SchemaValue } from '../types'
22import type { Field , FieldOption , FieldType } from './type'
33import { setCustomOrder } from '../custom/order'
44
@@ -42,13 +42,15 @@ function addOptions(field: Field, schema: NonBooleanJsfSchema) {
4242 * Add fields attribute to a field
4343 * @param field - The field to add the fields to
4444 * @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
4547 * @description
4648 * This adds the fields attribute to based on the schema's items.
4749 * Since options and fields are mutually exclusive, we only add fields if no options were provided.
4850 */
49- function addFields ( field : Field , schema : NonBooleanJsfSchema , strictInputType ?: boolean ) {
51+ function addFields ( field : Field , schema : NonBooleanJsfSchema , originalSchema : JsfSchema , strictInputType ?: boolean ) {
5052 if ( field . options === undefined ) {
51- const fields = getFields ( schema , strictInputType )
53+ const fields = getFields ( schema , originalSchema , strictInputType )
5254 if ( fields ) {
5355 field . fields = fields
5456 }
@@ -129,8 +131,6 @@ You can fix the json schema or skip this error by calling createHeadlessForm(sch
129131 if ( schema . properties ) {
130132 return 'select'
131133 }
132-
133- // Otherwise, assume "string" as the fallback type and get input from it
134134 }
135135
136136 // Get input type from schema (fallback type is "string")
@@ -201,7 +201,7 @@ function getFieldOptions(schema: NonBooleanJsfSchema) {
201201 if ( schema . enum ) {
202202 const enumAsOneOf : JsfSchema [ 'oneOf' ] = schema . enum ?. map ( value => ( {
203203 title : typeof value === 'string' ? value : JSON . stringify ( value ) ,
204- const : value ,
204+ const : value as SchemaValue ,
205205 } ) ) || [ ]
206206 return convertToOptions ( enumAsOneOf )
207207 }
@@ -212,15 +212,22 @@ function getFieldOptions(schema: NonBooleanJsfSchema) {
212212/**
213213 * Get the fields for an object schema
214214 * @param schema - The schema of the field
215+ * @param originalSchema - The original schema (needed for calculating the original input type on conditionally hidden fields)
215216 * @param strictInputType - Whether to strictly enforce the input type
216217 * @returns The fields for the schema or an empty array if the schema does not define any properties
217218 */
218- function getObjectFields ( schema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] | null {
219+ function getObjectFields ( schema : NonBooleanJsfSchema , originalSchema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] | null {
219220 const fields : Field [ ] = [ ]
220221
221222 for ( const key in schema . properties ) {
222223 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+ } )
224231 if ( field ) {
225232 fields . push ( field )
226233 }
@@ -234,10 +241,11 @@ function getObjectFields(schema: NonBooleanJsfSchema, strictInputType?: boolean)
234241/**
235242 * Get the fields for an array schema
236243 * @param schema - The schema of the field
244+ * @param originalSchema - The original schema (needed for calculating the original input type on conditionally hidden fields)
237245 * @param strictInputType - Whether to strictly enforce the input type
238246 * @returns The fields for the schema or an empty array if the schema does not define any items
239247 */
240- function getArrayFields ( schema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] {
248+ function getArrayFields ( schema : NonBooleanJsfSchema , originalSchema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] {
241249 const fields : Field [ ] = [ ]
242250
243251 if ( typeof schema . items !== 'object' || schema . items === null ) {
@@ -249,15 +257,27 @@ function getArrayFields(schema: NonBooleanJsfSchema, strictInputType?: boolean):
249257
250258 for ( const key in objectSchema . properties ) {
251259 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+ } )
253267 if ( field ) {
254268 field . nameKey = key
255269 fields . push ( field )
256270 }
257271 }
258272 }
259273 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+ } )
261281 if ( field ) {
262282 fields . push ( field )
263283 }
@@ -271,15 +291,16 @@ function getArrayFields(schema: NonBooleanJsfSchema, strictInputType?: boolean):
271291/**
272292 * Get the fields for a schema from either `items` or `properties`
273293 * @param schema - The schema of the field
294+ * @param originalSchema - The original schema (needed for calculating the original input type on conditionally hidden fields)
274295 * @param strictInputType - Whether to strictly enforce the input type
275296 * @returns The fields for the schema
276297 */
277- function getFields ( schema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] | null {
298+ function getFields ( schema : NonBooleanJsfSchema , originalSchema : NonBooleanJsfSchema , strictInputType ?: boolean ) : Field [ ] | null {
278299 if ( typeof schema . properties === 'object' && schema . properties !== null ) {
279- return getObjectFields ( schema , strictInputType )
300+ return getObjectFields ( schema , originalSchema , strictInputType )
280301 }
281302 else if ( typeof schema . items === 'object' && schema . items !== null ) {
282- return getArrayFields ( schema , strictInputType )
303+ return getArrayFields ( schema , originalSchema , strictInputType )
283304 }
284305
285306 return null
@@ -298,26 +319,48 @@ const excludedSchemaProps = [
298319 'properties' , // Handled separately
299320]
300321
322+ interface BuildFieldSchemaParams {
323+ schema : JsfSchema
324+ name : string
325+ required ?: boolean
326+ originalSchema : NonBooleanJsfSchema
327+ strictInputType ?: boolean
328+ type ?: JsfSchemaType
329+ }
330+
301331/**
302332 * 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
303341 */
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 {
311350 // If schema is boolean false, return a field with isVisible=false
312351 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+
314356 return {
315357 type : inputType ,
316358 name,
317359 inputType,
318360 jsonType : 'boolean' ,
319361 required,
320362 isVisible : false ,
363+ ...( inputHasInnerFields && { fields : [ ] } ) ,
321364 }
322365 }
323366
@@ -369,7 +412,7 @@ export function buildFieldSchema(
369412 }
370413
371414 addOptions ( field , schema )
372- addFields ( field , schema )
415+ addFields ( field , schema , originalSchema )
373416
374417 return field
375418}
0 commit comments