diff --git a/CHANGELOG.md b/CHANGELOG.md index 535383d..7c71b78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 7.2.0 + +* Added CustomSemantics widget that is used to wrap all the inputfields and buttons to make the component accessible for e2e testing. +* Upgraded pinput to 5.0.1 from 2.3.0 +* Updated flutter_iconica_analysis to 7.0.0 with new rules + ## 7.1.3 * Fixed forgotpassword description line height. diff --git a/example/pubspec.lock b/example/pubspec.lock index 4ab19dd..d1ab254 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" fake_async: dependency: transitive description: @@ -68,33 +68,28 @@ packages: path: ".." relative: true source: path - version: "7.1.0" + version: "7.2.0" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" leak_tracker: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.7" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.8" leak_tracker_testing: dependency: transitive description: @@ -123,18 +118,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.15.0" path: dependency: transitive description: @@ -147,23 +142,15 @@ packages: dependency: transitive description: name: pinput - sha256: "543da5bfdefd9e06914a12100f8c9156f84cef3efc14bca507c49e966c5b813b" + sha256: "8a73be426a91fefec90a7f130763ca39772d547e92f19a827cf4aa02e323d35a" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "5.0.1" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" - smart_auth: - dependency: transitive - description: - name: smart_auth - sha256: a25229b38c02f733d0a4e98d941b42bed91a976cb589e934895e60ccfa674cf6 - url: "https://pub.dev" - source: hosted - version: "1.1.1" source_span: dependency: transitive description: @@ -176,10 +163,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.12.0" stream_channel: dependency: transitive description: @@ -192,10 +179,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" term_glyph: dependency: transitive description: @@ -208,10 +195,10 @@ packages: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.3" universal_platform: dependency: transitive description: @@ -232,10 +219,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "14.3.0" sdks: - dart: ">=3.3.0 <4.0.0" + dart: ">=3.4.0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/lib/flutter_login.dart b/lib/flutter_login.dart index 8b0b619..ae0c96a 100644 --- a/lib/flutter_login.dart +++ b/lib/flutter_login.dart @@ -1,11 +1,11 @@ /// library flutter_login; -export 'src/config/forgot_password_spacer_options.dart'; -export 'src/config/login_options.dart'; -export 'src/config/spacer_options.dart'; -export 'src/service/login_validation.dart'; -export 'src/service/validation.dart'; -export 'src/widgets/email_password_login.dart'; -export 'src/widgets/forgot_password_form.dart'; -export 'src/widgets/mfa_widget.dart'; +export "src/config/forgot_password_spacer_options.dart"; +export "src/config/login_options.dart"; +export "src/config/spacer_options.dart"; +export "src/service/login_validation.dart"; +export "src/service/validation.dart"; +export "src/widgets/email_password_login.dart"; +export "src/widgets/forgot_password_form.dart"; +export "src/widgets/mfa_widget.dart"; diff --git a/lib/src/config/forgot_password_spacer_options.dart b/lib/src/config/forgot_password_spacer_options.dart index 80df0a5..e9cf7d1 100644 --- a/lib/src/config/forgot_password_spacer_options.dart +++ b/lib/src/config/forgot_password_spacer_options.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +import "package:flutter/material.dart"; @immutable diff --git a/lib/src/config/login_options.dart b/lib/src/config/login_options.dart index 9226692..eddeeff 100644 --- a/lib/src/config/login_options.dart +++ b/lib/src/config/login_options.dart @@ -1,10 +1,10 @@ -import 'dart:async'; +import "dart:async"; -import 'package:flutter/material.dart'; -import 'package:flutter_login/src/config/forgot_password_spacer_options.dart'; -import 'package:flutter_login/src/config/spacer_options.dart'; -import 'package:flutter_login/src/service/login_validation.dart'; -import 'package:flutter_login/src/service/validation.dart'; +import "package:flutter/material.dart"; +import "package:flutter_login/src/config/forgot_password_spacer_options.dart"; +import "package:flutter_login/src/config/spacer_options.dart"; +import "package:flutter_login/src/service/login_validation.dart"; +import "package:flutter_login/src/service/validation.dart"; @immutable class LoginOptions { @@ -17,7 +17,7 @@ class LoginOptions { this.passwordTextAlign, this.emailDecoration = const InputDecoration( contentPadding: EdgeInsets.symmetric(horizontal: 8), - labelText: 'Email address', + labelText: "Email address", border: OutlineInputBorder(), focusedBorder: OutlineInputBorder( borderSide: BorderSide( @@ -32,7 +32,7 @@ class LoginOptions { ), this.passwordDecoration = const InputDecoration( contentPadding: EdgeInsets.symmetric(horizontal: 8), - labelText: 'Password', + labelText: "Password", border: OutlineInputBorder(), focusedBorder: OutlineInputBorder( borderSide: BorderSide( @@ -45,14 +45,15 @@ class LoginOptions { fontSize: 16, ), ), - this.initialEmail = '', - this.initialPassword = '', + this.initialEmail = "", + this.initialPassword = "", this.spacers = const LoginSpacerOptions( spacerBeforeTitle: 8, spacerAfterTitle: 2, formFlexValue: 2, ), this.translations = const LoginTranslations(), + this.accessibilityIdentifiers = const LoginAccessibilityIdentifiers.empty(), this.validationService, this.loginButtonBuilder = _createLoginButton, this.forgotPasswordButtonBuilder = _createForgotPasswordButton, @@ -134,6 +135,12 @@ class LoginOptions { /// Translations for various texts on the login screen. final LoginTranslations translations; + /// Accessibility identifiers for the standard widgets in the component. + /// The inputfields and buttons have accessibility identifiers and their own + /// container so they are visible in the accessibility tree. + /// This is used for testing purposes. + final LoginAccessibilityIdentifiers accessibilityIdentifiers; + /// The validation service used for validating email and password inputs. final ValidationService? validationService; @@ -159,15 +166,17 @@ class LoginOptions { final AppBar? forgotPasswordCustomAppBar; } +/// Translations for all the texts in the component class LoginTranslations { + /// Provide your own translations to override the default english translations const LoginTranslations({ - this.emailEmpty = 'Please enter your email address', - this.passwordEmpty = 'Please enter your password', - this.emailInvalid = 'Please enter a valid email address', - this.loginButton = 'Log in', - this.forgotPasswordButton = 'Forgot password?', - this.requestForgotPasswordButton = 'Send link', - this.registrationButton = 'Create account', + this.emailEmpty = "Please enter your email address", + this.passwordEmpty = "Please enter your password", + this.emailInvalid = "Please enter a valid email address", + this.loginButton = "Log in", + this.forgotPasswordButton = "Forgot password?", + this.requestForgotPasswordButton = "Send link", + this.registrationButton = "Create account", }); final String emailInvalid; @@ -179,6 +188,52 @@ class LoginTranslations { final String registrationButton; } +/// Accessibility identifiers for the standard widgets in the component. +class LoginAccessibilityIdentifiers { + /// Default [LoginAccessibilityIdentifiers] constructor where all the + /// identifiers are required. This is to ensure that apps automatically break + /// when new identifiers are added. + const LoginAccessibilityIdentifiers({ + required this.emailTextFieldIdentifier, + required this.passwordTextFieldIdentifier, + required this.loginButtonIdentifier, + required this.forgotPasswordButtonIdentifier, + required this.requestForgotPasswordButtonIdentifier, + required this.registrationButtonIdentifier, + }); + + /// Empty [LoginAccessibilityIdentifiers] constructor where all the + /// identifiers are already set to their default values. You can override all + /// or some of the default values. + const LoginAccessibilityIdentifiers.empty({ + this.emailTextFieldIdentifier = "email_text_field", + this.passwordTextFieldIdentifier = "password_text_field", + this.loginButtonIdentifier = "login_button", + this.forgotPasswordButtonIdentifier = "forgot_password_button", + this.requestForgotPasswordButtonIdentifier = + "request_forgot_password_button", + this.registrationButtonIdentifier = "registration_button", + }); + + /// Identifier for the email text field. + final String emailTextFieldIdentifier; + + /// Identifier for the password text field. + final String passwordTextFieldIdentifier; + + /// Identifier for the login button. + final String loginButtonIdentifier; + + /// Identifier for the forgot password button. + final String forgotPasswordButtonIdentifier; + + /// Identifier for the request forgot password button. + final String requestForgotPasswordButtonIdentifier; + + /// Identifier for the registration button. + final String registrationButtonIdentifier; +} + Widget _createEmailInputContainer(Widget child) => Padding( padding: const EdgeInsets.only(bottom: 15), child: child, diff --git a/lib/src/config/spacer_options.dart b/lib/src/config/spacer_options.dart index 41de027..5434152 100644 --- a/lib/src/config/spacer_options.dart +++ b/lib/src/config/spacer_options.dart @@ -1,4 +1,4 @@ -import 'package:flutter/material.dart'; +import "package:flutter/material.dart"; @immutable class LoginSpacerOptions { diff --git a/lib/src/service/login_validation.dart b/lib/src/service/login_validation.dart index f5e3216..1f0b165 100644 --- a/lib/src/service/login_validation.dart +++ b/lib/src/service/login_validation.dart @@ -1,4 +1,4 @@ -import 'package:flutter_login/flutter_login.dart'; +import "package:flutter_login/flutter_login.dart"; class LoginValidationService implements ValidationService { const LoginValidationService(this.options); diff --git a/lib/src/widgets/custom_semantics.dart b/lib/src/widgets/custom_semantics.dart new file mode 100644 index 0000000..5dea8d0 --- /dev/null +++ b/lib/src/widgets/custom_semantics.dart @@ -0,0 +1,36 @@ +import "dart:io"; + +import "package:flutter/foundation.dart"; +import "package:flutter/material.dart"; + +/// A wrapper that wraps a widget with a [Semantics] widget. +/// This is used for testing purposes to add a unique identifier to a widget. +/// The [identifier] should be unique +/// [container] is set to true to make sure the widget is always its own +/// accessibility element. +/// [excludeSemantics] is set to false to make sure that the widget can still +/// receive input. +class CustomSemantics extends StatelessWidget { + /// Creates a [CustomSemantics] widget. + /// The [identifier] should be unique for the specific screen. + const CustomSemantics({ + required this.identifier, + required this.child, + super.key, + }); + + /// The widget that should be wrapped with a [Semantics] widget. + final Widget child; + + /// Identifier for the widget that should be unique for the specific screen. + final String identifier; + + @override + Widget build(BuildContext context) => Semantics( + excludeSemantics: false, + container: true, + label: kIsWeb || Platform.isIOS ? null : identifier, + identifier: identifier, + child: child, + ); +} diff --git a/lib/src/widgets/email_password_login.dart b/lib/src/widgets/email_password_login.dart index 07ee4dd..a2cfab5 100644 --- a/lib/src/widgets/email_password_login.dart +++ b/lib/src/widgets/email_password_login.dart @@ -1,7 +1,8 @@ -import 'dart:async'; +import "dart:async"; -import 'package:flutter/material.dart'; -import 'package:flutter_login/flutter_login.dart'; +import "package:flutter/material.dart"; +import "package:flutter_login/flutter_login.dart"; +import "package:flutter_login/src/widgets/custom_semantics.dart"; class EmailPasswordLoginForm extends StatefulWidget { /// Constructs an [EmailPasswordLoginForm] widget. @@ -45,8 +46,8 @@ class _EmailPasswordLoginFormState extends State { final ValueNotifier _formValid = ValueNotifier(false); bool _obscurePassword = true; - String _currentEmail = ''; - String _currentPassword = ''; + String _currentEmail = ""; + String _currentPassword = ""; void _updateCurrentEmail(String email) { _currentEmail = email; @@ -92,92 +93,108 @@ class _EmailPasswordLoginFormState extends State { Widget build(BuildContext context) { var options = widget.options; - var emailTextFormField = TextFormField( - autofillHints: const [ - AutofillHints.email, - AutofillHints.username, - ], - textAlign: options.emailTextAlign ?? TextAlign.start, - onChanged: _updateCurrentEmail, - validator: widget.options.validations.validateEmail, - initialValue: options.initialEmail, - keyboardType: TextInputType.emailAddress, - textInputAction: TextInputAction.next, - style: options.emailTextStyle, - decoration: options.emailDecoration, + var emailTextFormField = CustomSemantics( + identifier: options.accessibilityIdentifiers.emailTextFieldIdentifier, + child: TextFormField( + autofillHints: const [ + AutofillHints.email, + AutofillHints.username, + ], + textAlign: options.emailTextAlign ?? TextAlign.start, + onChanged: _updateCurrentEmail, + validator: widget.options.validations.validateEmail, + initialValue: options.initialEmail, + keyboardType: TextInputType.emailAddress, + textInputAction: TextInputAction.next, + style: options.emailTextStyle, + decoration: options.emailDecoration, + ), ); - var passwordTextFormField = TextFormField( - autofillHints: const [ - AutofillHints.password, - ], - textAlign: options.passwordTextAlign ?? TextAlign.start, - obscureText: _obscurePassword, - onChanged: _updateCurrentPassword, - validator: widget.options.validations.validatePassword, - initialValue: options.initialPassword, - keyboardType: TextInputType.visiblePassword, - textInputAction: TextInputAction.done, - style: options.passwordTextStyle, - onFieldSubmitted: (_) async => _handleLogin(), - decoration: options.passwordDecoration.copyWith( - suffixIcon: options.showObscurePassword - ? IconButton( - padding: options.suffixIconPadding, - onPressed: () { - setState(() { - _obscurePassword = !_obscurePassword; - }); - }, - icon: Icon( - _obscurePassword ? Icons.visibility : Icons.visibility_off, - size: options.suffixIconSize, - ), - ) - : null, + var passwordTextFormField = CustomSemantics( + identifier: options.accessibilityIdentifiers.passwordTextFieldIdentifier, + child: TextFormField( + autofillHints: const [ + AutofillHints.password, + ], + textAlign: options.passwordTextAlign ?? TextAlign.start, + obscureText: _obscurePassword, + onChanged: _updateCurrentPassword, + validator: widget.options.validations.validatePassword, + initialValue: options.initialPassword, + keyboardType: TextInputType.visiblePassword, + textInputAction: TextInputAction.done, + style: options.passwordTextStyle, + onFieldSubmitted: (_) async => _handleLogin(), + decoration: options.passwordDecoration.copyWith( + suffixIcon: options.showObscurePassword + ? IconButton( + padding: options.suffixIconPadding, + onPressed: () { + setState(() { + _obscurePassword = !_obscurePassword; + }); + }, + icon: Icon( + _obscurePassword ? Icons.visibility : Icons.visibility_off, + size: options.suffixIconSize, + ), + ) + : null, + ), ), ); var forgotPasswordButton = widget.onForgotPassword != null ? Align( alignment: Alignment.topRight, - child: options.forgotPasswordButtonBuilder( - context, - () => widget.onForgotPassword?.call(_currentEmail, context), - false, - () {}, - options, + child: CustomSemantics( + identifier: options + .accessibilityIdentifiers.forgotPasswordButtonIdentifier, + child: options.forgotPasswordButtonBuilder( + context, + () => widget.onForgotPassword?.call(_currentEmail, context), + false, + () {}, + options, + ), ), ) : const SizedBox(height: 16); var loginButton = AnimatedBuilder( animation: _formValid, - builder: (context, _) => options.loginButtonBuilder( + builder: (context, _) => CustomSemantics( + identifier: options.accessibilityIdentifiers.loginButtonIdentifier, + child: options.loginButtonBuilder( + context, + _handleLogin, + !_formValid.value, + () { + _formKey.currentState?.validate(); + }, + options, + ), + ), + ); + + var registrationButton = CustomSemantics( + identifier: options.accessibilityIdentifiers.registrationButtonIdentifier, + child: options.registrationButtonBuilder( context, - _handleLogin, - !_formValid.value, - () { - _formKey.currentState?.validate(); + () async { + widget.onRegister?.call( + _currentEmail, + _currentPassword, + context, + ); }, + false, + () {}, options, ), ); - var registerButton = options.registrationButtonBuilder( - context, - () async { - widget.onRegister?.call( - _currentEmail, - _currentPassword, - context, - ); - }, - false, - () {}, - options, - ); - return Scaffold( backgroundColor: options.loginBackgroundColor, body: CustomScrollView( @@ -220,7 +237,7 @@ class _EmailPasswordLoginFormState extends State { ], loginButton, if (widget.onRegister != null) ...[ - registerButton, + registrationButton, ], if (options.spacers.spacerAfterButton != null) ...[ Spacer(flex: options.spacers.spacerAfterButton!), diff --git a/lib/src/widgets/forgot_password_form.dart b/lib/src/widgets/forgot_password_form.dart index 8d98d4c..159b354 100644 --- a/lib/src/widgets/forgot_password_form.dart +++ b/lib/src/widgets/forgot_password_form.dart @@ -1,7 +1,8 @@ -import 'dart:async'; +import "dart:async"; -import 'package:flutter/material.dart'; -import 'package:flutter_login/flutter_login.dart'; +import "package:flutter/material.dart"; +import "package:flutter_login/flutter_login.dart"; +import "package:flutter_login/src/widgets/custom_semantics.dart"; class ForgotPasswordForm extends StatefulWidget { /// Constructs a [ForgotPasswordForm] widget. @@ -49,7 +50,7 @@ class _ForgotPasswordFormState extends State { final ValueNotifier _formValid = ValueNotifier(false); - String _currentEmail = ''; + String _currentEmail = ""; void _updateCurrentEmail(String email) { _currentEmail = email; @@ -135,19 +136,23 @@ class _ForgotPasswordFormState extends State { child: Align( alignment: Alignment.center, child: options.emailInputContainerBuilder( - TextFormField( - autofillHints: const [AutofillHints.email], - textAlign: - options.emailTextAlign ?? TextAlign.start, - focusNode: _focusNode, - onChanged: _updateCurrentEmail, - validator: - widget.options.validations.validateEmail, - initialValue: options.initialEmail, - keyboardType: TextInputType.emailAddress, - textInputAction: TextInputAction.next, - style: options.emailTextStyle, - decoration: options.emailDecoration, + CustomSemantics( + identifier: options.accessibilityIdentifiers + .emailTextFieldIdentifier, + child: TextFormField( + autofillHints: const [AutofillHints.email], + textAlign: + options.emailTextAlign ?? TextAlign.start, + focusNode: _focusNode, + onChanged: _updateCurrentEmail, + validator: + widget.options.validations.validateEmail, + initialValue: options.initialEmail, + keyboardType: TextInputType.emailAddress, + textInputAction: TextInputAction.next, + style: options.emailTextStyle, + decoration: options.emailDecoration, + ), ), ), ), @@ -165,19 +170,24 @@ class _ForgotPasswordFormState extends State { AnimatedBuilder( animation: _formValid, builder: (context, snapshot) => Align( - child: widget.options.requestForgotPasswordButtonBuilder( - context, - () async { - _formKey.currentState?.validate(); - if (_formValid.value) { - widget.onRequestForgotPassword(_currentEmail); - } - }, - !_formValid.value, - () { - _formKey.currentState?.validate(); - }, - options, + child: CustomSemantics( + identifier: options.accessibilityIdentifiers + .requestForgotPasswordButtonIdentifier, + child: + widget.options.requestForgotPasswordButtonBuilder( + context, + () async { + _formKey.currentState?.validate(); + if (_formValid.value) { + widget.onRequestForgotPassword(_currentEmail); + } + }, + !_formValid.value, + () { + _formKey.currentState?.validate(); + }, + options, + ), ), ), ), diff --git a/lib/src/widgets/mfa_widget.dart b/lib/src/widgets/mfa_widget.dart index 62eb00b..1308ce1 100644 --- a/lib/src/widgets/mfa_widget.dart +++ b/lib/src/widgets/mfa_widget.dart @@ -1,5 +1,5 @@ -import 'package:flutter/material.dart'; -import 'package:pinput/pinput.dart'; +import "package:flutter/material.dart"; +import "package:pinput/pinput.dart"; class MFAWidget extends StatefulWidget { /// Constructs an [MFAWidget]. @@ -39,8 +39,8 @@ class MFAWidget extends StatefulWidget { }) : assert( (onSubmitted == null && submitButtonBuilder == null) || (onSubmitted != null && submitButtonBuilder != null), - 'onSubmitted and submitButtonBuilder must be both null or both' - ' not null', + "onSubmitted and submitButtonBuilder must be both null or both" + " not null", ); /// Callback function triggered when the MFA code is completed. @@ -106,7 +106,11 @@ class _MFAWidgetState extends State { followingPinTheme: widget.followingPinTheme, disabledPinTheme: widget.disabledPinTheme, errorPinTheme: widget.errorPinTheme, - separatorPositions: widget.seperatorPositions, + separatorBuilder: (index) { + var seperatorSize = + widget.seperatorPositions?[index].toDouble() ?? 8.0; + return SizedBox(width: seperatorSize); + }, errorBuilder: widget.errorBuilder, errorText: widget.errorText, errorTextStyle: widget.errorTextStyle, diff --git a/pubspec.yaml b/pubspec.yaml index 18bab5b..4465171 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_login description: Flutter Login Component -version: 7.1.3 +version: 7.2.0 publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub @@ -11,7 +11,7 @@ environment: dependencies: flutter: sdk: flutter - pinput: ^2.2.31 + pinput: ^5.0.1 dev_dependencies: flutter_test: @@ -19,6 +19,4 @@ dev_dependencies: flutter_iconica_analysis: git: url: https://github.com/Iconica-Development/flutter_iconica_analysis - ref: 6.0.0 - -flutter: + ref: 7.0.0