@@ -8,26 +8,53 @@ const ValueConstraints = ({ attribute, onUpdate }) => {
88 const [ constInput , setConstInput ] = useState ( '' ) ;
99 const [ enumInput , setEnumInput ] = useState ( '' ) ;
1010
11+ // For arrays with simple item types (not $ref), enum/const should be on items, not the array itself
12+ const isSimpleArray = attribute . type === 'array' && attribute . items && ! attribute . items . $ref ;
13+ const effectiveType = isSimpleArray ? attribute . items ?. type : attribute . type ;
14+
15+ // Get enum value from the correct location (items for simple arrays, attribute otherwise)
16+ const currentEnum = isSimpleArray ? attribute . items ?. enum : attribute . enum ;
17+ const currentConst = isSimpleArray ? attribute . items ?. const : attribute . const ;
18+
1119 // Initialize local state from attribute values
1220 useEffect ( ( ) => {
13- setConstInput ( formatValueForInput ( attribute . const ) ) ;
14- } , [ attribute . const ] ) ;
21+ setConstInput ( formatValueForInput ( currentConst ) ) ;
22+ } , [ currentConst ] ) ;
1523
1624 // Initialize enum input as empty (it's only shown when no enum exists yet)
1725 useEffect ( ( ) => {
18- if ( ! attribute . enum || attribute . enum . length === 0 ) {
26+ if ( ! currentEnum || currentEnum . length === 0 ) {
1927 setEnumInput ( '' ) ;
2028 }
21- } , [ attribute . enum ] ) ;
29+ } , [ currentEnum ] ) ;
30+
31+ // Helper to update enum/const at the correct level (items for simple arrays)
32+ const updateValueConstraint = ( updates ) => {
33+ if ( isSimpleArray ) {
34+ // Place enum/const inside items for simple arrays
35+ // Need to handle undefined values by explicitly removing keys
36+ const newItems = { ...attribute . items } ;
37+ Object . keys ( updates ) . forEach ( ( key ) => {
38+ if ( updates [ key ] === undefined ) {
39+ delete newItems [ key ] ;
40+ } else {
41+ newItems [ key ] = updates [ key ] ;
42+ }
43+ } ) ;
44+ onUpdate ( { items : newItems } ) ;
45+ } else {
46+ onUpdate ( updates ) ;
47+ }
48+ } ;
2249
2350 // Handle Const field blur - parse and update parent state
2451 const handleConstBlur = ( ) => {
2552 if ( ! constInput ) {
26- onUpdate ( { const : undefined } ) ;
53+ updateValueConstraint ( { const : undefined } ) ;
2754 return ;
2855 }
29- const parsed = parseInputValue ( constInput , attribute . type ) ;
30- onUpdate ( { const : parsed } ) ;
56+ const parsed = parseInputValue ( constInput , effectiveType ) ;
57+ updateValueConstraint ( { const : parsed } ) ;
3158 } ;
3259
3360 // Handle Enum field blur - parse and update parent state
@@ -36,66 +63,101 @@ const ValueConstraints = ({ attribute, onUpdate }) => {
3663 if ( value ) {
3764 try {
3865 const parsed = JSON . parse ( `[${ value } ]` ) ;
39- onUpdate ( { enum : parsed } ) ;
66+ updateValueConstraint ( { enum : parsed } ) ;
4067 } catch {
4168 const enumValues = value
4269 . split ( ',' )
4370 . map ( ( v ) => v . trim ( ) )
4471 . filter ( ( v ) => v ) ;
45- onUpdate ( { enum : enumValues . length > 0 ? enumValues : undefined } ) ;
72+ updateValueConstraint ( { enum : enumValues . length > 0 ? enumValues : undefined } ) ;
4673 }
4774 // Clear the input after successful processing
4875 setEnumInput ( '' ) ;
4976 }
5077 } ;
5178
79+ // Get placeholder examples based on effective type
80+ const getEnumPlaceholder = ( ) => {
81+ switch ( effectiveType ) {
82+ case 'number' :
83+ case 'integer' :
84+ return 'e.g., 1, 2, 3' ;
85+ case 'boolean' :
86+ return 'e.g., true, false' ;
87+ default :
88+ return 'e.g., active, pending, completed' ;
89+ }
90+ } ;
91+
92+ const getConstPlaceholder = ( ) => {
93+ switch ( effectiveType ) {
94+ case 'number' :
95+ case 'integer' :
96+ return 'e.g., 42' ;
97+ case 'boolean' :
98+ return 'e.g., true' ;
99+ default :
100+ return 'e.g., active' ;
101+ }
102+ } ;
103+
104+ // Build description with JSON Schema context
105+ const enumDescription = isSimpleArray
106+ ? 'Allowed values for each item in the array (JSON Schema enum). Comma-separated list.'
107+ : 'Allowed values for this field (JSON Schema enum). Comma-separated list.' ;
108+
109+ const constDescription = isSimpleArray
110+ ? 'Each item in the array must be exactly this value (JSON Schema const).'
111+ : 'Field must be exactly this value (JSON Schema const).' ;
112+
52113 return (
53114 < >
54- < Header variant = "h4" > Value Constraints</ Header >
115+ < Header variant = "h4" > Value Constraints (JSON Schema) </ Header >
55116
56- < FormField label = "Const (Single Constant Value)" description = "Field must be exactly this value" >
117+ < FormField label = "Const (Single Constant Value)" description = { constDescription } constraintText = { `Example: ${ getConstPlaceholder ( ) } ` } >
57118 < Input
58119 value = { constInput }
59120 onChange = { ( { detail } ) => setConstInput ( detail . value ) }
60121 onBlur = { handleConstBlur }
61- placeholder = 'e.g., "active", 42, or JSON value'
62- disabled = { attribute . enum && attribute . enum . length > 0 }
122+ placeholder = { getConstPlaceholder ( ) }
123+ disabled = { currentEnum && currentEnum . length > 0 }
63124 />
64125 </ FormField >
65126
66127 < FormField
67- label = "Enum Values (Multiple Allowed Values)"
68- description = "Comma-separated list of allowed values (mutually exclusive with const)"
128+ label = "Enum (Allowed Values)"
129+ description = { enumDescription }
130+ constraintText = { `Example: ${ getEnumPlaceholder ( ) } - Values are comma-separated` }
69131 >
70- { attribute . enum && attribute . enum . length > 0 ? (
132+ { currentEnum && currentEnum . length > 0 ? (
71133 < SpaceBetween size = "xs" >
72134 < TokenGroup
73- items = { attribute . enum . map ( ( val ) => ( {
135+ items = { currentEnum . map ( ( val ) => ( {
74136 label : typeof val === 'object' ? JSON . stringify ( val ) : String ( val ) ,
75137 dismissLabel : `Remove ${ val } ` ,
76138 } ) ) }
77139 onDismiss = { ( { detail : { itemIndex } } ) => {
78- const newEnum = [ ...( attribute . enum || [ ] ) ] ;
140+ const newEnum = [ ...( currentEnum || [ ] ) ] ;
79141 newEnum . splice ( itemIndex , 1 ) ;
80- onUpdate ( { enum : newEnum . length > 0 ? newEnum : undefined } ) ;
142+ updateValueConstraint ( { enum : newEnum . length > 0 ? newEnum : undefined } ) ;
81143 } }
82144 />
83145 < Button
84146 variant = "link"
85147 onClick = { ( ) => {
86- onUpdate ( { enum : undefined } ) ;
148+ updateValueConstraint ( { enum : undefined } ) ;
87149 } }
88150 >
89151 Clear all enum values
90152 </ Button >
91153 </ SpaceBetween >
92154 ) : (
93155 < Input
94- placeholder = "value1, value2, value3"
156+ placeholder = { getEnumPlaceholder ( ) }
95157 value = { enumInput }
96158 onChange = { ( { detail } ) => setEnumInput ( detail . value ) }
97159 onBlur = { handleEnumBlur }
98- disabled = { attribute . const !== undefined }
160+ disabled = { currentConst !== undefined }
99161 />
100162 ) }
101163 </ FormField >
@@ -108,6 +170,12 @@ ValueConstraints.propTypes = {
108170 type : PropTypes . string ,
109171 const : PropTypes . oneOfType ( [ PropTypes . string , PropTypes . number , PropTypes . bool , PropTypes . object , PropTypes . array ] ) ,
110172 enum : PropTypes . arrayOf ( PropTypes . oneOfType ( [ PropTypes . string , PropTypes . number , PropTypes . bool , PropTypes . object , PropTypes . array ] ) ) ,
173+ items : PropTypes . shape ( {
174+ type : PropTypes . string ,
175+ $ref : PropTypes . string ,
176+ const : PropTypes . oneOfType ( [ PropTypes . string , PropTypes . number , PropTypes . bool , PropTypes . object , PropTypes . array ] ) ,
177+ enum : PropTypes . arrayOf ( PropTypes . oneOfType ( [ PropTypes . string , PropTypes . number , PropTypes . bool , PropTypes . object , PropTypes . array ] ) ) ,
178+ } ) ,
111179 } ) . isRequired ,
112180 onUpdate : PropTypes . func . isRequired ,
113181} ;
0 commit comments