11package com.goalpanzi.mission_mate.core.ui.component
22
3+ import android.view.KeyEvent
34import androidx.compose.foundation.BorderStroke
45import androidx.compose.foundation.background
56import androidx.compose.foundation.border
@@ -23,7 +24,10 @@ import androidx.compose.ui.draw.clip
2324import androidx.compose.ui.focus.onFocusChanged
2425import androidx.compose.ui.graphics.Color
2526import androidx.compose.ui.graphics.Shape
27+ import androidx.compose.ui.input.key.onKeyEvent
28+ import androidx.compose.ui.text.TextRange
2629import androidx.compose.ui.text.TextStyle
30+ import androidx.compose.ui.text.input.TextFieldValue
2731import androidx.compose.ui.text.input.VisualTransformation
2832import androidx.compose.ui.text.style.TextAlign
2933import androidx.compose.ui.unit.dp
@@ -59,15 +63,33 @@ fun InvitationCodeTextField(
5963 contentPadding : PaddingValues = PaddingValues (),
6064 keyboardOptions : KeyboardOptions = KeyboardOptions .Default ,
6165 keyboardActions : KeyboardActions = KeyboardActions .Default ,
62- readOnly : Boolean = false
66+ readOnly : Boolean = false,
67+ onDeleteWhenBlank : () -> Unit = {},
6368) {
69+ val textFieldValue by remember(text) {
70+ mutableStateOf(
71+ TextFieldValue (
72+ text = text,
73+ selection = TextRange (
74+ index = if (text.isNotBlank()) 1 else 0
75+ )
76+ )
77+ )
78+ }
6479 var isFocused by remember { mutableStateOf(false ) }
6580 BasicTextField (
6681 modifier = modifier
6782 .onFocusChanged {
6883 isFocused = it.isFocused
84+ }
85+ .onKeyEvent { event ->
86+ val isDeleteButton = event.nativeKeyEvent.keyCode == KeyEvent .KEYCODE_DEL
87+ if (isDeleteButton && textFieldValue.text.isBlank()) {
88+ onDeleteWhenBlank()
89+ }
90+ false
6991 },
70- value = text ,
92+ value = textFieldValue ,
7193 singleLine = isSingleLine,
7294 textStyle = textStyle.copy(
7395 color = textColor,
@@ -77,38 +99,122 @@ fun InvitationCodeTextField(
7799 visualTransformation = visualTransformation,
78100 keyboardOptions = keyboardOptions,
79101 keyboardActions = keyboardActions,
80- onValueChange = onValueChange,
102+ onValueChange = {
103+ if (it.text.isBlank() || it.selection != TextRange .Zero ) onValueChange(it.text)
104+ },
81105 readOnly = readOnly,
82106 decorationBox = { innerTextField ->
83- Box (
84- modifier = Modifier
85- .clip(shape)
86- .border(
87- border = if (isError) errorBorderStroke
88- else if (isFocused || text.isNotEmpty()) focusedBorderStroke
89- else borderStroke,
90- shape = shape
91- )
92- .background(
93- if (text.isNotEmpty()) containerColor
94- else if (! isFocused ) unfocusedHintColor
95- else containerColor
96- )
97- .padding(contentPadding),
98- contentAlignment = textAlign
99- ) {
100- if (text.isBlank() && ! isFocused) {
101- Text (
102- modifier = Modifier .fillMaxWidth(),
103- text = hint ? : " 0" ,
104- style = hintStyle,
105- color = hintColor,
106- textAlign = TextAlign .Center
107- )
108- }
109- innerTextField()
110- }
107+ InvitationCodeBox (
108+ text = text,
109+ isFocused = isFocused,
110+ hint = hint,
111+ isError = isError,
112+ hintStyle = hintStyle,
113+ hintColor = hintColor,
114+ containerColor = containerColor,
115+ unfocusedHintColor = unfocusedHintColor,
116+ borderStroke = borderStroke,
117+ focusedBorderStroke = focusedBorderStroke,
118+ errorBorderStroke = errorBorderStroke,
119+ shape = shape,
120+ textAlign = textAlign,
121+ contentPadding = contentPadding,
122+ innerTextField = innerTextField,
123+ )
124+ }
125+ )
126+ }
111127
128+ @Composable
129+ fun InvitationCodeText (
130+ text : String ,
131+ modifier : Modifier = Modifier ,
132+ hint : String? = null,
133+ isError : Boolean = false,
134+ textStyle : TextStyle = MissionMateTypography .heading_md_bold,
135+ hintStyle : TextStyle = MissionMateTypography .heading_md_bold,
136+ textColor : Color = ColorGray1_FF404249 ,
137+ hintColor : Color = ColorDisabled_FFB3B3B3 ,
138+ containerColor : Color = ColorWhite_FFFFFFFF ,
139+ unfocusedHintColor : Color = ColorGray5_FFF5F6F9 ,
140+ borderStroke : BorderStroke = BorderStroke (1.dp, ColorGray5_FFF5F6F9 ),
141+ focusedBorderStroke : BorderStroke = BorderStroke (1.dp, ColorGray4_FFE5E5E5 ),
142+ errorBorderStroke : BorderStroke = BorderStroke (2.dp, ColorRed_FFFF5858 ),
143+ shape : Shape = RoundedCornerShape (12.dp),
144+ textAlign : Alignment = Alignment .Center ,
145+ contentPadding : PaddingValues = PaddingValues ()
146+ ) {
147+ InvitationCodeBox (
148+ modifier = modifier,
149+ text = text,
150+ isFocused = false ,
151+ hint = hint,
152+ isError = isError,
153+ hintStyle = hintStyle,
154+ hintColor = hintColor,
155+ containerColor = containerColor,
156+ unfocusedHintColor = unfocusedHintColor,
157+ borderStroke = borderStroke,
158+ focusedBorderStroke = focusedBorderStroke,
159+ errorBorderStroke = errorBorderStroke,
160+ shape = shape,
161+ textAlign = textAlign,
162+ contentPadding = contentPadding,
163+ innerTextField = {
164+ Text (
165+ text = text,
166+ style = textStyle,
167+ color = textColor
168+ )
112169 }
113170 )
114171}
172+
173+ @Composable
174+ fun InvitationCodeBox (
175+ text : CharSequence ,
176+ isFocused : Boolean ,
177+ modifier : Modifier = Modifier ,
178+ hint : String? = null,
179+ isError : Boolean = false,
180+ hintStyle : TextStyle = MissionMateTypography .heading_md_bold,
181+ hintColor : Color = ColorDisabled_FFB3B3B3 ,
182+ containerColor : Color = ColorWhite_FFFFFFFF ,
183+ unfocusedHintColor : Color = ColorGray5_FFF5F6F9 ,
184+ borderStroke : BorderStroke = BorderStroke (1.dp, ColorGray5_FFF5F6F9 ),
185+ focusedBorderStroke : BorderStroke = BorderStroke (1.dp, ColorGray4_FFE5E5E5 ),
186+ errorBorderStroke : BorderStroke = BorderStroke (2.dp, ColorRed_FFFF5858 ),
187+ shape : Shape = RoundedCornerShape (12.dp),
188+ textAlign : Alignment = Alignment .Center ,
189+ contentPadding : PaddingValues = PaddingValues (),
190+ innerTextField : @Composable () -> Unit = {}
191+ ) {
192+ Box (
193+ modifier = modifier
194+ .clip(shape)
195+ .border(
196+ border = if (isError) errorBorderStroke
197+ else if (isFocused || text.isNotEmpty()) focusedBorderStroke
198+ else borderStroke,
199+ shape = shape
200+ )
201+ .background(
202+ if (text.isNotEmpty()) containerColor
203+ else if (! isFocused) unfocusedHintColor
204+ else containerColor
205+ )
206+ .padding(contentPadding),
207+ contentAlignment = textAlign
208+ ) {
209+ if (text.isBlank() && ! isFocused) {
210+ Text (
211+ modifier = Modifier .fillMaxWidth(),
212+ text = hint ? : " 0" ,
213+ style = hintStyle,
214+ color = hintColor,
215+ textAlign = TextAlign .Center
216+ )
217+ }
218+ innerTextField()
219+ }
220+ }
0 commit comments