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