-
Notifications
You must be signed in to change notification settings - Fork 1.9k
feat: AuthTextField #2231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
demolaf
wants to merge
11
commits into
firebase:version-10.0.0-dev
Choose a base branch
from
demolaf:feat/T3
base: version-10.0.0-dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
feat: AuthTextField #2231
Changes from 9 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
9af10d2
feat: AuthMethodPicker, logo and provider theme style
demolaf b6f7bdc
chore: organize folder structure
demolaf 96ffa30
feat: TOS and PP footer, ui tests for AuthMethodPicker
demolaf bfd056c
chore: tests folder structure
demolaf 4c3a59b
chore: use version catalog for compose deps
demolaf a840716
feat: AuthTextField with validation
demolaf 58145d6
test: AuthTextField and field validations
demolaf 24c687c
chore: update doc comments
demolaf 9fc948d
Merge branch 'version-10.0.0-dev' of https://github.com/firebase/Fire…
demolaf eb38a85
refactor: remove libs.versions.toml catalog file
demolaf 45b6a40
Merge branch 'version-10.0.0-dev' of https://github.com/firebase/Fire…
demolaf File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
201 changes: 201 additions & 0 deletions
201
auth/src/main/java/com/firebase/ui/auth/compose/ui/components/AuthTextField.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
package com.firebase.ui.auth.compose.ui.components | ||
|
||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.Spacer | ||
import androidx.compose.foundation.layout.fillMaxSize | ||
import androidx.compose.foundation.layout.height | ||
import androidx.compose.foundation.text.KeyboardActions | ||
import androidx.compose.foundation.text.KeyboardOptions | ||
import androidx.compose.material.icons.Icons | ||
import androidx.compose.material.icons.filled.Email | ||
import androidx.compose.material.icons.filled.Lock | ||
import androidx.compose.material.icons.filled.Visibility | ||
import androidx.compose.material.icons.filled.VisibilityOff | ||
import androidx.compose.material3.Icon | ||
import androidx.compose.material3.IconButton | ||
import androidx.compose.material3.Text | ||
import androidx.compose.material3.TextField | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.runtime.mutableStateOf | ||
import androidx.compose.runtime.remember | ||
import androidx.compose.runtime.setValue | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.platform.LocalContext | ||
import androidx.compose.ui.text.input.PasswordVisualTransformation | ||
import androidx.compose.ui.text.input.VisualTransformation | ||
import androidx.compose.ui.tooling.preview.Preview | ||
import androidx.compose.ui.unit.dp | ||
import com.firebase.ui.auth.compose.configuration.PasswordRule | ||
import com.firebase.ui.auth.compose.configuration.string_provider.DefaultAuthUIStringProvider | ||
import com.firebase.ui.auth.compose.configuration.validators.EmailValidator | ||
import com.firebase.ui.auth.compose.configuration.validators.FieldValidator | ||
import com.firebase.ui.auth.compose.configuration.validators.PasswordValidator | ||
|
||
/** | ||
* A customizable input field with built-in validation display. | ||
* | ||
* **Example usage:** | ||
* ```kotlin | ||
* val emailTextValue = remember { mutableStateOf("") } | ||
* | ||
* val emailValidator = remember { | ||
* EmailValidator(stringProvider = DefaultAuthUIStringProvider(context)) | ||
* } | ||
* | ||
* AuthTextField( | ||
* value = emailTextValue, | ||
* onValueChange = { emailTextValue.value = it }, | ||
* label = { | ||
* Text("Email") | ||
* }, | ||
* validator = emailValidator | ||
* ) | ||
* ``` | ||
* | ||
* @param modifier A modifier for the field. | ||
* @param value The current value of the text field. | ||
* @param onValueChange A callback when the value changes. | ||
* @param label The label for the text field. | ||
* @param enabled If the field is enabled. | ||
* @param isError Manually set the error state. | ||
* @param errorMessage A custom error message to display. | ||
* @param validator A validator to automatically handle error state and messages. | ||
* @param keyboardOptions Keyboard options for the field. | ||
* @param keyboardActions Keyboard actions for the field. | ||
* @param visualTransformation Visual transformation for the input (e.g., password). | ||
* @param leadingIcon An optional icon to display at the start of the field. | ||
* @param trailingIcon An optional icon to display at the start of the field. | ||
*/ | ||
@Composable | ||
fun AuthTextField( | ||
modifier: Modifier = Modifier, | ||
value: String, | ||
onValueChange: (String) -> Unit, | ||
label: @Composable (() -> Unit)? = null, | ||
enabled: Boolean = true, | ||
isError: Boolean? = null, | ||
errorMessage: String? = null, | ||
validator: FieldValidator? = null, | ||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default, | ||
keyboardActions: KeyboardActions = KeyboardActions.Default, | ||
visualTransformation: VisualTransformation = VisualTransformation.None, | ||
leadingIcon: @Composable (() -> Unit)? = null, | ||
trailingIcon: @Composable (() -> Unit)? = null, | ||
) { | ||
val isSecureTextField = validator is PasswordValidator | ||
var passwordVisible by remember { mutableStateOf(false) } | ||
|
||
TextField( | ||
modifier = modifier, | ||
value = value, | ||
onValueChange = { newValue -> | ||
onValueChange(newValue) | ||
validator?.validate(newValue) | ||
}, | ||
label = label, | ||
singleLine = true, | ||
enabled = enabled, | ||
isError = isError ?: validator?.hasError ?: false, | ||
supportingText = { | ||
if (validator?.hasError ?: false) { | ||
Text(text = errorMessage ?: validator.errorMessage) | ||
} | ||
}, | ||
keyboardOptions = keyboardOptions, | ||
keyboardActions = keyboardActions, | ||
visualTransformation = if (isSecureTextField && !passwordVisible) | ||
PasswordVisualTransformation() else visualTransformation, | ||
leadingIcon = leadingIcon, | ||
trailingIcon = trailingIcon ?: { | ||
if (isSecureTextField) { | ||
IconButton( | ||
onClick = { | ||
passwordVisible = !passwordVisible | ||
} | ||
) { | ||
Icon( | ||
imageVector = if (passwordVisible) | ||
Icons.Filled.VisibilityOff else Icons.Filled.Visibility, | ||
contentDescription = if (passwordVisible) "Hide password" else "Show password" | ||
) | ||
} | ||
} | ||
}, | ||
) | ||
} | ||
|
||
@Preview(showBackground = true) | ||
@Composable | ||
internal fun PreviewAuthTextField() { | ||
val context = LocalContext.current | ||
val nameTextValue = remember { mutableStateOf("") } | ||
val emailTextValue = remember { mutableStateOf("") } | ||
val passwordTextValue = remember { mutableStateOf("") } | ||
val emailValidator = remember { | ||
EmailValidator(stringProvider = DefaultAuthUIStringProvider(context)) | ||
} | ||
val passwordValidator = remember { | ||
PasswordValidator( | ||
stringProvider = DefaultAuthUIStringProvider(context), | ||
rules = listOf( | ||
PasswordRule.MinimumLength(8), | ||
PasswordRule.RequireUppercase, | ||
PasswordRule.RequireLowercase, | ||
) | ||
) | ||
} | ||
|
||
Column( | ||
modifier = Modifier | ||
.fillMaxSize(), | ||
verticalArrangement = Arrangement.Center, | ||
horizontalAlignment = Alignment.CenterHorizontally, | ||
) { | ||
AuthTextField( | ||
value = nameTextValue.value, | ||
label = { | ||
Text("Name") | ||
}, | ||
onValueChange = { text -> | ||
nameTextValue.value = text | ||
}, | ||
) | ||
Spacer(modifier = Modifier.height(16.dp)) | ||
AuthTextField( | ||
value = emailTextValue.value, | ||
validator = emailValidator, | ||
label = { | ||
Text("Email") | ||
}, | ||
onValueChange = { text -> | ||
emailTextValue.value = text | ||
}, | ||
leadingIcon = { | ||
Icon( | ||
imageVector = Icons.Default.Email, | ||
contentDescription = "" | ||
) | ||
} | ||
) | ||
Spacer(modifier = Modifier.height(16.dp)) | ||
AuthTextField( | ||
value = passwordTextValue.value, | ||
validator = passwordValidator, | ||
label = { | ||
Text("Password") | ||
}, | ||
onValueChange = { text -> | ||
passwordTextValue.value = text | ||
}, | ||
leadingIcon = { | ||
Icon( | ||
imageVector = Icons.Default.Lock, | ||
contentDescription = "" | ||
) | ||
} | ||
) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.