1616
1717package  com.google.android.fhir.datacapture.views.compose 
1818
19+ import  androidx.compose.foundation.layout.fillMaxWidth 
1920import  androidx.compose.material3.DropdownMenuItem 
2021import  androidx.compose.material3.ExperimentalMaterial3Api 
22+ import  androidx.compose.material3.ExposedDropdownMenuAnchorType 
2123import  androidx.compose.material3.ExposedDropdownMenuBox 
2224import  androidx.compose.material3.ExposedDropdownMenuDefaults 
2325import  androidx.compose.material3.Icon 
2426import  androidx.compose.material3.MaterialTheme 
25- import  androidx.compose.material3.MenuAnchorType 
2627import  androidx.compose.material3.OutlinedTextField 
2728import  androidx.compose.material3.Text 
2829import  androidx.compose.runtime.Composable 
@@ -35,14 +36,20 @@ import androidx.compose.runtime.setValue
3536import  androidx.compose.ui.Modifier 
3637import  androidx.compose.ui.graphics.asImageBitmap 
3738import  androidx.compose.ui.platform.testTag 
39+ import  androidx.compose.ui.semantics.error 
40+ import  androidx.compose.ui.semantics.semantics 
41+ import  androidx.compose.ui.text.AnnotatedString 
3842import  androidx.core.graphics.drawable.toBitmap 
3943import  com.google.android.fhir.datacapture.views.factories.DropDownAnswerOption 
4044
4145@OptIn(ExperimentalMaterial3Api ::class )
4246@Composable
43- internal  fun  ExposedDropDownMenuBoxItem (
47+ internal  fun  DropDownItem (
4448  modifier :  Modifier ,
4549  enabled :  Boolean ,
50+   labelText :  AnnotatedString ?  = null,
51+   supportingText :  String?  = null,
52+   isError :  Boolean  = false,
4653  selectedOption :  DropDownAnswerOption ?  = null,
4754  options :  List <DropDownAnswerOption >,
4855  onDropDownAnswerOptionSelected :  (DropDownAnswerOption ? ) ->  Unit ,
@@ -68,39 +75,66 @@ internal fun ExposedDropDownMenuBoxItem(
6875      value =  selectedOptionDisplay,
6976      onValueChange =  {},
7077      modifier = 
71-         Modifier .testTag(DROP_DOWN_TEXT_FIELD_TAG )
72-           .menuAnchor(MenuAnchorType .PrimaryNotEditable , enabled),
78+         Modifier .fillMaxWidth()
79+           .testTag(DROP_DOWN_TEXT_FIELD_TAG )
80+           .semantics { if  (isError) error(supportingText ? :  " "  ) }
81+           .menuAnchor(ExposedDropdownMenuAnchorType .PrimaryNotEditable , enabled),
7382      readOnly =  true ,
7483      enabled =  enabled,
7584      minLines =  1 ,
76-       label =  {},
77-       supportingText =  {},
85+       isError =  isError,
86+       label =  { labelText?.let  { Text (it) } },
87+       supportingText =  { supportingText?.let  { Text (it) } },
88+       leadingIcon = 
89+         selectedDropDownAnswerOption?.answerOptionImage?.let  {
90+           {
91+             Icon (
92+               it.toBitmap().asImageBitmap(),
93+               contentDescription =  selectedOptionDisplay,
94+               modifier =  Modifier .testTag(DROP_DOWN_TEXT_FIELD_LEADING_ICON_TAG ),
95+             )
96+           }
97+         },
7898      trailingIcon =  { ExposedDropdownMenuDefaults .TrailingIcon (expanded =  expanded) },
7999    )
80100    ExposedDropdownMenu (expanded =  expanded, onDismissRequest =  { expanded =  false  }) {
81101      options.forEach { option -> 
82-         DropdownMenuItem (
83-           text =  {
84-             Text (option.answerOptionAnnotatedString(), style =  MaterialTheme .typography.bodyLarge)
85-           },
86-           leadingIcon =  {
87-             option.answerOptionImage?.let  {
88-               Icon (
89-                 it.toBitmap().asImageBitmap(),
90-                 contentDescription =  option.answerOptionString,
91-               )
92-             }
93-           },
94-           enabled =  enabled,
95-           onClick =  {
96-             selectedDropDownAnswerOption =  option
97-             expanded =  false 
98-           },
99-           contentPadding =  ExposedDropdownMenuDefaults .ItemContentPadding ,
100-         )
102+         DropDownAnswerMenuItem (enabled, option) {
103+           selectedDropDownAnswerOption =  option
104+           expanded =  false 
105+         }
101106      }
102107    }
103108  }
104109}
105110
111+ @OptIn(ExperimentalMaterial3Api ::class )
112+ @Composable
113+ internal  fun  DropDownAnswerMenuItem (
114+   enabled :  Boolean ,
115+   answerOption :  DropDownAnswerOption ,
116+   onSelected :  () ->  Unit ,
117+ ) {
118+   DropdownMenuItem (
119+     modifier =  Modifier .testTag(DROP_DOWN_ANSWER_MENU_ITEM_TAG ),
120+     text =  {
121+       Text (answerOption.answerOptionAnnotatedString(), style =  MaterialTheme .typography.bodyLarge)
122+     },
123+     leadingIcon = 
124+       answerOption.answerOptionImage?.let  {
125+         {
126+           Icon (
127+             it.toBitmap().asImageBitmap(),
128+             contentDescription =  answerOption.answerOptionString,
129+           )
130+         }
131+       },
132+     enabled =  enabled,
133+     onClick =  { onSelected() },
134+     contentPadding =  ExposedDropdownMenuDefaults .ItemContentPadding ,
135+   )
136+ }
137+ 
106138const  val  DROP_DOWN_TEXT_FIELD_TAG  =  " drop_down_text_field" 
139+ const  val  DROP_DOWN_TEXT_FIELD_LEADING_ICON_TAG  =  " drop_down_text_field_leading_icon" 
140+ const  val  DROP_DOWN_ANSWER_MENU_ITEM_TAG  =  " drop_down_answer_list_menu_item" 
0 commit comments