diff --git a/packages/wyatt_form_bloc/README.md b/packages/wyatt_form_bloc/README.md index 2ac8212b..74a53324 100644 --- a/packages/wyatt_form_bloc/README.md +++ b/packages/wyatt_form_bloc/README.md @@ -30,21 +30,22 @@ Form Bloc for Dart & Flutter. ## Features - Form - * FormInput: *atom of a form* + * FormInputValidator: - Store data - Validate this data - * FormEntry: *shell of this atom* - - Associate a key to an input - - Configure form attribute (exportation, name...) - * FormData: *collection of entries* - - Contain all entries + * FormInputMetadata: + - Store infos and options about an input. + * FormInput: + - Associaite a key, to a validator and metadata. + * FormData: *collection of inputs* + - Contain all inputs - Basic set operation - FormDataCubit * Data management behind a form. - Use entries to pass a FormData object - - You can use several pre configured FormInput for validation - - You can use updateFormData() to change FormData and validators during runtime (intersection, union, difference or replace) + - You can use several pre configured `FormInputValidator` for validation + - You can use updateFormData() to change `FormData` during runtime (intersection, union, difference or replace) - Consistent * Every class have same naming convention @@ -59,4 +60,120 @@ import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; ## Usage -todo \ No newline at end of file +Firstly, you have to create your form inputs. + +```dart +static List getNormalEntries() { + return const [ + FormInput(formFieldName, Name.pure()), + FormInput(formFieldEmail, Email.pure()), + FormInput(formFieldPhone, Phone.pure()), + FormInput(formFieldList, ListOption.pure(defaultValue: ['checkbox3'])), + FormInput(formFieldRadio, TextString.pure()), + FormInput(formFieldPro, Boolean.pure(), metadata: FormInputMetadata(name: 'business')), + FormInput(formFieldHidden, Boolean.pure(), metadata: FormInputMetadata(export: false)), + ]; +} + +static List getBusinessEntries() { + const entries = [ + FormInput(formFieldSiren, Siren.pure()), + FormInput(formFieldIban, Iban.pure()), + ]; + return getNormalEntries() + entries; +} + +static FormData getNormalFormData() { + return FormData(getNormalEntries()); +} + +static FormData getProFormData() { + return FormData(getBusinessEntries()); +} +``` + +> Let's create functions to enable dynamic changes in runtime. + +> When creating metadata with `FormInputMetadata`, `T` is the type of `extra` object. + +Then a `FormData` is a collection of inputs. You can `validate`, `contains`, `intersection`, `difference`, `union`, or `clone` this data. + +After that, you have to extends `FormDataCubit`. + +```dart +class CustomFormCubit extends FormDataCubit { + CustomFormCubit({required FormData inputs}) : super(inputs: inputs); + + @override + Future submitForm() { + log(state.data.toMap().toString()); + // Handle all your logic here. + emit(...) + } +} +``` + +> The submited form is in `state.data` ! + +Don't forget to create and provide it ! + +```dart +FormDataCubit _formCubit = CustomFormCubit(inputs: getNormalFormData()); + +return BlocProvider( + create: (context) => _formCubit, + child: const WidgetTree(), +); +``` + +You can now create the first form input ! + +```dart +class _EmailInput extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return TextField( + onChanged: (email) => context + .read() + .dataChanged(formFieldEmail, Email.dirty(email)), + keyboardType: TextInputType.emailAddress, + decoration: InputDecoration( + labelText: 'email', + helperText: '', + errorText: state.data.isNotValid(formFieldEmail) + ? 'invalid email' + : null, + ), + ); + }, + ); + } +} +``` + +Then, you can create the trigger + +```dart +class _SignUpButton extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) => previous.status != current.status, + builder: (context, state) { + return state.status.isSubmissionInProgress + ? const CircularProgressIndicator() + : ElevatedButton( + onPressed: state.status.isValidated + ? () => context.read().submitForm() + : null, + child: const Text('SIGN UP'), + ); + }, + ); + } +} +``` + +> With `state.status` you can access the status of the form to check if there is an error or if it's in submission. \ No newline at end of file diff --git a/packages/wyatt_form_bloc/example/.metadata b/packages/wyatt_form_bloc/example/.metadata index 3c3e4b52..75a8145c 100644 --- a/packages/wyatt_form_bloc/example/.metadata +++ b/packages/wyatt_form_bloc/example/.metadata @@ -1,10 +1,30 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled and should not be manually edited. +# This file should be version controlled. version: - revision: 5464c5bac742001448fe4fc0597be939379f88ea + revision: 85684f9300908116a78138ea4c6036c35c9a1236 channel: stable project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 85684f9300908116a78138ea4c6036c35c9a1236 + base_revision: 85684f9300908116a78138ea4c6036c35c9a1236 + - platform: web + create_revision: 85684f9300908116a78138ea4c6036c35c9a1236 + base_revision: 85684f9300908116a78138ea4c6036c35c9a1236 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/wyatt_form_bloc/example/lib/app/app.dart b/packages/wyatt_form_bloc/example/lib/app/app.dart index 60d99e66..cc8691b4 100644 --- a/packages/wyatt_form_bloc/example/lib/app/app.dart +++ b/packages/wyatt_form_bloc/example/lib/app/app.dart @@ -16,31 +16,37 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:form_bloc_example/app/metadata.dart'; import 'package:form_bloc_example/constants.dart'; import 'package:form_bloc_example/cubit/custom_form_cubit.dart'; import 'package:form_bloc_example/sign_up/sign_up_page.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +const blue = Metadata(category: Category.perso); +const red = Metadata(category: Category.business); + class App extends StatelessWidget { const App({Key? key}) : super(key: key); - static List getNormalEntries() { + static List getNormalEntries() { return const [ - FormEntry(formFieldName, Name.pure()), - FormEntry(formFieldEmail, Email.pure()), - FormEntry(formFieldPhone, Phone.pure()), - FormEntry( + FormInput(formFieldName, Name.pure(), metadata: FormInputMetadata(extra: blue)), + FormInput(formFieldEmail, Email.pure(), metadata: FormInputMetadata(extra: blue)), + FormInput(formFieldPhone, Phone.pure(), metadata: FormInputMetadata(extra: red)), + FormInput( formFieldList, ListOption.pure(defaultValue: ['checkbox3'])), - FormEntry(formFieldRadio, TextString.pure()), - FormEntry(formFieldPro, Boolean.pure(), name: 'business'), - FormEntry(formFieldHidden, Boolean.pure(), export: false), + FormInput(formFieldRadio, TextString.pure()), + FormInput(formFieldPro, Boolean.pure(), + metadata: FormInputMetadata(name: 'business')), + FormInput(formFieldHidden, Boolean.pure(), + metadata: FormInputMetadata(export: false, extra: blue)), ]; } - static List getBusinessEntries() { + static List getBusinessEntries() { const entries = [ - FormEntry(formFieldSiren, Siren.pure()), - FormEntry(formFieldIban, Iban.pure()), + FormInput(formFieldSiren, Siren.pure()), + FormInput(formFieldIban, Iban.pure()), ]; return getNormalEntries() + entries; } @@ -55,7 +61,7 @@ class App extends StatelessWidget { @override Widget build(BuildContext context) { - FormDataCubit _formCubit = CustomFormCubit(entries: getNormalFormData()); + FormDataCubit _formCubit = CustomFormCubit(inputs: getNormalFormData()); return BlocProvider( create: (context) => _formCubit, diff --git a/packages/wyatt_form_bloc/example/lib/cubit/custom_form_state.dart b/packages/wyatt_form_bloc/example/lib/app/metadata.dart similarity index 72% rename from packages/wyatt_form_bloc/example/lib/cubit/custom_form_state.dart rename to packages/wyatt_form_bloc/example/lib/app/metadata.dart index f6993044..b4e68725 100644 --- a/packages/wyatt_form_bloc/example/lib/cubit/custom_form_state.dart +++ b/packages/wyatt_form_bloc/example/lib/app/metadata.dart @@ -1,3 +1,4 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. // @@ -14,9 +15,20 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -part of 'custom_form_cubit.dart'; +enum Category { + perso, + business +} -@immutable -abstract class CustomFormState {} +class Metadata { + final Category category; -class CustomFormInitial extends CustomFormState {} + const Metadata({ + required this.category, + }); + + @override + String toString() { + return category.toString(); + } +} diff --git a/packages/wyatt_form_bloc/example/lib/cubit/custom_form_cubit.dart b/packages/wyatt_form_bloc/example/lib/cubit/custom_form_cubit.dart index 6cdae37d..3f211c60 100644 --- a/packages/wyatt_form_bloc/example/lib/cubit/custom_form_cubit.dart +++ b/packages/wyatt_form_bloc/example/lib/cubit/custom_form_cubit.dart @@ -16,18 +16,15 @@ import 'dart:developer'; -import 'package:meta/meta.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; -part 'custom_form_state.dart'; - class CustomFormCubit extends FormDataCubit { - CustomFormCubit({required FormData entries}) : super(entries: entries); + CustomFormCubit({required FormData inputs}) : super(inputs: inputs); @override Future submitForm() { log(state.data.toMap().toString()); - + return Future.value(); } } diff --git a/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart index 82d28ed2..6d611a5d 100644 --- a/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart +++ b/packages/wyatt_form_bloc/example/lib/sign_up/widgets/sign_up_form.dart @@ -19,35 +19,83 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:form_bloc_example/app/app.dart'; +import 'package:form_bloc_example/app/metadata.dart'; import 'package:form_bloc_example/constants.dart'; import 'package:wyatt_form_bloc/wyatt_form_bloc.dart'; +class CategoryIndicator extends StatelessWidget { + const CategoryIndicator( + {Key? key, required this.field, required this.builder}) + : super(key: key); + + final String field; + final Function(BuildContext context, FormDataState state) builder; + + Color computeColor(Metadata meta) { + switch (meta.category) { + case Category.perso: + return Colors.blue; + case Category.business: + return Colors.red; + } + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: ((context, state) { + final meta = state.data.metadataOf(field).extra as Metadata; + final color = computeColor(meta); + + return Row( + children: [ + Container( + height: 8, + width: 8, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(8), + ), + ), + const SizedBox(width: 20,), + SizedBox( + width: MediaQuery.of(context).size.width - 45, + child: builder(context, state), + ) + ], + ); + }), + ); + } +} + class _NameInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return TextField( - onChanged: (name) => context - .read() - .dataChanged(formFieldName, Name.dirty(name)), - keyboardType: TextInputType.name, - decoration: InputDecoration( - labelText: 'name', - helperText: '', - errorText: - state.data.input(formFieldName).invalid ? 'invalid name' : null, - ), - ); - }, - ); + return CategoryIndicator( + field: formFieldName, + builder: (context, state) { + return TextField( + onChanged: (name) => context + .read() + .dataChanged(formFieldName, Name.dirty(name)), + keyboardType: TextInputType.name, + decoration: InputDecoration( + labelText: 'name', + helperText: '', + errorText: + state.data.isNotValid(formFieldName) ? 'invalid name' : null, + ), + ); + }); } } class _EmailInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return CategoryIndicator( + field: formFieldEmail, builder: (context, state) { return TextField( onChanged: (email) => context @@ -57,9 +105,8 @@ class _EmailInput extends StatelessWidget { decoration: InputDecoration( labelText: 'email', helperText: '', - errorText: state.data.input(formFieldEmail).invalid - ? 'invalid email' - : null, + errorText: + state.data.isNotValid(formFieldEmail) ? 'invalid email' : null, ), ); }, @@ -70,7 +117,8 @@ class _EmailInput extends StatelessWidget { class _PhoneInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return CategoryIndicator( + field: formFieldPhone, builder: (context, state) { return TextField( onChanged: (phone) => context @@ -80,9 +128,8 @@ class _PhoneInput extends StatelessWidget { decoration: InputDecoration( labelText: 'phone', helperText: '', - errorText: state.data.input(formFieldPhone).invalid - ? 'invalid phone' - : null, + errorText: + state.data.isNotValid(formFieldPhone) ? 'invalid phone' : null, ), ); }, @@ -93,7 +140,8 @@ class _PhoneInput extends StatelessWidget { class _SirenInput extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return CategoryIndicator( + field: formFieldName, builder: (context, state) { return TextField( onChanged: (siren) => context @@ -103,9 +151,8 @@ class _SirenInput extends StatelessWidget { decoration: InputDecoration( labelText: 'siren', helperText: '', - errorText: state.data.input(formFieldSiren).invalid - ? 'invalid SIREN' - : null, + errorText: + state.data.isNotValid(formFieldSiren) ? 'invalid SIREN' : null, ), ); }, @@ -127,7 +174,7 @@ class _IbanInput extends StatelessWidget { labelText: 'iban', helperText: '', errorText: - state.data.input(formFieldIban).invalid ? 'invalid IBAN' : null, + state.data.isNotValid(formFieldIban) ? 'invalid IBAN' : null, ), ); }, @@ -141,7 +188,7 @@ class _CheckListInput extends StatelessWidget { return BlocBuilder( builder: (context, state) { final _input = - state.data.input>(formFieldList) as ListOption; + state.data.validatorOf>(formFieldList); final _options = _input.value; return Column( @@ -192,8 +239,7 @@ class _RadioListInput extends StatelessWidget { Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - final _input = - state.data.input(formFieldRadio) as TextString; + final _input = state.data.validatorOf(formFieldRadio); return Column( mainAxisSize: MainAxisSize.min, @@ -249,7 +295,7 @@ class _CheckHiddenInput extends StatelessWidget { trailing: BlocBuilder( builder: (context, state) { return Checkbox( - value: state.data.input(formFieldHidden).value, + value: state.data.validatorOf(formFieldHidden).value, onChanged: (v) { final value = v!; // state is false, so value can't be null @@ -272,7 +318,7 @@ class _CheckIsProInput extends StatelessWidget { trailing: BlocBuilder( builder: (context, state) { return Checkbox( - value: state.data.input(formFieldPro).value, + value: state.data.validatorOf(formFieldPro).value, onChanged: (isPro) { final value = isPro!; // state is false, so value can't be null @@ -370,7 +416,7 @@ class SignUpForm extends StatelessWidget { const SizedBox(height: 8), BlocBuilder( builder: (context, state) { - if (state.data.input(formFieldPro).value) { + if (state.data.validatorOf(formFieldPro).value) { return Column(children: [ _SirenInput(), const SizedBox(height: 8), diff --git a/packages/wyatt_form_bloc/example/pubspec.yaml b/packages/wyatt_form_bloc/example/pubspec.yaml index 64a109bb..63abb8c0 100644 --- a/packages/wyatt_form_bloc/example/pubspec.yaml +++ b/packages/wyatt_form_bloc/example/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.16.2 <3.0.0" + sdk: ">=2.17.2 <3.0.0" # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions diff --git a/packages/wyatt_form_bloc/example/web/favicon.png b/packages/wyatt_form_bloc/example/web/favicon.png new file mode 100644 index 00000000..8aaa46ac Binary files /dev/null and b/packages/wyatt_form_bloc/example/web/favicon.png differ diff --git a/packages/wyatt_form_bloc/example/web/icons/Icon-192.png b/packages/wyatt_form_bloc/example/web/icons/Icon-192.png new file mode 100644 index 00000000..b749bfef Binary files /dev/null and b/packages/wyatt_form_bloc/example/web/icons/Icon-192.png differ diff --git a/packages/wyatt_form_bloc/example/web/icons/Icon-512.png b/packages/wyatt_form_bloc/example/web/icons/Icon-512.png new file mode 100644 index 00000000..88cfd48d Binary files /dev/null and b/packages/wyatt_form_bloc/example/web/icons/Icon-512.png differ diff --git a/packages/wyatt_form_bloc/example/web/icons/Icon-maskable-192.png b/packages/wyatt_form_bloc/example/web/icons/Icon-maskable-192.png new file mode 100644 index 00000000..eb9b4d76 Binary files /dev/null and b/packages/wyatt_form_bloc/example/web/icons/Icon-maskable-192.png differ diff --git a/packages/wyatt_form_bloc/example/web/icons/Icon-maskable-512.png b/packages/wyatt_form_bloc/example/web/icons/Icon-maskable-512.png new file mode 100644 index 00000000..d69c5669 Binary files /dev/null and b/packages/wyatt_form_bloc/example/web/icons/Icon-maskable-512.png differ diff --git a/packages/wyatt_form_bloc/example/web/index.html b/packages/wyatt_form_bloc/example/web/index.html new file mode 100644 index 00000000..41b3bc33 --- /dev/null +++ b/packages/wyatt_form_bloc/example/web/index.html @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + example + + + + + + + + + + diff --git a/packages/wyatt_form_bloc/example/web/manifest.json b/packages/wyatt_form_bloc/example/web/manifest.json new file mode 100644 index 00000000..096edf8f --- /dev/null +++ b/packages/wyatt_form_bloc/example/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/packages/wyatt_form_bloc/lib/src/cubit/form_data_cubit.dart b/packages/wyatt_form_bloc/lib/src/cubit/form_data_cubit.dart index 728c239d..1be75738 100644 --- a/packages/wyatt_form_bloc/lib/src/cubit/form_data_cubit.dart +++ b/packages/wyatt_form_bloc/lib/src/cubit/form_data_cubit.dart @@ -17,6 +17,7 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; import 'package:meta/meta.dart'; import 'package:wyatt_form_bloc/src/enums/enums.dart'; import 'package:wyatt_form_bloc/src/form/form.dart'; @@ -24,19 +25,19 @@ import 'package:wyatt_form_bloc/src/form/form.dart'; part 'form_data_state.dart'; abstract class FormDataCubit extends Cubit { - FormDataCubit({required FormData entries}) - : super(FormDataState(data: entries)); + FormDataCubit({required FormData inputs}) + : super(FormDataState(data: inputs)); /// Change value of a field. /// /// Inputs: /// - `field`: The key of the field to change. - /// - `dirtyValue`: The new value of the field. - void dataChanged(String field, FormInput dirtyValue) { + /// - `dirtyValue`: The new value of the field. (Wrapped in a dirty validator) + void dataChanged(String field, FormInputValidator dirtyValue) { final _form = state.data.clone(); if (_form.contains(field)) { - _form.update(field, dirtyValue); + _form.updateValidator(field, dirtyValue); } else { throw Exception('Form field $field not found'); } @@ -44,7 +45,7 @@ abstract class FormDataCubit extends Cubit { emit( state.copyWith( data: _form, - status: _form.selfValidate(), + status: _form.validate(), ), ); } @@ -78,7 +79,7 @@ abstract class FormDataCubit extends Cubit { emit( state.copyWith( data: _form, - status: _form.selfValidate(), + status: _form.validate(), ), ); } diff --git a/packages/wyatt_form_bloc/lib/src/cubit/form_data_state.dart b/packages/wyatt_form_bloc/lib/src/cubit/form_data_state.dart index d8f5ec82..2d03e217 100644 --- a/packages/wyatt_form_bloc/lib/src/cubit/form_data_state.dart +++ b/packages/wyatt_form_bloc/lib/src/cubit/form_data_state.dart @@ -17,7 +17,7 @@ part of 'form_data_cubit.dart'; @immutable -class FormDataState { +class FormDataState extends Equatable { final FormStatus status; final FormData data; final String? errorMessage; @@ -41,23 +41,8 @@ class FormDataState { } @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - - return other is FormDataState && - other.status == status && - other.data == data && - other.errorMessage == errorMessage; - } - + bool? get stringify => true; + @override - int get hashCode { - return status.hashCode ^ data.hashCode ^ errorMessage.hashCode; - } - - @override - String toString() { - return 'FormDataState(status: $status, data: $data, ' - 'errorMessage: $errorMessage)'; - } + List get props => [status, data, errorMessage]; } diff --git a/packages/wyatt_form_bloc/lib/src/enums/form_status.dart b/packages/wyatt_form_bloc/lib/src/enums/form_status.dart index 8e0709be..b5701ef6 100644 --- a/packages/wyatt_form_bloc/lib/src/enums/form_status.dart +++ b/packages/wyatt_form_bloc/lib/src/enums/form_status.dart @@ -14,6 +14,16 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +import 'package:wyatt_form_bloc/src/form/form.dart'; + +const Set _validatedFormStatuses = { + FormStatus.valid, + FormStatus.submissionInProgress, + FormStatus.submissionSuccess, + FormStatus.submissionFailure, + FormStatus.submissionCanceled, +}; + /// Enum representing the status of a form at any given point in time. enum FormStatus { /// The form has not been touched. @@ -35,19 +45,8 @@ enum FormStatus { submissionFailure, /// The form submission has been canceled. - submissionCanceled -} + submissionCanceled; -const Set _validatedFormStatuses = { - FormStatus.valid, - FormStatus.submissionInProgress, - FormStatus.submissionSuccess, - FormStatus.submissionFailure, - FormStatus.submissionCanceled, -}; - -/// Useful extensions on [FormStatus] -extension FormStatusX on FormStatus { /// Indicates whether the form is untouched. bool get isPure => this == FormStatus.pure; @@ -76,4 +75,13 @@ extension FormStatusX on FormStatus { /// Indicates whether the form submission has been canceled. bool get isSubmissionCanceled => this == FormStatus.submissionCanceled; + + /// Validate a list of inputs + static FormStatus validate(List inputs) { + return inputs.every((FormInput input) => input.validator.pure) + ? FormStatus.pure + : inputs.any((FormInput input) => input.validator.valid == false) + ? FormStatus.invalid + : FormStatus.valid; + } } diff --git a/packages/wyatt_form_bloc/lib/src/form/form.dart b/packages/wyatt_form_bloc/lib/src/form/form.dart index a7ab3277..2a131d1b 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form.dart +++ b/packages/wyatt_form_bloc/lib/src/form/form.dart @@ -1,19 +1,25 @@ // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. -// +// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. -// +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program. If not, see . -export 'form_data.dart'; -export 'form_entry.dart'; -export 'form_input.dart'; +import 'package:equatable/equatable.dart'; +import 'package:meta/meta.dart'; +import 'package:wyatt_form_bloc/src/enums/form_input_status.dart'; +import 'package:wyatt_form_bloc/src/enums/form_status.dart'; + +part 'form_input.dart'; +part 'form_input_metadata.dart'; +part 'form_input_validator.dart'; +part 'form_data.dart'; diff --git a/packages/wyatt_form_bloc/lib/src/form/form_data.dart b/packages/wyatt_form_bloc/lib/src/form/form_data.dart index 6bad8487..8c978cf9 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form_data.dart +++ b/packages/wyatt_form_bloc/lib/src/form/form_data.dart @@ -14,133 +14,164 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:meta/meta.dart'; -import 'package:wyatt_form_bloc/src/enums/enums.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; -import 'package:wyatt_form_bloc/src/utils/list_equals.dart'; +part of 'form.dart'; @immutable -class FormData { - const FormData(this._entries); +class FormData extends Equatable { + final List _inputs; - FormData.empty() : this([]); + const FormData(this._inputs); + const FormData.empty() : this(const []); - final List _entries; - - List get entries => _entries; - - List> inputs() { - return _entries - .map((FormEntry entry) => entry.input as FormInput) - .toList(); - } - - static FormStatus validate(List inputs) { - return inputs.every((FormInput element) => element.pure) - ? FormStatus.pure - : inputs.any((FormInput input) => input.valid == false) - ? FormStatus.invalid - : FormStatus.valid; - } - - FormStatus selfValidate() { - return validate(inputs()); - } - - FormInput input(String key) { + /// Returns the input for the associated key + FormInput inputByKey(String key) { if (contains(key)) { - return _entries.firstWhere((FormEntry entry) => entry.key == key).input - as FormInput; + return _inputs.firstWhere((FormInput input) => input.key == key); } else { throw Exception('FormInput with key `$key` does not exist in form'); } } - bool contains(String key) { - return _entries.any((FormEntry entry) => entry.key == key); - } - - FormData intersection(FormData other) { - final List entries = []; - - for (final FormEntry entry in _entries) { - if (other.contains(entry.key)) { - entries.add(entry); - } - } - - return FormData(entries); - } - - FormData difference(FormData other) { - final List entries = []; - - for (final FormEntry otherEntry in other._entries) { - if (!contains(otherEntry.key)) { - entries.add(otherEntry); - } - } - - for (final FormEntry entry in _entries) { - if (!other.contains(entry.key)) { - entries.add(entry); - } - } - - return FormData(entries); - } - - FormData union(FormData other) { - final List entries = []; - - for (final FormEntry entry in _entries) { - entries.add(entry); - } - - for (final FormEntry otherEntry in other._entries) { - if (!contains(otherEntry.key)) { - entries.add(otherEntry); - } - } - - return FormData(entries); - } - - void update(String key, FormInput input) { + /// Updates a input (perform a replace at index). + void updateInput(String key, FormInput input) { if (contains(key)) { - final index = _entries.indexOf( - _entries.firstWhere((FormEntry entry) => entry.key == key), + final index = _inputs.indexOf( + inputByKey(key), ); - _entries[index] = _entries[index].copyWith(input: input); + _inputs[index] = input; } } + /// Updates validator of a given input. (perform copyWith) + void updateValidator(String key, FormInputValidator dirtyValue) { + if (contains(key)) { + final index = _inputs.indexOf( + inputByKey(key), + ); + _inputs[index] = _inputs[index].copyWith(validator: dirtyValue); + } + } + + /// Updates metadata of a given input. (perform copyWith) + void updateMetadata(String key, FormInputMetadata meta) { + if (contains(key)) { + final index = _inputs.indexOf( + inputByKey(key), + ); + _inputs[index] = _inputs[index].copyWith(metadata: meta); + } + } + + /// A [FormInputValidator] represents the value of a single form input field. + /// It contains information about the [FormInputStatus], value, as well + /// as validation status. + T validatorOf(String key) { + return inputByKey(key).validator as T; + } + + /// Returns a validation error if the [FormInputValidator] is invalid. + /// Returns null if the [FormInputValidator] is valid. + E? errorOf(String key) { + return (inputByKey(key).validator as FormInputValidator).error; + } + + /// The value of the associated [FormInputValidator]. For example, + /// if you have a FormInputValidator for FirstName, the value could be 'Joe'. + V valueOf(String key) { + return (inputByKey(key).validator as FormInputValidator).value; + } + + /// Returns `true` if the [FormInputValidator] is not valid. + /// Same as `E? errorOf(String key) != null` + bool isNotValid(String key) { + return !inputByKey(key).validator.valid; + } + + /// Returns the metadata associated. With `M` the type of extra data. + FormInputMetadata metadataOf(String key) { + return inputByKey(key).metadata as FormInputMetadata; + } + + /// Validate self inputs. + FormStatus validate() { + return FormStatus.validate(_inputs); + } + + /// Check if this contains an input with the given key. + bool contains(String key) { + return _inputs.any((FormInput input) => input.key == key); + } + + /// Makes an intersection set operation and returns newly created [FormData] + FormData intersection(FormData other) { + final List inputs = []; + + for (final FormInput i in _inputs) { + if (other.contains(i.key)) { + inputs.add(i); + } + } + + return FormData(inputs); + } + + /// Makes a difference set operation and returns newly created [FormData] + FormData difference(FormData other) { + final List inputs = []; + + for (final FormInput i in other._inputs) { + if (!contains(i.key)) { + inputs.add(i); + } + } + + for (final FormInput i in _inputs) { + if (!other.contains(i.key)) { + inputs.add(i); + } + } + + return FormData(inputs); + } + + /// Makes an union set operation and returns newly created [FormData] + FormData union(FormData other) { + final List inputs = []; + + for (final FormInput i in _inputs) { + inputs.add(i); + } + + for (final FormInput i in other._inputs) { + if (!contains(i.key)) { + inputs.add(i); + } + } + + return FormData(inputs); + } + + /// Deeply copy this. FormData clone() { return FormData( - _entries.map((FormEntry entry) => entry.clone()).toList(), + _inputs.map((FormInput input) => input.clone()).toList(), ); } + /// Export this to [Map] format. Map toMap() { final map = {}; - for (final entry in _entries) { - if (entry.export) { - map[entry.name] = entry.input.value; + for (final input in _inputs) { + if (input.metadata.export) { + map[input.name] = input.validator.value; } } return map; } @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - - return other is FormData && listEquals(other._entries, _entries); - } - + bool? get stringify => true; + @override - int get hashCode => _entries.hashCode; - - @override - String toString() => 'FormData(entries: $_entries)'; + List get props => _inputs; } diff --git a/packages/wyatt_form_bloc/lib/src/form/form_entry.dart b/packages/wyatt_form_bloc/lib/src/form/form_entry.dart deleted file mode 100644 index 017da7c6..00000000 --- a/packages/wyatt_form_bloc/lib/src/form/form_entry.dart +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -import 'package:meta/meta.dart'; -import 'package:wyatt_form_bloc/src/form/form.dart'; - -@immutable -class FormEntry { - const FormEntry(this.key, this.input, {this.export = true, String? name}) - : _field = name ?? key; - - final String key; - final FormInput input; - final bool export; - final String _field; - - String get name => _field; - - FormEntry copyWith({ - String? key, - FormInput? input, - bool? export, - String? name, - }) { - return FormEntry( - key ?? this.key, - input ?? this.input, - export: export ?? this.export, - name: name, - ); - } - - FormEntry clone() { - return FormEntry( - key, - input, - export: export, - name: name, - ); - } - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - - return other is FormEntry && - other.key == key && - other.input == input && - other.export == export && - other.name == name; - } - - @override - int get hashCode { - return key.hashCode ^ - input.hashCode ^ - export.hashCode ^ - name.hashCode; - } - - @override - String toString() { - return 'FormEntry(key: $key, input: $input, ' - 'export: $export, name: $name)'; - } -} diff --git a/packages/wyatt_form_bloc/lib/src/form/form_input.dart b/packages/wyatt_form_bloc/lib/src/form/form_input.dart index d438e4ab..58a2e506 100644 --- a/packages/wyatt_form_bloc/lib/src/form/form_input.dart +++ b/packages/wyatt_form_bloc/lib/src/form/form_input.dart @@ -1,3 +1,4 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first // Copyright (C) 2022 WYATT GROUP // Please see the AUTHORS file for details. // @@ -14,98 +15,45 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import 'package:meta/meta.dart'; -import 'package:wyatt_form_bloc/src/enums/enums.dart'; +part of 'form.dart'; -/// {@template form_input} -/// A [FormInput] represents the value of a single form input field. -/// It contains information about the [FormInputStatus], [value], as well -/// as validation status. -/// -/// [FormInput] should be extended to define custom [FormInput] instances. -/// -/// ```dart -/// enum FirstNameError { empty } -/// class FirstName extends FormInput { -/// const FirstName.pure({String value = ''}) : super.pure(value); -/// const FirstName.dirty({String value = ''}) : super.dirty(value); -/// -/// @override -/// FirstNameError? validator(String value) { -/// return value.isEmpty ? FirstNameError.empty : null; -/// } -/// } -/// ``` -/// {@endtemplate} -@immutable -abstract class FormInput { - const FormInput._(this.value, [this.pure = true]); +class FormInput extends Equatable { + final String key; + final FormInputValidator validator; + final FormInputMetadata metadata; - /// Constructor which create a `pure` [FormInput] with a given value. - const FormInput.pure(T value) : this._(value); + String get name => metadata._name ?? key; - /// Constructor which create a `dirty` [FormInput] with a given value. - const FormInput.dirty(T value) : this._(value, false); - - /// The value of the given [FormInput]. - /// For example, if you have a `FormInput` for `FirstName`, - /// the value could be 'Joe'. - final T value; - - /// If the [FormInput] is pure (has been touched/modified). - /// Typically when the `FormInput` is initially created, - /// it is created using the `FormInput.pure` constructor to - /// signify that the user has not modified it. - /// - /// For subsequent changes (in response to user input), the - /// `FormInput.dirty` constructor should be used to signify that - /// the `FormInput` has been manipulated. - final bool pure; - - /// The [FormInputStatus] which can be one of the following: - /// * [FormInputStatus.pure] - /// - if the input has not been modified. - /// * [FormInputStatus.invalid] - /// - if the input has been modified and validation failed. - /// * [FormInputStatus.valid] - /// - if the input has been modified and validation succeeded. - FormInputStatus get status => pure - ? FormInputStatus.pure - : valid - ? FormInputStatus.valid - : FormInputStatus.invalid; - - /// Returns a validation error if the [FormInput] is invalid. - /// Returns `null` if the [FormInput] is valid. - E? get error => validator(value); - - /// Whether the [FormInput] value is valid according to the - /// overridden `validator`. - /// - /// Returns `true` if `validator` returns `null` for the - /// current [FormInput] value and `false` otherwise. - bool get valid => validator(value) == null; - - /// Whether the [FormInput] value is not valid. - /// A value is invalid when the overridden `validator` - /// returns an error (non-null value). - bool get invalid => status == FormInputStatus.invalid; - - /// A function that must return a validation error if the provided - /// [value] is invalid and `null` otherwise. - E? validator(T value); + const FormInput( + this.key, + this.validator, { + // ignore: avoid_redundant_argument_values + this.metadata = const FormInputMetadata(export: true), + }); @override - int get hashCode => value.hashCode ^ pure.hashCode; + bool? get stringify => true; @override - bool operator ==(Object other) { - if (other.runtimeType != runtimeType) return false; - return other is FormInput && - other.value == value && - other.pure == pure; + List get props => [key, validator, metadata]; + + FormInput copyWith({ + String? key, + FormInputValidator? validator, + FormInputMetadata? metadata, + }) { + return FormInput( + key ?? this.key, + validator ?? this.validator, + metadata: metadata ?? this.metadata, + ); } - @override - String toString() => 'FormInput<$runtimeType>(value: $value, pure: $pure)'; + FormInput clone() { + return copyWith( + key: key, + validator: validator, + metadata: metadata, + ); + } } diff --git a/packages/wyatt_form_bloc/lib/src/form/form_input_metadata.dart b/packages/wyatt_form_bloc/lib/src/form/form_input_metadata.dart new file mode 100644 index 00000000..e8921ef1 --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/form/form_input_metadata.dart @@ -0,0 +1,56 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'form.dart'; + +class FormInputMetadata extends Equatable { + final bool export; + final String? _name; + final T? extra; + + const FormInputMetadata({ + this.export = true, + this.extra, + String? name, + }) : _name = name; + + @override + bool? get stringify => true; + + @override + List get props => [export, _name, extra]; + + FormInputMetadata copyWith({ + bool? export, + String? name, + T? extra, + }) { + return FormInputMetadata( + export: export ?? this.export, + name: name ?? _name, + extra: extra ?? this.extra, + ); + } + + FormInputMetadata clone() { + return copyWith( + export: export, + name: _name, + extra: extra, + ); + } +} diff --git a/packages/wyatt_form_bloc/lib/src/form/form_input_validator.dart b/packages/wyatt_form_bloc/lib/src/form/form_input_validator.dart new file mode 100644 index 00000000..3207762a --- /dev/null +++ b/packages/wyatt_form_bloc/lib/src/form/form_input_validator.dart @@ -0,0 +1,104 @@ +// Copyright (C) 2022 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +part of 'form.dart'; + +/// {@template form_input} +/// A [FormInputValidator] represents the value of a single form input field. +/// It contains information about the [FormInputStatus], [value], as well +/// as validation status. +/// +/// [FormInputValidator] should be extended to define custom +/// [FormInputValidator] instances. +/// +/// ```dart +/// enum FirstNameError { empty } +/// class FirstName extends FormInputValidator { +/// const FirstName.pure({String value = ''}) : super.pure(value); +/// const FirstName.dirty({String value = ''}) : super.dirty(value); +/// +/// @override +/// FirstNameError? validator(String value) { +/// return value.isEmpty ? FirstNameError.empty : null; +/// } +/// } +/// ``` +/// {@endtemplate} +@immutable +abstract class FormInputValidator extends Equatable { + const FormInputValidator._(this.value, [this.pure = true]); + + /// Constructor which create a `pure` [FormInputValidator] with a given value. + const FormInputValidator.pure(V value) : this._(value); + + /// Constructor which create a `dirty` [FormInputValidator] with a + /// given value. + const FormInputValidator.dirty(V value) : this._(value, false); + + /// The value of the given [FormInputValidator]. + /// For example, if you have a `FormInputValidator` for `FirstName`, + /// the value could be 'Joe'. + final V value; + + /// If the [FormInputValidator] is pure (has been touched/modified). + /// Typically when the `FormInputValidator` is initially created, + /// it is created using the `FormInputValidator.pure` constructor to + /// signify that the user has not modified it. + /// + /// For subsequent changes (in response to user input), the + /// `FormInputValidator.dirty` constructor should be used to signify that + /// the `FormInputValidator` has been manipulated. + final bool pure; + + /// The [FormInputStatus] which can be one of the following: + /// * [FormInputStatus.pure] + /// - if the input has not been modified. + /// * [FormInputStatus.invalid] + /// - if the input has been modified and validation failed. + /// * [FormInputStatus.valid] + /// - if the input has been modified and validation succeeded. + FormInputStatus get status => pure + ? FormInputStatus.pure + : valid + ? FormInputStatus.valid + : FormInputStatus.invalid; + + /// Returns a validation error if the [FormInputValidator] is invalid. + /// Returns `null` if the [FormInputValidator] is valid. + E? get error => validator(value); + + /// Whether the [FormInputValidator] value is valid according to the + /// overridden `validator`. + /// + /// Returns `true` if `validator` returns `null` for the + /// current [FormInputValidator] value and `false` otherwise. + bool get valid => validator(value) == null; + + /// Whether the [FormInputValidator] value is not valid. + /// A value is invalid when the overridden `validator` + /// returns an error (non-null value). + bool get invalid => status == FormInputStatus.invalid; + + /// A function that must return a validation error if the provided + /// [value] is invalid and `null` otherwise. + E? validator(V value); + + @override + bool? get stringify => true; + + @override + List get props => [value, pure]; +} diff --git a/packages/wyatt_form_bloc/lib/src/utils/list_equals.dart b/packages/wyatt_form_bloc/lib/src/utils/list_equals.dart deleted file mode 100644 index e7d1989c..00000000 --- a/packages/wyatt_form_bloc/lib/src/utils/list_equals.dart +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2022 WYATT GROUP -// Please see the AUTHORS file for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -bool listEquals(List? a, List? b) { - if (a == null) return b == null; - if (b == null || a.length != b.length) return false; - if (identical(a, b)) return true; - for (int index = 0; index < a.length; index += 1) { - if (a[index] != b[index]) return false; - } - return true; -} diff --git a/packages/wyatt_form_bloc/lib/src/validators/boolean.dart b/packages/wyatt_form_bloc/lib/src/validators/boolean.dart index db03ffe6..30349320 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/boolean.dart +++ b/packages/wyatt_form_bloc/lib/src/validators/boolean.dart @@ -20,7 +20,7 @@ import 'package:wyatt_form_bloc/src/form/form.dart'; /// {@template boolean} /// Form input for a bool input /// {@endtemplate} -class Boolean extends FormInput { +class Boolean extends FormInputValidator { /// {@macro boolean} const Boolean.pure({bool? defaultValue = false}) : super.pure(defaultValue ?? false); diff --git a/packages/wyatt_form_bloc/lib/src/validators/confirmed_password.dart b/packages/wyatt_form_bloc/lib/src/validators/confirmed_password.dart index 3637a5ee..158fef70 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/confirmed_password.dart +++ b/packages/wyatt_form_bloc/lib/src/validators/confirmed_password.dart @@ -21,7 +21,7 @@ import 'package:wyatt_form_bloc/src/form/form.dart'; /// Form input for a confirmed password input. /// {@endtemplate} class ConfirmedPassword - extends FormInput { + extends FormInputValidator { /// {@macro confirmed_password} const ConfirmedPassword.pure({this.password = ''}) : super.pure(''); diff --git a/packages/wyatt_form_bloc/lib/src/validators/email.dart b/packages/wyatt_form_bloc/lib/src/validators/email.dart index 9de7c449..a8192ca6 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/email.dart +++ b/packages/wyatt_form_bloc/lib/src/validators/email.dart @@ -20,7 +20,7 @@ import 'package:wyatt_form_bloc/src/form/form.dart'; /// {@template email} /// Form input for an email input. /// {@endtemplate} -class Email extends FormInput { +class Email extends FormInputValidator { /// {@macro email} const Email.pure() : super.pure(''); @@ -28,7 +28,7 @@ class Email extends FormInput { const Email.dirty([String value = '']) : super.dirty(value); static final RegExp _emailRegExp = RegExp( - r'^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$', + r'[^@ \t\r\n]+@[^@ \t\r\n]+\.[^@ \t\r\n]+', ); @override diff --git a/packages/wyatt_form_bloc/lib/src/validators/iban.dart b/packages/wyatt_form_bloc/lib/src/validators/iban.dart index 301c1bcc..64b98665 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/iban.dart +++ b/packages/wyatt_form_bloc/lib/src/validators/iban.dart @@ -20,7 +20,7 @@ import 'package:wyatt_form_bloc/src/form/form.dart'; /// {@template iban} /// Form input for an IBAN input. /// {@endtemplate} -class Iban extends FormInput { +class Iban extends FormInputValidator { /// {@macro iban} const Iban.pure() : super.pure(''); diff --git a/packages/wyatt_form_bloc/lib/src/validators/list_option.dart b/packages/wyatt_form_bloc/lib/src/validators/list_option.dart index 13c7dc5c..d021223a 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/list_option.dart +++ b/packages/wyatt_form_bloc/lib/src/validators/list_option.dart @@ -20,7 +20,7 @@ import 'package:wyatt_form_bloc/src/form/form.dart'; /// {@template list_option} /// Form input for a list input /// {@endtemplate} -class ListOption extends FormInput, ValidationError> { +class ListOption extends FormInputValidator, ValidationError> { /// {@macro list_option} const ListOption.pure({List? defaultValue}) : super.pure(defaultValue ?? const []); diff --git a/packages/wyatt_form_bloc/lib/src/validators/name.dart b/packages/wyatt_form_bloc/lib/src/validators/name.dart index 952c6353..860a3b48 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/name.dart +++ b/packages/wyatt_form_bloc/lib/src/validators/name.dart @@ -20,7 +20,7 @@ import 'package:wyatt_form_bloc/src/form/form.dart'; /// {@template name} /// Form input for a name input. /// {@endtemplate} -class Name extends FormInput { +class Name extends FormInputValidator { /// {@macro name} const Name.pure() : super.pure(''); diff --git a/packages/wyatt_form_bloc/lib/src/validators/password.dart b/packages/wyatt_form_bloc/lib/src/validators/password.dart index f897c9f6..b9ee5fe1 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/password.dart +++ b/packages/wyatt_form_bloc/lib/src/validators/password.dart @@ -20,7 +20,7 @@ import 'package:wyatt_form_bloc/src/form/form.dart'; /// {@template password} /// Form input for a password input. /// {@endtemplate} -class Password extends FormInput { +class Password extends FormInputValidator { /// {@macro password} const Password.pure() : super.pure(''); diff --git a/packages/wyatt_form_bloc/lib/src/validators/phone.dart b/packages/wyatt_form_bloc/lib/src/validators/phone.dart index ba009760..8a63cc2e 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/phone.dart +++ b/packages/wyatt_form_bloc/lib/src/validators/phone.dart @@ -20,7 +20,7 @@ import 'package:wyatt_form_bloc/src/form/form.dart'; /// {@template phone} /// Form input for a phone input. /// {@endtemplate} -class Phone extends FormInput { +class Phone extends FormInputValidator { /// {@macro phone} const Phone.pure() : super.pure(''); diff --git a/packages/wyatt_form_bloc/lib/src/validators/siren.dart b/packages/wyatt_form_bloc/lib/src/validators/siren.dart index e0cea358..811fb4bd 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/siren.dart +++ b/packages/wyatt_form_bloc/lib/src/validators/siren.dart @@ -20,7 +20,7 @@ import 'package:wyatt_form_bloc/src/form/form.dart'; /// {@template siren} /// Form input for a SIREN input. /// {@endtemplate} -class Siren extends FormInput { +class Siren extends FormInputValidator { /// {@macro siren} const Siren.pure() : super.pure(''); diff --git a/packages/wyatt_form_bloc/lib/src/validators/text_string.dart b/packages/wyatt_form_bloc/lib/src/validators/text_string.dart index 89ce6427..230f69e4 100644 --- a/packages/wyatt_form_bloc/lib/src/validators/text_string.dart +++ b/packages/wyatt_form_bloc/lib/src/validators/text_string.dart @@ -20,7 +20,7 @@ import 'package:wyatt_form_bloc/src/form/form.dart'; /// {@template text_string} /// Form input for a text input /// {@endtemplate} -class TextString extends FormInput { +class TextString extends FormInputValidator { /// {@macro text_string} const TextString.pure() : super.pure(''); diff --git a/packages/wyatt_form_bloc/pubspec.yaml b/packages/wyatt_form_bloc/pubspec.yaml index 8e6d0342..9232a917 100644 --- a/packages/wyatt_form_bloc/pubspec.yaml +++ b/packages/wyatt_form_bloc/pubspec.yaml @@ -4,14 +4,15 @@ repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/mas version: 0.0.2 environment: - sdk: '>=2.16.2 <3.0.0' + sdk: '>=2.17.2 <3.0.0' dependencies: bloc: ^8.0.3 + equatable: ^2.0.3 meta: ^1.7.0 dev_dependencies: - test: ^1.21.0 + test: ^1.21.4 wyatt_analysis: git: