@@ -9,7 +9,10 @@ import type {
99import { useFrontendClient } from "./frontend-client-context" ;
1010import type { ComponentFormProps } from "../components/ComponentForm" ;
1111import type { FormFieldContext } from "./form-field-context" ;
12- import { appPropError } from "./use-app" ;
12+ import {
13+ appPropErrors , arrayPropErrors , booleanPropErrors , integerPropErrors ,
14+ stringPropErrors ,
15+ } from "../utils/component" ;
1316
1417export type DynamicProps < T extends ConfigurableProps > = { id : string ; configurableProps : T ; } ; // TODO
1518
@@ -19,6 +22,7 @@ export type FormContext<T extends ConfigurableProps> = {
1922 configuredProps : ConfiguredProps < T > ;
2023 dynamicProps ?: DynamicProps < T > ; // lots of calls require dynamicProps?.id, so need to expose
2124 dynamicPropsQueryIsFetching ?: boolean ;
25+ errors : Record < string , string [ ] > ;
2226 fields : Record < string , FormFieldContext < ConfigurableProp > > ;
2327 id : string ;
2428 isValid : boolean ;
@@ -168,55 +172,39 @@ export const FormContextProvider = <T extends ConfigurableProps>({
168172 // so can't rely on that base control form validation
169173 const propErrors = ( prop : ConfigurableProp , value : unknown ) : string [ ] => {
170174 const errs : string [ ] = [ ] ;
171- if ( value === undefined ) {
172- if ( ! prop . optional ) {
173- errs . push ( "required" ) ;
174- }
175- } else if ( prop . type === "integer" ) { // XXX type should be "number"? we don't support floats otherwise...
176- if ( typeof value !== "number" ) {
177- errs . push ( "not a number" ) ;
178- } else {
179- if ( prop . min != null && value < prop . min ) {
180- errs . push ( "number too small" ) ;
181- }
182- if ( prop . max != null && value > prop . max ) {
183- errs . push ( "number too big" ) ;
184- }
185- }
186- } else if ( prop . type === "boolean" ) {
187- if ( typeof value !== "boolean" ) {
188- errs . push ( "not a boolean" ) ;
189- }
190- } else if ( prop . type === "string" ) {
191- type StringProp = ConfigurableProp & {
192- min ?: number ;
193- max ?: number ;
194- }
195- const {
196- min = 1 , max,
197- } = prop as StringProp ;
198- if ( typeof value !== "string" ) {
199- errs . push ( "not a string" ) ;
200- } else {
201- if ( value . length < min ) {
202- errs . push ( `string length must be at least ${ min } characters` ) ;
203- }
204- if ( max && value . length > max ) {
205- errs . push ( `string length must not exceed ${ max } characters` ) ;
206- }
207- }
208- } else if ( prop . type === "app" ) {
175+ if ( prop . optional || prop . hidden || prop . disabled ) return [ ]
176+ if ( prop . type === "app" ) {
209177 const field = fields [ prop . name ]
210178 if ( field ) {
211179 const app = field . extra . app
212- const err = appPropError ( {
180+ errs . push ( ...( appPropErrors ( {
181+ prop,
213182 value,
214183 app,
215- } )
216- if ( err ) errs . push ( err )
184+ } ) ?? [ ] ) )
217185 } else {
218186 errs . push ( "field not registered" )
219187 }
188+ } else if ( prop . type === "boolean" ) {
189+ errs . push ( ...( booleanPropErrors ( {
190+ prop,
191+ value,
192+ } ) ?? [ ] ) )
193+ } else if ( prop . type === "integer" ) {
194+ errs . push ( ...( integerPropErrors ( {
195+ prop,
196+ value,
197+ } ) ?? [ ] ) )
198+ } else if ( prop . type === "string" ) {
199+ errs . push ( ...( stringPropErrors ( {
200+ prop,
201+ value,
202+ } ) ?? [ ] ) )
203+ } else if ( prop . type === "string[]" ) {
204+ errs . push ( ...( arrayPropErrors ( {
205+ prop,
206+ value,
207+ } ) ?? [ ] ) )
220208 }
221209 return errs ;
222210 } ;
@@ -377,6 +365,7 @@ export const FormContextProvider = <T extends ConfigurableProps>({
377365 configuredProps,
378366 dynamicProps,
379367 dynamicPropsQueryIsFetching,
368+ errors,
380369 fields,
381370 optionalPropIsEnabled,
382371 optionalPropSetEnabled,
0 commit comments