Skip to content
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 109 additions & 33 deletions next/src/field/type.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,123 @@
import type { JsfSchemaType } from '../types'
Copy link
Collaborator

@sandrina-p sandrina-p May 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @eng-almeida 👋 I'll review it this afternoon around 16:00!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eng-almeida when do you plan to finish this MR?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @sandrina-p, sorry for dropping the ball here. I'll try to wrap this up next week 🤞


/**
* WIP type for UI field output that allows for all `x-jsf-presentation` properties to be splatted
* TODO/QUESTION: what are the required fields for a field? what are the things we want to deprecate, if any?
*/
export interface Field {
name: string
label?: string
description?: string
fields?: Field[]
// @deprecated in favor of inputType,
export type FieldType = 'text' | 'number' | 'select' | 'file' | 'radio' | 'group-array' | 'email' | 'date' | 'checkbox' | 'fieldset' | 'money' | 'country' | 'textarea'
Copy link
Collaborator

@sandrina-p sandrina-p May 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: Here's my controversial opinion: JSF does not care about FieldType, it's whatever comes from JSON schema x-jsf-presentation.inputType. We do not provide any extra logic/validation just based on it, right? (right? 👀)

So answering @lukad question:

We don't actually have any sort of validation that checks that when for example 'x-js-presentation': { 'inputType': 'money'} is given there is also 'x-js-presentation': { 'currency': 'EUR'}. @sandrina-p, is that something we do in v0?

We don't and we shouldn't. That logic is a concern of Remote internals, not JSF as headless generator/validator. If we ever validate that, it's another layer on top of JSON-SCHEMA-FORM

Does it make sense to you both?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P.S. I know, this kind affects most of your MR, as the field types should be based on the json schema type, not the inputType 😶

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @eng-almeida , when do you plan to finish this PR? :)


interface BaseField {
type: FieldType
inputType: FieldType
name: string
label: string
required: boolean
inputType: FieldType
jsonType: JsfSchemaType
isVisible: boolean
accept?: string
errorMessage?: Record<string, string>
computedAttributes?: Record<string, unknown>
errorMessage: Record<string, string>
schema: any
isVisible: boolean
description?: string
statement?: {
title: string
inputType: 'statement'
severity: 'warning' | 'error' | 'info'
}
[key: string]: unknown
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line hides a lot of TS errors that are hard to address without it. I'll keep investigating...

}

export interface FieldOption {
label: string
value: string
description?: string
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo:

  1. The FieldOption is a mirror of oneOf, so if the oneOf has, foo inside, then the Type includes foo too.
  2. value is not necessarily a string, can be anything, number, bool, even object. It's a mirror of oneOf.const 🪩
  3. value can be optional too :p Look at this example with pattern

}

export interface FieldSelect extends BaseField {
type: 'select'
options: FieldOption[]
}

export interface FieldTextarea extends BaseField {
type: 'textarea'
maxLength: number
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxLength ia not mandatory in a JsonSchema and if not provided it won't be in the field.

Suggested change
maxLength: number
maxLength?: number

minLength?: number
}

export interface FieldDate extends BaseField {
type: 'date'
format: string
minDate?: string
maxDate?: string
maxLength?: number
maxFileSize?: number
format?: string
anyOf?: unknown[]
options?: unknown[]
const?: unknown
checkboxValue?: unknown

// Allow additional properties from x-jsf-presentation (e.g. meta from oneOf/anyOf)
[key: string]: unknown
}

/**
* Field option
* @description
* Represents a key/value pair that is used to populate the options for a field.
* Will be created from the oneOf/anyOf elements in a schema.
*/
export interface FieldOption {
export interface FieldText extends BaseField {
type: 'text'
maxLength: number
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as with FieldTextArea.

maskSecret?: number
}

export interface FieldRadio extends BaseField {
type: 'radio'
options: FieldOption[]
direction?: 'row' | 'column'
Copy link
Collaborator

@sandrina-p sandrina-p May 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: Here's another example. This is Remote internal need, not a JSF concern. A few other examples down the line (currency, fileDownload, statement, etc... All of those Types can exist, but not at JSF.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right 💯 ! Probably the right move is to extend these types on Remote SDK project which uses Remote JSON Schemas 👍

const?: string
}

export interface FieldNumber extends BaseField {
type: 'number'
}

export interface FieldMoney extends BaseField {
type: 'money'
currency: string
}

export interface FieldCheckbox extends BaseField {
type: 'checkbox'
options?: FieldOption[]
multiple?: boolean
direction?: 'row' | 'column'
checkboxValue?: string | boolean
const?: string
}

export interface FieldEmail extends BaseField {
type: 'email'
maxLength: number
format: 'email'
}

export interface FieldFile extends BaseField {
type: 'file'
accept: string
multiple?: boolean
fileDownload: string
fileName: string
}
export interface FieldFieldSet extends BaseField {
type: 'fieldset'
valueGroupingDisabled?: boolean
visualGroupingDisabled?: boolean
variant?: 'card' | 'focused' | 'default'
fields: Field[]
}

export interface GroupArrayField extends BaseField {
type: 'group-array'
name: string
label: string
value: unknown
[key: string]: unknown
description: string
fields: () => Field[]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug: This is v0, in v1 is fields: Field[] (Once #177 is merged)) :D

addFieldText: string
}

export type FieldType = 'text' | 'number' | 'select' | 'file' | 'radio' | 'group-array' | 'email' | 'date' | 'checkbox' | 'fieldset' | 'money' | 'country' | 'textarea'
export type Field =
| FieldSelect
| FieldTextarea
| FieldDate
| FieldText
| FieldRadio
| FieldNumber
| FieldMoney
| FieldCheckbox
| FieldEmail
| FieldFile
| FieldFieldSet
| GroupArrayField
Loading