diff --git a/src/field/schema.ts b/src/field/schema.ts index ab93f207..60c394d3 100644 --- a/src/field/schema.ts +++ b/src/field/schema.ts @@ -160,8 +160,7 @@ function convertToOptions(nodeOptions: JsfSchema[]): Array { .map((schemaOption) => { const title = schemaOption.title const value = schemaOption.const - const presentation = schemaOption['x-jsf-presentation'] - const meta = presentation?.meta + const presentation = typeof schemaOption['x-jsf-presentation'] === 'object' ? schemaOption['x-jsf-presentation'] : {} const result: { label: string @@ -172,15 +171,10 @@ function convertToOptions(nodeOptions: JsfSchema[]): Array { value, } - // Add meta if it exists - if (meta) { - result.meta = meta - } - // Add other properties, without known ones we already handled above const { title: _, const: __, 'x-jsf-presentation': ___, ...rest } = schemaOption - return { ...result, ...rest } + return { ...result, ...presentation, ...rest } }) } diff --git a/test/fields.test.ts b/test/fields.test.ts index f764b0bc..d39165d3 100644 --- a/test/fields.test.ts +++ b/test/fields.test.ts @@ -441,6 +441,79 @@ describe('fields', () => { }, ]) }) + + it('supports x-jsf-presentation properties inside options', () => { + const schema: JsfSchema = { + type: 'object', + properties: { + plan: { + 'type': 'string', + 'oneOf': [ + { const: 'free', title: 'Free' }, + { 'const': 'basic', 'title': 'Basic', 'x-jsf-presentation': { meta: { displayCost: '$30.00/mo', originalCost: '$35.00/mo' } } }, + { 'const': 'standard', 'title': 'Standard', 'x-jsf-presentation': { meta: { displayCost: '$50.00/mo' }, recommended: true } }, + ], + 'x-jsf-presentation': { + inputType: 'radio', + }, + }, + }, + } + + const fields = buildFieldSchema(schema, 'root', true)!.fields! + + expect(fields).toEqual([ + { + inputType: 'radio', + type: 'radio', + jsonType: 'string', + isVisible: true, + name: 'plan', + required: false, + options: [ + { label: 'Free', value: 'free' }, + { label: 'Basic', value: 'basic', meta: { displayCost: '$30.00/mo', originalCost: '$35.00/mo' } }, + { label: 'Standard', value: 'standard', meta: { displayCost: '$50.00/mo' }, recommended: true }, + ], + }, + ]) + }) + + it('ignores a non-object x-jsf-presentation', () => { + const schema: JsfSchema = { + type: 'object', + properties: { + plan: { + 'type': 'string', + 'oneOf': [ + { const: 'free', title: 'Free' }, + // @ts-expect-error - using an invalid value on purpose + { 'const': 'basic', 'title': 'Basic', 'x-jsf-presentation': '$30.00/mo' }, + ], + 'x-jsf-presentation': { + inputType: 'radio', + }, + }, + }, + } + + const fields = buildFieldSchema(schema, 'root', true)!.fields! + + expect(fields).toEqual([ + { + inputType: 'radio', + type: 'radio', + jsonType: 'string', + isVisible: true, + name: 'plan', + required: false, + options: [ + { label: 'Free', value: 'free' }, + { label: 'Basic', value: 'basic' }, + ], + }, + ]) + }) }) describe('input type calculation', () => {