From 40c3bc63f52910067c8c5cb609efe93ccf7d1d57 Mon Sep 17 00:00:00 2001 From: Floris Halleriet Date: Fri, 10 Nov 2023 11:19:24 +0100 Subject: [PATCH] feat: add more validation styling and textfield size customization --- CHANGELOG.md | 39 +++++--- example/pubspec.lock | 2 +- lib/src/config/login_options.dart | 21 +++- lib/src/widgets/email_password_login.dart | 116 ++++++++++++++++------ lib/src/widgets/forgot_password_form.dart | 45 +++++++-- pubspec.yaml | 2 +- 6 files changed, 167 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff35d90..a74dac1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,38 +1,49 @@ +## 5.0.1 + +- Added more options for styling the error/validation messages and allow height/width of TextFormField's to be changed. + ## 5.0.0 -* Removed the redundant initialEmail parameter from 'ForgotPasswordForm'. The only one to use now is the one in the 'LoginOptions'. + +- Removed the redundant initialEmail parameter from 'ForgotPasswordForm'. The only one to use now is the one in the 'LoginOptions'. ## 4.2.0 -* Option for spacers add the start and end of the form + +- Option for spacers add the start and end of the form ## 4.1.1 -* Export default LoginValidationService + +- Export default LoginValidationService ## 4.1.0 -* Option to add spacers between all items + +- Option to add spacers between all items ## 4.0.0 -* More decoration options less default padding + +- More decoration options less default padding ## 3.1.2 -* Added textStyle option for email and password fields + +- Added textStyle option for email and password fields ## 3.1.1 -* Fix login values not copied to validation + +- Fix login values not copied to validation ## 3.0.0 -* Added login options to loginbuilders for more customization + +- Added login options to loginbuilders for more customization ## 2.0.1 -* Fixed email regex +- Fixed email regex ## 2.0.0 -* add forgot password validation on button press -* add onDisabledPress param for methods -* correctly use initialEmail in forgot password screen - +- add forgot password validation on button press +- add onDisabledPress param for methods +- correctly use initialEmail in forgot password screen ## 0.0.1 -* TODO: Describe initial release. +- TODO: Describe initial release. diff --git a/example/pubspec.lock b/example/pubspec.lock index abf4bb3..2c4d923 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -68,7 +68,7 @@ packages: path: ".." relative: true source: path - version: "4.2.0" + version: "5.0.1" flutter_test: dependency: "direct dev" description: flutter diff --git a/lib/src/config/login_options.dart b/lib/src/config/login_options.dart index 6f3af51..8e34938 100644 --- a/lib/src/config/login_options.dart +++ b/lib/src/config/login_options.dart @@ -11,7 +11,13 @@ class LoginOptions { this.image, this.title, this.subtitle, + this.textFieldHeight, + this.textFieldWidth, this.maxFormWidth, + this.errorStyle = const TextStyle( + fontSize: 12.5, + color: Colors.red, + ), this.emailTextStyle, this.passwordTextStyle, this.emailDecoration = const InputDecoration(), @@ -26,6 +32,7 @@ class LoginOptions { this.requestForgotPasswordButtonBuilder = _createRequestForgotPasswordButton, this.registrationButtonBuilder = _createRegisterButton, + this.errorMessageBuilder = _errorMessageBuilder, this.emailInputContainerBuilder = _createEmailInputContainer, this.passwordInputContainerBuilder = _createPasswordInputContainer, }); @@ -34,6 +41,7 @@ class LoginOptions { final ButtonBuilder registrationButtonBuilder; final ButtonBuilder forgotPasswordButtonBuilder; final ButtonBuilder requestForgotPasswordButtonBuilder; + final InputContainerBuilder errorMessageBuilder; final InputContainerBuilder emailInputContainerBuilder; final InputContainerBuilder passwordInputContainerBuilder; @@ -47,10 +55,14 @@ class LoginOptions { /// Maximum width of the form. Defaults to 400. final double? maxFormWidth; + final double? textFieldHeight; + final double? textFieldWidth; + final InputDecoration emailDecoration; final InputDecoration passwordDecoration; final String initialEmail; final String initialPassword; + final TextStyle? errorStyle; final TextStyle? emailTextStyle; final TextStyle? passwordTextStyle; final LoginTranslations translations; @@ -81,12 +93,17 @@ class LoginTranslations { } Widget _createEmailInputContainer(Widget child) => Padding( - padding: const EdgeInsets.only(bottom: 15), + padding: const EdgeInsets.only(bottom: 8), + child: child, + ); + +Widget _errorMessageBuilder(Widget child) => Padding( + padding: const EdgeInsets.only(left: 16, top: 4), child: child, ); Widget _createPasswordInputContainer(Widget child) => Padding( - padding: const EdgeInsets.only(bottom: 15), + padding: const EdgeInsets.only(bottom: 8), child: child, ); diff --git a/lib/src/widgets/email_password_login.dart b/lib/src/widgets/email_password_login.dart index 1e57110..0704c9b 100644 --- a/lib/src/widgets/email_password_login.dart +++ b/lib/src/widgets/email_password_login.dart @@ -26,6 +26,9 @@ class _EmailPasswordLoginFormState extends State { final ValueNotifier _formValid = ValueNotifier(false); bool _obscurePassword = true; + String? emailValidationText; + String? passwordValidationText; + String _currentEmail = ''; String _currentPassword = ''; @@ -138,42 +141,93 @@ class _EmailPasswordLoginFormState extends State { mainAxisSize: MainAxisSize.min, children: [ options.emailInputContainerBuilder( - TextFormField( - onChanged: _updateCurrentEmail, - validator: - widget.options.validations.validateEmail, - initialValue: options.initialEmail, - keyboardType: TextInputType.emailAddress, - textInputAction: TextInputAction.next, - style: options.emailTextStyle, - decoration: options.emailDecoration, + Column( + children: [ + SizedBox( + height: options.textFieldHeight, + width: options.textFieldWidth, + child: TextFormField( + onChanged: _updateCurrentEmail, + validator: (value) { + var validationResult = widget + .options.validations + .validateEmail(value); + setState(() { + emailValidationText = validationResult; + }); + return; + }, + initialValue: options.initialEmail, + keyboardType: TextInputType.emailAddress, + textInputAction: TextInputAction.next, + style: options.emailTextStyle, + decoration: options.emailDecoration, + ), + ), + if (emailValidationText != null) + options.errorMessageBuilder( + Align( + alignment: Alignment.centerLeft, + child: Text( + emailValidationText!, + style: options.errorStyle, + ), + ), + ), + ], ), ), options.passwordInputContainerBuilder( - TextFormField( - obscureText: _obscurePassword, - onChanged: _updateCurrentPassword, - validator: - widget.options.validations.validatePassword, - initialValue: options.initialPassword, - keyboardType: TextInputType.visiblePassword, - textInputAction: TextInputAction.done, - style: options.passwordTextStyle, - onFieldSubmitted: (_) => _handleLogin(), - decoration: options.passwordDecoration.copyWith( - suffixIcon: IconButton( - onPressed: () { - setState(() { - _obscurePassword = !_obscurePassword; - }); - }, - icon: Icon( - _obscurePassword - ? Icons.visibility - : Icons.visibility_off, + Column( + children: [ + SizedBox( + height: options.textFieldHeight, + width: options.textFieldWidth, + child: TextFormField( + obscureText: _obscurePassword, + onChanged: _updateCurrentPassword, + validator: (value) { + var validationResult = widget + .options.validations + .validatePassword(value); + setState(() { + passwordValidationText = + validationResult; + }); + return; + }, + initialValue: options.initialPassword, + keyboardType: TextInputType.visiblePassword, + textInputAction: TextInputAction.done, + style: options.passwordTextStyle, + onFieldSubmitted: (_) => _handleLogin(), + decoration: + options.passwordDecoration.copyWith( + suffixIcon: IconButton( + onPressed: () { + setState(() { + _obscurePassword = + !_obscurePassword; + }); + }, + icon: Icon( + _obscurePassword + ? Icons.visibility + : Icons.visibility_off, + ), + ), + ), ), ), - ), + if (passwordValidationText != null) + options.errorMessageBuilder( + Align( + alignment: Alignment.centerLeft, + child: Text(passwordValidationText!, + style: options.errorStyle), + ), + ), + ], ), ), if (widget.onForgotPassword != null) ...[ diff --git a/lib/src/widgets/forgot_password_form.dart b/lib/src/widgets/forgot_password_form.dart index 318fedb..b2bf177 100644 --- a/lib/src/widgets/forgot_password_form.dart +++ b/lib/src/widgets/forgot_password_form.dart @@ -27,6 +27,8 @@ class _ForgotPasswordFormState extends State { final GlobalKey _formKey = GlobalKey(); final FocusNode _focusNode = FocusNode(); + String? emailValidationText; + @override void initState() { super.initState(); @@ -84,15 +86,40 @@ class _ForgotPasswordFormState extends State { Expanded( child: Align( child: options.emailInputContainerBuilder( - TextFormField( - focusNode: _focusNode, - onChanged: _updateCurrentEmail, - validator: widget.options.validations.validateEmail, - initialValue: options.initialEmail, - keyboardType: TextInputType.emailAddress, - textInputAction: TextInputAction.next, - style: options.emailTextStyle, - decoration: options.emailDecoration, + Column( + children: [ + SizedBox( + height: options.textFieldHeight, + width: options.textFieldWidth, + child: TextFormField( + focusNode: _focusNode, + onChanged: _updateCurrentEmail, + validator: (value) { + var validationResult = + widget.options.validations.validateEmail(value); + setState(() { + emailValidationText = validationResult; + }); + return; + }, + initialValue: options.initialEmail, + keyboardType: TextInputType.emailAddress, + textInputAction: TextInputAction.next, + style: options.emailTextStyle, + decoration: options.emailDecoration, + ), + ), + if (emailValidationText != null) + options.errorMessageBuilder( + Align( + alignment: Alignment.centerLeft, + child: Text( + emailValidationText!, + style: options.errorStyle, + ), + ), + ), + ], ), ), ), diff --git a/pubspec.yaml b/pubspec.yaml index cff9d12..0d5e19c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_login description: Flutter Login Component -version: 5.0.0 +version: 5.0.1 environment: sdk: ">=2.18.1 <3.0.0"