feat!(form): migrate to wyatt architecture
This commit is contained in:
parent
79fdd3c837
commit
b89ef3de8a
@ -16,16 +16,16 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
# Dart - Form BLoC
|
||||
# Flutter - Form BLoC
|
||||
|
||||
<p align="left">
|
||||
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis">
|
||||
<img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" />
|
||||
</a>
|
||||
<img src="https://img.shields.io/badge/SDK-Dart%20%7C%20Flutter-blue?style=flat-square" alt="SDK: Dart & Flutter" />
|
||||
<img src="https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square" alt="SDK: Flutter" />
|
||||
</p>
|
||||
|
||||
Form Bloc for Dart & Flutter.
|
||||
Form Bloc for Flutter.
|
||||
|
||||
## Features
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
include: package:wyatt_analysis/analysis_options.yaml
|
||||
include: package:wyatt_analysis/analysis_options.flutter.yaml
|
||||
|
||||
analyzer:
|
||||
exclude: "!example/**"
|
@ -21,6 +21,6 @@
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>9.0</string>
|
||||
<string>11.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -272,7 +272,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@ -349,7 +349,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -398,7 +398,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
@ -43,5 +43,7 @@
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -18,7 +18,7 @@ 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/simple_custom_form_cubit/simple_custom_form_cubit.dart';
|
||||
import 'package:form_bloc_example/sign_up/sign_up_page.dart';
|
||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||
|
||||
@ -29,41 +29,43 @@ class App extends StatelessWidget {
|
||||
const App({Key? key}) : super(key: key);
|
||||
|
||||
static List<FormInput> getNormalEntries() {
|
||||
return const [
|
||||
FormInput(formFieldName, Name.pure(), metadata: FormInputMetadata<Metadata>(extra: blue)),
|
||||
FormInput(formFieldEmail, Email.pure(), metadata: FormInputMetadata<Metadata>(extra: blue)),
|
||||
FormInput(formFieldPhone, Phone.pure(), metadata: FormInputMetadata<Metadata>(extra: red)),
|
||||
FormInput(
|
||||
formFieldList, ListOption<String>.pure(defaultValue: ['checkbox3'])),
|
||||
FormInput(formFieldRadio, TextString.pure()),
|
||||
FormInput(formFieldPro, Boolean.pure(),
|
||||
metadata: FormInputMetadata<Metadata>(name: 'business')),
|
||||
FormInput(formFieldHidden, Boolean.pure(),
|
||||
metadata: FormInputMetadata<Metadata>(export: false, extra: blue)),
|
||||
return [
|
||||
FormInput(formFieldName, const Name.pure(),
|
||||
metadata: const FormInputMetadata<Metadata>(extra: blue)),
|
||||
FormInput(formFieldEmail, const Email.pure(),
|
||||
metadata: const FormInputMetadata<Metadata>(extra: blue)),
|
||||
FormInput(formFieldList,
|
||||
const ListOption<String>.pure(defaultValue: 'c3')),
|
||||
FormInput(formFieldRadio, const TextString.pure()),
|
||||
FormInput(formFieldPro, const Boolean.pure(),
|
||||
metadata: const FormInputMetadata<Metadata>(name: 'business')),
|
||||
FormInput(formFieldHidden, const Boolean.pure(),
|
||||
metadata:
|
||||
const FormInputMetadata<Metadata>(export: false, extra: blue)),
|
||||
];
|
||||
}
|
||||
|
||||
static List<FormInput> getBusinessEntries() {
|
||||
const entries = [
|
||||
FormInput(formFieldSiren, Siren.pure()),
|
||||
FormInput(formFieldIban, Iban.pure()),
|
||||
final entries = [
|
||||
FormInput(formFieldPhone, const Phone.pure(),
|
||||
metadata: const FormInputMetadata<Metadata>(extra: red)),
|
||||
];
|
||||
return getNormalEntries() + entries;
|
||||
}
|
||||
|
||||
static FormData getNormalFormData() {
|
||||
return FormData(getNormalEntries());
|
||||
static WyattForm getNormalFormData() {
|
||||
return WyattFormImpl(getNormalEntries());
|
||||
}
|
||||
|
||||
static FormData getProFormData() {
|
||||
return FormData(getBusinessEntries());
|
||||
static WyattForm getProFormData() {
|
||||
return WyattFormImpl(getBusinessEntries());
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
FormDataCubit formCubit = CustomFormCubit(inputs: getNormalFormData());
|
||||
SimpleCustomFormCubit formCubit = SimpleCustomFormCubit(getNormalFormData());
|
||||
|
||||
return BlocProvider(
|
||||
return BlocProvider<SimpleCustomFormCubit>(
|
||||
create: (context) => formCubit,
|
||||
child: const WidgetTree(),
|
||||
);
|
||||
|
@ -28,7 +28,5 @@ class Metadata {
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return category.toString();
|
||||
}
|
||||
String toString() => 'Metadata(category: $category)';
|
||||
}
|
||||
|
@ -17,8 +17,6 @@
|
||||
const String formFieldName = 'name';
|
||||
const String formFieldPhone = 'phone';
|
||||
const String formFieldEmail = 'email';
|
||||
const String formFieldSiren = 'siren';
|
||||
const String formFieldIban = 'iban';
|
||||
const String formFieldList = 'list';
|
||||
const String formFieldRadio = 'radio';
|
||||
const String formFieldHidden = 'hidden';
|
||||
|
@ -14,39 +14,33 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
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:form_bloc_example/simple_custom_form_cubit/simple_custom_form_cubit.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;
|
||||
}
|
||||
Color computeColor(Metadata? meta) {
|
||||
switch (meta?.category) {
|
||||
case Category.perso:
|
||||
return Colors.blue;
|
||||
case Category.business:
|
||||
return Colors.red;
|
||||
case null:
|
||||
return Colors.green;
|
||||
}
|
||||
}
|
||||
|
||||
class _NameInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<FormDataCubit, FormDataState>(
|
||||
builder: ((context, state) {
|
||||
final meta = state.data.metadataOf(field).extra as Metadata;
|
||||
return InputBuilderMetadata<SimpleCustomFormCubit, Metadata>(
|
||||
field: formFieldName,
|
||||
builder: (context, cubit, state, field, inputValid, metadata) {
|
||||
final meta = state.form.metadataOf<Metadata>(field).extra;
|
||||
final color = computeColor(meta);
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
Container(
|
||||
@ -57,58 +51,24 @@ class CategoryIndicator extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20,),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width - 45,
|
||||
child: builder(context, state),
|
||||
child: TextField(
|
||||
onChanged: (value) =>
|
||||
cubit.dataChanged(field, Name.dirty(value)),
|
||||
keyboardType: TextInputType.name,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'name',
|
||||
helperText: '',
|
||||
errorText: !inputValid ? 'invalid name' : null,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _NameInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CategoryIndicator(
|
||||
field: formFieldName,
|
||||
builder: (context, state) {
|
||||
return TextField(
|
||||
onChanged: (name) => context
|
||||
.read<FormDataCubit>()
|
||||
.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 CategoryIndicator(
|
||||
field: formFieldEmail,
|
||||
builder: (context, state) {
|
||||
return TextField(
|
||||
onChanged: (email) => context
|
||||
.read<FormDataCubit>()
|
||||
.dataChanged(formFieldEmail, Email.dirty(email)),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'email',
|
||||
helperText: '',
|
||||
errorText:
|
||||
state.data.isNotValid(formFieldEmail) ? 'invalid email' : null,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -117,67 +77,58 @@ class _EmailInput extends StatelessWidget {
|
||||
class _PhoneInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CategoryIndicator(
|
||||
field: formFieldPhone,
|
||||
builder: (context, state) {
|
||||
return TextField(
|
||||
onChanged: (phone) => context
|
||||
.read<FormDataCubit>()
|
||||
.dataChanged(formFieldPhone, Phone.dirty(phone)),
|
||||
keyboardType: TextInputType.phone,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'phone',
|
||||
helperText: '',
|
||||
errorText:
|
||||
state.data.isNotValid(formFieldPhone) ? 'invalid phone' : null,
|
||||
),
|
||||
return InputBuilderMetadata<SimpleCustomFormCubit, Metadata>(
|
||||
field: formFieldPhone,
|
||||
builder: (context, cubit, state, field, inputValid, metadata) {
|
||||
final meta = state.form.metadataOf<Metadata>(field).extra;
|
||||
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: TextField(
|
||||
onChanged: (value) =>
|
||||
cubit.dataChanged(field, Phone.dirty(value)),
|
||||
keyboardType: TextInputType.phone,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'phone',
|
||||
helperText: '',
|
||||
errorText: !inputValid ? 'invalid phone' : null,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SirenInput extends StatelessWidget {
|
||||
class _EmailInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CategoryIndicator(
|
||||
field: formFieldName,
|
||||
builder: (context, state) {
|
||||
return TextField(
|
||||
onChanged: (siren) => context
|
||||
.read<FormDataCubit>()
|
||||
.dataChanged(formFieldSiren, Siren.dirty(siren)),
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'siren',
|
||||
helperText: '',
|
||||
errorText:
|
||||
state.data.isNotValid(formFieldSiren) ? 'invalid SIREN' : null,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _IbanInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<FormDataCubit, FormDataState>(
|
||||
builder: (context, state) {
|
||||
return TextField(
|
||||
onChanged: (iban) => context
|
||||
.read<FormDataCubit>()
|
||||
.dataChanged(formFieldIban, Iban.dirty(iban)),
|
||||
keyboardType: TextInputType.text,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'iban',
|
||||
helperText: '',
|
||||
errorText:
|
||||
state.data.isNotValid(formFieldIban) ? 'invalid IBAN' : null,
|
||||
),
|
||||
);
|
||||
},
|
||||
return InputBuilder<SimpleCustomFormCubit>(
|
||||
field: formFieldEmail,
|
||||
builder: (context, cubit, state, field, inputValid) => TextField(
|
||||
onChanged: (value) => cubit.dataChanged(field, Email.dirty(value)),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'email',
|
||||
helperText: '',
|
||||
errorText: !inputValid ? 'invalid email' : null,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -185,11 +136,11 @@ class _IbanInput extends StatelessWidget {
|
||||
class _CheckListInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<FormDataCubit, FormDataState>(
|
||||
builder: (context, state) {
|
||||
final input =
|
||||
state.data.validatorOf<ListOption<String>>(formFieldList);
|
||||
final options = input.value;
|
||||
return InputBuilder<SimpleCustomFormCubit>(
|
||||
field: formFieldList,
|
||||
builder: (context, cubit, state, field, inputValid) {
|
||||
final input = state.form.validatorOf<ListOption<String>>(field);
|
||||
final choices = ['c1', 'c2', 'c3'];
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@ -197,34 +148,34 @@ class _CheckListInput extends StatelessWidget {
|
||||
ListTile(
|
||||
title: const Text('Checkbox1'),
|
||||
trailing: Checkbox(
|
||||
value: options.contains('checkbox1'),
|
||||
value: input.value == choices[0],
|
||||
onChanged: (_) {
|
||||
context.read<FormDataCubit>().dataChanged(
|
||||
formFieldList,
|
||||
input.select('checkbox1'),
|
||||
);
|
||||
cubit.dataChanged(
|
||||
field,
|
||||
ListOption.dirty(choices: choices, value: choices[0]),
|
||||
);
|
||||
}),
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('Checkbox2'),
|
||||
trailing: Checkbox(
|
||||
value: options.contains('checkbox2'),
|
||||
value: input.value == choices[1],
|
||||
onChanged: (_) {
|
||||
context.read<FormDataCubit>().dataChanged(
|
||||
formFieldList,
|
||||
input.select('checkbox2'),
|
||||
);
|
||||
cubit.dataChanged(
|
||||
field,
|
||||
ListOption.dirty(choices: choices, value: choices[1]),
|
||||
);
|
||||
}),
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('Checkbox3 (default)'),
|
||||
trailing: Checkbox(
|
||||
value: options.contains('checkbox3'),
|
||||
value: input.value == choices[2],
|
||||
onChanged: (_) {
|
||||
context.read<FormDataCubit>().dataChanged(
|
||||
formFieldList,
|
||||
input.select('checkbox3'),
|
||||
);
|
||||
cubit.dataChanged(
|
||||
field,
|
||||
ListOption.dirty(choices: choices, value: choices[2]),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
@ -237,9 +188,10 @@ class _CheckListInput extends StatelessWidget {
|
||||
class _RadioListInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<FormDataCubit, FormDataState>(
|
||||
builder: (context, state) {
|
||||
final input = state.data.validatorOf<TextString>(formFieldRadio);
|
||||
return InputBuilder<SimpleCustomFormCubit>(
|
||||
field: formFieldRadio,
|
||||
builder: ((context, cubit, state, field, inputValid) {
|
||||
final input = state.form.validatorOf<TextString>(field);
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@ -250,10 +202,10 @@ class _RadioListInput extends StatelessWidget {
|
||||
groupValue: true,
|
||||
value: input.value == 'radio1',
|
||||
onChanged: (_) {
|
||||
context.read<FormDataCubit>().dataChanged(
|
||||
formFieldRadio,
|
||||
const TextString.dirty('radio1'),
|
||||
);
|
||||
cubit.dataChanged(
|
||||
field,
|
||||
const TextString.dirty('radio1'),
|
||||
);
|
||||
}),
|
||||
),
|
||||
ListTile(
|
||||
@ -262,10 +214,10 @@ class _RadioListInput extends StatelessWidget {
|
||||
groupValue: true,
|
||||
value: input.value == 'radio2',
|
||||
onChanged: (_) {
|
||||
context.read<FormDataCubit>().dataChanged(
|
||||
formFieldRadio,
|
||||
const TextString.dirty('radio2'),
|
||||
);
|
||||
cubit.dataChanged(
|
||||
field,
|
||||
const TextString.dirty('radio2'),
|
||||
);
|
||||
}),
|
||||
),
|
||||
ListTile(
|
||||
@ -274,15 +226,15 @@ class _RadioListInput extends StatelessWidget {
|
||||
groupValue: true,
|
||||
value: input.value == 'radio3',
|
||||
onChanged: (_) {
|
||||
context.read<FormDataCubit>().dataChanged(
|
||||
formFieldRadio,
|
||||
const TextString.dirty('radio3'),
|
||||
);
|
||||
cubit.dataChanged(
|
||||
field,
|
||||
const TextString.dirty('radio3'),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -292,17 +244,18 @@ class _CheckHiddenInput extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
title: const Text('This input is not exported'),
|
||||
trailing: BlocBuilder<FormDataCubit, FormDataState>(
|
||||
builder: (context, state) {
|
||||
trailing: InputBuilder<SimpleCustomFormCubit>(
|
||||
field: formFieldHidden,
|
||||
builder: (context, cubit, state, field, inputValid) {
|
||||
return Checkbox(
|
||||
value: state.data.validatorOf<Boolean>(formFieldHidden).value,
|
||||
value: state.form.validatorOf<Boolean>(field).value,
|
||||
onChanged: (v) {
|
||||
final value = v!; // state is false, so value can't be null
|
||||
|
||||
context.read<FormDataCubit>().dataChanged(
|
||||
formFieldHidden,
|
||||
Boolean.dirty(value: value),
|
||||
);
|
||||
cubit.dataChanged(
|
||||
field,
|
||||
Boolean.dirty(value: value),
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
@ -315,25 +268,24 @@ class _CheckIsProInput extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
title: const Text('Are you a pro?'),
|
||||
trailing: BlocBuilder<FormDataCubit, FormDataState>(
|
||||
builder: (context, state) {
|
||||
trailing: InputBuilder<SimpleCustomFormCubit>(
|
||||
field: formFieldPro,
|
||||
builder: (context, cubit, state, field, inputValid) {
|
||||
return Checkbox(
|
||||
value: state.data.validatorOf<Boolean>(formFieldPro).value,
|
||||
onChanged: (isPro) {
|
||||
final value = isPro!; // state is false, so value can't be null
|
||||
value: state.form.validatorOf<Boolean>(field).value,
|
||||
onChanged: (v) {
|
||||
final value = v!; // state is false, so value can't be null
|
||||
|
||||
context.read<FormDataCubit>().dataChanged(
|
||||
formFieldPro,
|
||||
Boolean.dirty(value: value),
|
||||
);
|
||||
cubit.dataChanged(
|
||||
field,
|
||||
Boolean.dirty(value: value),
|
||||
);
|
||||
|
||||
if (value) {
|
||||
context.read<FormDataCubit>().updateFormData(
|
||||
App.getProFormData(),
|
||||
cubit.update(App.getProFormData(),
|
||||
operation: SetOperation.union);
|
||||
} else {
|
||||
context.read<FormDataCubit>().updateFormData(
|
||||
App.getNormalFormData(),
|
||||
cubit.update(App.getNormalFormData(),
|
||||
operation: SetOperation.intersection);
|
||||
}
|
||||
});
|
||||
@ -346,49 +298,28 @@ class _CheckIsProInput extends StatelessWidget {
|
||||
class _SignUpButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<FormDataCubit, FormDataState>(
|
||||
buildWhen: (previous, current) => previous.status != current.status,
|
||||
builder: (context, state) {
|
||||
return state.status.isSubmissionInProgress
|
||||
? const CircularProgressIndicator()
|
||||
: ElevatedButton(
|
||||
onPressed: state.status.isValidated
|
||||
? () => context.read<FormDataCubit>().submitForm()
|
||||
: null,
|
||||
child: const Text('SIGN UP'),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DebugButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<FormDataCubit, FormDataState>(
|
||||
builder: (context, state) {
|
||||
return ElevatedButton(
|
||||
onPressed: () {
|
||||
log(state.toString());
|
||||
},
|
||||
child: const Text('DEBUG'),
|
||||
);
|
||||
},
|
||||
);
|
||||
return SubmitBuilder<SimpleCustomFormCubit>(
|
||||
builder: (context, cubit, status) {
|
||||
return status.isSubmissionInProgress
|
||||
? const CircularProgressIndicator()
|
||||
: ElevatedButton(
|
||||
onPressed: status.isValidated ? () => cubit.submit() : null,
|
||||
child: const Text('SIGN UP'),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class _ResetButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<FormDataCubit, FormDataState>(
|
||||
builder: (context, state) {
|
||||
return ElevatedButton(
|
||||
onPressed: () => context.read<FormDataCubit>().resetForm(),
|
||||
child: const Text('RESET'),
|
||||
);
|
||||
},
|
||||
);
|
||||
return SubmitBuilder<SimpleCustomFormCubit>(
|
||||
builder: (context, cubit, status) {
|
||||
return ElevatedButton(
|
||||
onPressed: () => cubit.reset(),
|
||||
child: const Text('RESET'),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -397,7 +328,7 @@ class SignUpForm extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocListener<FormDataCubit, FormDataState>(
|
||||
return BlocListener<SimpleCustomFormCubit, FormDataState>(
|
||||
listener: (context, state) {
|
||||
if (state.status.isSubmissionSuccess) {
|
||||
Navigator.of(context).pop(); // Never happens here
|
||||
@ -418,8 +349,6 @@ class SignUpForm extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
_EmailInput(),
|
||||
const SizedBox(height: 8),
|
||||
_PhoneInput(),
|
||||
const SizedBox(height: 8),
|
||||
_CheckListInput(),
|
||||
const SizedBox(height: 8),
|
||||
_RadioListInput(),
|
||||
@ -428,13 +357,12 @@ class SignUpForm extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
_CheckIsProInput(),
|
||||
const SizedBox(height: 8),
|
||||
BlocBuilder<FormDataCubit, FormDataState>(
|
||||
BlocBuilder<SimpleCustomFormCubit, FormDataState>(
|
||||
builder: (context, state) {
|
||||
if (state.data.validatorOf<Boolean>(formFieldPro).value) {
|
||||
if (state.form.validatorOf<Boolean>(formFieldPro).value ??
|
||||
false) {
|
||||
return Column(children: [
|
||||
_SirenInput(),
|
||||
const SizedBox(height: 8),
|
||||
_IbanInput(),
|
||||
_PhoneInput(),
|
||||
const SizedBox(height: 8),
|
||||
]);
|
||||
}
|
||||
@ -444,8 +372,6 @@ class SignUpForm extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
_SignUpButton(),
|
||||
const SizedBox(height: 8),
|
||||
_DebugButton(),
|
||||
const SizedBox(height: 8),
|
||||
_ResetButton(),
|
||||
],
|
||||
),
|
||||
|
@ -18,12 +18,13 @@ import 'dart:developer';
|
||||
|
||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||
|
||||
class CustomFormCubit extends FormDataCubit {
|
||||
CustomFormCubit({required FormData inputs}) : super(inputs: inputs);
|
||||
class SimpleCustomFormCubit extends FormDataCubitImpl {
|
||||
SimpleCustomFormCubit(super.form) : super();
|
||||
|
||||
@override
|
||||
Future<void> submitForm() {
|
||||
log(state.data.toMap().toString());
|
||||
Future<void> submit() {
|
||||
final value = FormJsonEncoder().encode(state.form);
|
||||
log(value);
|
||||
|
||||
return Future.value();
|
||||
}
|
@ -14,17 +14,4 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
export 'form/every_input_validator.dart';
|
||||
export 'inputs/base/regex_validator.dart';
|
||||
export 'inputs/base/text_validator.dart';
|
||||
export 'inputs/boolean.dart';
|
||||
export 'inputs/confirmed_password.dart';
|
||||
export 'inputs/email.dart';
|
||||
export 'inputs/enum_validator.dart';
|
||||
export 'inputs/iban.dart';
|
||||
export 'inputs/list_option.dart';
|
||||
export 'inputs/name.dart';
|
||||
export 'inputs/password.dart';
|
||||
export 'inputs/phone.dart';
|
||||
export 'inputs/siren.dart';
|
||||
export 'inputs/text_string.dart';
|
||||
export 'enums/enums.dart';
|
@ -0,0 +1,39 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/data/form_operations/form_difference.dart';
|
||||
import 'package:wyatt_form_bloc/src/data/form_operations/form_intersection.dart';
|
||||
import 'package:wyatt_form_bloc/src/data/form_operations/form_replace.dart';
|
||||
import 'package:wyatt_form_bloc/src/data/form_operations/form_union.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart';
|
||||
|
||||
enum SetOperation {
|
||||
/// Replace entire set with new set.
|
||||
replace(FormReplace()),
|
||||
|
||||
/// Keep common elements between sets.
|
||||
intersection(FormIntersection()),
|
||||
|
||||
/// Remove common elements between sets.
|
||||
difference(FormDifference()),
|
||||
|
||||
/// Add new elements to set.
|
||||
union(FormUnion());
|
||||
|
||||
final FormOperation operation;
|
||||
|
||||
const SetOperation(this.operation);
|
||||
}
|
@ -23,5 +23,6 @@ abstract class ValidationError {}
|
||||
|
||||
enum ValidationStandardError implements ValidationError {
|
||||
invalid,
|
||||
empty
|
||||
empty,
|
||||
notEqual,
|
||||
}
|
@ -1,110 +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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.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/validators/form/every_input_validator.dart';
|
||||
|
||||
part 'form_data_state.dart';
|
||||
|
||||
abstract class FormDataCubit extends Cubit<FormDataState> {
|
||||
FormValidator validationStrategy;
|
||||
FormData formCopy;
|
||||
|
||||
FormDataCubit({
|
||||
required FormData inputs,
|
||||
FormValidator validator = const EveryInputValidator(),
|
||||
}) : formCopy = inputs.clone(),
|
||||
validationStrategy = validator,
|
||||
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. (Wrapped in a dirty validator)
|
||||
void dataChanged<V>(
|
||||
String field,
|
||||
FormInputValidator<V, ValidationError> dirtyValue,
|
||||
) {
|
||||
final form = state.data.clone();
|
||||
|
||||
if (form.contains(field)) {
|
||||
form.updateValidator(field, dirtyValue);
|
||||
} else {
|
||||
throw Exception('Form field $field not found');
|
||||
}
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
data: form,
|
||||
status: validationStrategy.validate(form),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Just validate the form manually. (Useful if you just update the strategy)
|
||||
void validate() {
|
||||
final form = state.data;
|
||||
emit(state.copyWith(status: validationStrategy.validate(form)));
|
||||
}
|
||||
|
||||
/// Update entries list.
|
||||
///
|
||||
/// Inputs:
|
||||
/// - `data`: The new entries list.
|
||||
/// - `operation`: The operation to perform on the entries set.
|
||||
void updateFormData(
|
||||
FormData data, {
|
||||
SetOperation operation = SetOperation.replace,
|
||||
}) {
|
||||
FormData form = data;
|
||||
|
||||
switch (operation) {
|
||||
case SetOperation.replace:
|
||||
form = data;
|
||||
break;
|
||||
case SetOperation.difference:
|
||||
form = state.data.difference(data);
|
||||
break;
|
||||
case SetOperation.intersection:
|
||||
form = state.data.intersection(data);
|
||||
break;
|
||||
case SetOperation.union:
|
||||
form = state.data.union(data);
|
||||
break;
|
||||
}
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
data: form,
|
||||
status: validationStrategy.validate(form),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Reset all form inputs
|
||||
void resetForm() {
|
||||
emit(FormDataState(data: formCopy));
|
||||
}
|
||||
|
||||
/// Submit the form.
|
||||
Future<void> submitForm();
|
||||
}
|
34
packages/wyatt_form_bloc/lib/src/data/data.dart
Normal file
34
packages/wyatt_form_bloc/lib/src/data/data.dart
Normal file
@ -0,0 +1,34 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
export 'form/wyatt_form_impl.dart';
|
||||
export 'form_encoders/form_json_encoder.dart';
|
||||
export 'form_encoders/form_map_encoder.dart';
|
||||
export 'form_operations/form_difference.dart';
|
||||
export 'form_operations/form_intersection.dart';
|
||||
export 'form_operations/form_replace.dart';
|
||||
export 'form_operations/form_union.dart';
|
||||
export 'form_validators/every_input_validator.dart';
|
||||
export 'form_validators/only_required_input_validator.dart';
|
||||
export 'input_validators/boolean.dart';
|
||||
export 'input_validators/confirmed_password.dart';
|
||||
export 'input_validators/email.dart';
|
||||
export 'input_validators/enum_option.dart';
|
||||
export 'input_validators/list_option.dart';
|
||||
export 'input_validators/name.dart';
|
||||
export 'input_validators/password.dart';
|
||||
export 'input_validators/phone.dart';
|
||||
export 'input_validators/text_string.dart';
|
136
packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart
Normal file
136
packages/wyatt_form_bloc/lib/src/data/form/wyatt_form_impl.dart
Normal file
@ -0,0 +1,136 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/core/enums/form_status.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/data/form_validators/every_input_validator.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class WyattFormImpl extends WyattForm {
|
||||
final List<
|
||||
FormInput<dynamic, FormInputValidator<dynamic, ValidationError>,
|
||||
dynamic>> _inputs;
|
||||
final FormValidator _validator;
|
||||
|
||||
late List<
|
||||
FormInput<dynamic, FormInputValidator<dynamic, ValidationError>,
|
||||
dynamic>> _inputsInitial;
|
||||
|
||||
WyattFormImpl(
|
||||
this._inputs, {
|
||||
FormValidator validationStrategy = const EveryInputValidator(),
|
||||
}) : _validator = validationStrategy {
|
||||
_inputsInitial = _inputs.map((input) => input.clone()).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
List<
|
||||
FormInput<dynamic, FormInputValidator<dynamic, ValidationError>,
|
||||
dynamic>> get inputs => _inputs;
|
||||
|
||||
@override
|
||||
FormValidator get formValidationStrategy => _validator;
|
||||
|
||||
@override
|
||||
bool containsKey(String key) => inputs.any((input) => input.key == key);
|
||||
|
||||
@override
|
||||
List<FormInputValidator<Value, Error>>
|
||||
asValidatorList<Value, Error extends ValidationError>() => inputs
|
||||
.map<FormInputValidator<Value, Error>>(
|
||||
(input) => input.validator as FormInputValidator<Value, Error>,
|
||||
)
|
||||
.toList();
|
||||
|
||||
@override
|
||||
FormInput<dynamic, FormInputValidator<dynamic, ValidationError>, dynamic>
|
||||
inputOf(String key) {
|
||||
if (containsKey(key)) {
|
||||
return inputs.firstWhere((input) => input.key == key);
|
||||
} else {
|
||||
throw Exception('FormInput with key `$key` does not exist in form');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Error? errorOf<Error extends ValidationError>(String key) =>
|
||||
(inputOf(key).validator as FormInputValidator<dynamic, Error>).error;
|
||||
|
||||
@override
|
||||
FormInputMetadata<Extra> metadataOf<Extra>(String key) =>
|
||||
inputOf(key).metadata as FormInputMetadata<Extra>;
|
||||
|
||||
@override
|
||||
Validator validatorOf<
|
||||
Validator extends FormInputValidator<dynamic, ValidationError>>(
|
||||
String key,
|
||||
) =>
|
||||
inputOf(key).validator as Validator;
|
||||
|
||||
@override
|
||||
Value? valueOf<Value>(String key) =>
|
||||
(inputOf(key).validator as FormInputValidator<Value, dynamic>).value;
|
||||
|
||||
@override
|
||||
FormStatus validate() => formValidationStrategy.validate(this);
|
||||
|
||||
@override
|
||||
WyattForm clone() => WyattFormImpl(
|
||||
_inputs.map((input) => input.clone()).toList(),
|
||||
validationStrategy: formValidationStrategy,
|
||||
);
|
||||
|
||||
@override
|
||||
WyattForm reset() => WyattFormImpl(
|
||||
_inputsInitial,
|
||||
validationStrategy: formValidationStrategy,
|
||||
);
|
||||
|
||||
@override
|
||||
bool? get stringify => true;
|
||||
|
||||
@override
|
||||
List<Object?> get props => _inputs;
|
||||
|
||||
@override
|
||||
void updateMetadata<Extra>(String key, FormInputMetadata<Extra> metadata) {
|
||||
final index = _inputs.indexOf(
|
||||
inputOf(key),
|
||||
);
|
||||
_inputs[index] = _inputs[index].copyWith(metadata: metadata);
|
||||
}
|
||||
|
||||
@override
|
||||
void updateValidator<Value>(
|
||||
String key,
|
||||
FormInputValidator<Value?, ValidationError> dirtyValue,
|
||||
) {
|
||||
final index = _inputs.indexOf(
|
||||
inputOf(key),
|
||||
);
|
||||
_inputs[index] = _inputs[index].copyWith(validator: dirtyValue);
|
||||
}
|
||||
|
||||
@override
|
||||
WyattForm operationWith(FormOperation operation, WyattForm other) =>
|
||||
operation.call(this, other);
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:wyatt_form_bloc/src/data/form_encoders/form_map_encoder.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_encoders/form_encoder.dart';
|
||||
|
||||
class FormJsonEncoder extends FormEncoder<String> {
|
||||
@override
|
||||
String encode(WyattForm form) {
|
||||
final mapEncoder = FormMapEncoder();
|
||||
final map = mapEncoder.encode(form);
|
||||
return jsonEncode(map);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_encoders/form_encoder.dart';
|
||||
|
||||
class FormMapEncoder extends FormEncoder<Map<String, dynamic>> {
|
||||
@override
|
||||
Map<String, dynamic> encode(WyattForm form) {
|
||||
final inputs = form.inputs;
|
||||
final map = <String, dynamic>{};
|
||||
for (final input in inputs) {
|
||||
if (input.metadata.export) {
|
||||
map[input.name] = input.validator.value;
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/data/form/wyatt_form_impl.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
class FormDifference extends FormOperation {
|
||||
const FormDifference();
|
||||
|
||||
@override
|
||||
WyattForm call(WyattForm a, WyattForm b) {
|
||||
final inputs = <
|
||||
FormInput<dynamic, FormInputValidator<dynamic, ValidationError>,
|
||||
dynamic>>[];
|
||||
|
||||
for (final i in b.inputs) {
|
||||
if (!a.containsKey(i.key)) {
|
||||
inputs.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (final i in a.inputs) {
|
||||
if (!b.containsKey(i.key)) {
|
||||
inputs.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return WyattFormImpl(
|
||||
inputs,
|
||||
validationStrategy: a.formValidationStrategy,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/data/form/wyatt_form_impl.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
class FormIntersection extends FormOperation {
|
||||
const FormIntersection();
|
||||
|
||||
@override
|
||||
WyattForm call(WyattForm a, WyattForm b) {
|
||||
final inputs = <
|
||||
FormInput<dynamic, FormInputValidator<dynamic, ValidationError>,
|
||||
dynamic>>[];
|
||||
|
||||
for (final i in a.inputs) {
|
||||
if (b.containsKey(i.key)) {
|
||||
inputs.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return WyattFormImpl(
|
||||
inputs,
|
||||
validationStrategy: a.formValidationStrategy,
|
||||
);
|
||||
}
|
||||
}
|
@ -14,15 +14,12 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:convert';
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:wyatt_form_bloc/src/enums/form_input_status.dart';
|
||||
import 'package:wyatt_form_bloc/src/enums/form_status.dart';
|
||||
import 'package:wyatt_form_bloc/src/enums/validation_error.dart';
|
||||
class FormReplace extends FormOperation {
|
||||
const FormReplace();
|
||||
|
||||
part 'form_data.dart';
|
||||
part 'form_input.dart';
|
||||
part 'form_input_metadata.dart';
|
||||
part 'form_input_validator.dart';
|
||||
part 'form_validator.dart';
|
||||
@override
|
||||
WyattForm call(WyattForm a, WyattForm b) => b;
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/data/form/wyatt_form_impl.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
class FormUnion extends FormOperation {
|
||||
const FormUnion();
|
||||
|
||||
@override
|
||||
WyattForm call(WyattForm a, WyattForm b) {
|
||||
final inputs = <
|
||||
FormInput<dynamic, FormInputValidator<dynamic, ValidationError>,
|
||||
dynamic>>[];
|
||||
|
||||
for (final i in a.inputs) {
|
||||
inputs.add(i);
|
||||
}
|
||||
|
||||
for (final i in b.inputs) {
|
||||
if (!a.containsKey(i.key)) {
|
||||
inputs.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return WyattFormImpl(
|
||||
inputs,
|
||||
validationStrategy: a.formValidationStrategy,
|
||||
);
|
||||
}
|
||||
}
|
@ -14,7 +14,10 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/form_status.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart';
|
||||
|
||||
/// {@template every}
|
||||
/// Check and validate every input of a form
|
||||
@ -24,18 +27,13 @@ class EveryInputValidator extends FormValidator {
|
||||
const EveryInputValidator() : super();
|
||||
|
||||
@override
|
||||
FormStatus validate(FormData form) {
|
||||
FormStatus validate(WyattForm form) {
|
||||
if (isPure(form)) {
|
||||
return FormStatus.pure;
|
||||
}
|
||||
|
||||
return rawValidate(form.validators<dynamic, ValidationError>());
|
||||
}
|
||||
final validators = form.asValidatorList<dynamic, ValidationError>();
|
||||
|
||||
@override
|
||||
FormStatus rawValidate(
|
||||
List<FormInputValidator<dynamic, ValidationError>> validators,
|
||||
) {
|
||||
if (validators.any((validator) => validator.valid == false)) {
|
||||
return FormStatus.invalid;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/core/enums/form_status.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart';
|
||||
|
||||
class OnlyRequiredInputValidator extends FormValidator {
|
||||
const OnlyRequiredInputValidator() : super();
|
||||
|
||||
@override
|
||||
FormStatus validate(WyattForm form) {
|
||||
// TODO(hpcl): use metadata to check if input is required or not.
|
||||
return FormStatus.valid;
|
||||
}
|
||||
}
|
@ -14,21 +14,25 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/enums.dart';
|
||||
import 'package:wyatt_form_bloc/src/form/form.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
/// {@template boolean}
|
||||
/// Form input for a bool input
|
||||
/// {@endtemplate}
|
||||
class Boolean extends FormInputValidator<bool, ValidationStandardError> {
|
||||
class Boolean extends NullableValidator<bool, ValidationStandardError> {
|
||||
/// {@macro boolean}
|
||||
const Boolean.pure({bool? defaultValue = false})
|
||||
: super.pure(defaultValue ?? false);
|
||||
|
||||
/// {@macro boolean}
|
||||
const Boolean.dirty({bool value = false}) : super.dirty(value);
|
||||
|
||||
@override
|
||||
ValidationStandardError get onNull => ValidationStandardError.invalid;
|
||||
|
||||
@override
|
||||
ValidationStandardError? validator(bool? value) =>
|
||||
value != null ? null : ValidationStandardError.invalid;
|
||||
value != null ? null : onNull;
|
||||
|
||||
}
|
@ -14,25 +14,31 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/enums.dart';
|
||||
import 'package:wyatt_form_bloc/src/form/form.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
/// {@template confirmed_password}
|
||||
/// Form input for a confirmed password input.
|
||||
/// {@endtemplate}
|
||||
class ConfirmedPassword
|
||||
extends FormInputValidator<String, ValidationStandardError> {
|
||||
extends EqualityValidator<String, ValidationStandardError> {
|
||||
/// {@macro confirmed_password}
|
||||
const ConfirmedPassword.pure({this.password = ''}) : super.pure('');
|
||||
const ConfirmedPassword.pure({this.password = '', String? defaultValue})
|
||||
: super.pure(defaultValue);
|
||||
|
||||
/// {@macro confirmed_password}
|
||||
const ConfirmedPassword.dirty({required this.password, String value = ''})
|
||||
const ConfirmedPassword.dirty({required this.password, String? value})
|
||||
: super.dirty(value);
|
||||
|
||||
/// The original password.
|
||||
final String password;
|
||||
|
||||
@override
|
||||
ValidationStandardError? validator(String? value) =>
|
||||
password == value ? null : ValidationStandardError.invalid;
|
||||
String get another => password;
|
||||
|
||||
@override
|
||||
ValidationStandardError get onNotEqual => ValidationStandardError.notEqual;
|
||||
|
||||
@override
|
||||
ValidationStandardError get onNull => ValidationStandardError.invalid;
|
||||
}
|
@ -14,15 +14,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/enums.dart';
|
||||
import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
/// {@template email}
|
||||
/// Form input for an email input.
|
||||
/// {@endtemplate}
|
||||
class Email extends RegexValidator<ValidationStandardError> {
|
||||
/// {@macro email}
|
||||
const Email.pure() : super.pure();
|
||||
const Email.pure([super.value]) : super.pure();
|
||||
|
||||
/// {@macro email}
|
||||
const Email.dirty([super.value = '']) : super.dirty();
|
@ -14,24 +14,27 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/enums.dart';
|
||||
import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
/// {@template siren}
|
||||
/// Form input for a SIREN input.
|
||||
/// {@endtemplate}
|
||||
class Siren extends RegexValidator<ValidationStandardError> {
|
||||
/// {@macro siren}
|
||||
const Siren.pure() : super.pure();
|
||||
class EnumOption<T> extends AnyValidator<T, List<T>, ValidationError> {
|
||||
const EnumOption.pure({this.enums = const [], T? defaultValue})
|
||||
: super.pure(defaultValue);
|
||||
|
||||
/// {@macro siren}
|
||||
const Siren.dirty([super.value = '']) : super.dirty();
|
||||
const EnumOption.dirty({required this.enums, T? value})
|
||||
: super.dirty(value);
|
||||
|
||||
final List<T> enums;
|
||||
|
||||
@override
|
||||
ValidationStandardError get onEmpty => ValidationStandardError.empty;
|
||||
@override
|
||||
ValidationStandardError get onError => ValidationStandardError.invalid;
|
||||
List<T> get allChoices => enums;
|
||||
|
||||
@override
|
||||
RegExp get regex => RegExp(r'(\d{9}|\d{3}[ ]\d{3}[ ]\d{3})$');
|
||||
ValidationError get onError => ValidationStandardError.invalid;
|
||||
|
||||
@override
|
||||
ValidationError get onNull => ValidationStandardError.invalid;
|
||||
|
||||
@override
|
||||
bool test(T? element, T value) => element == value;
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
class ListOption<T> extends AnyValidator<T, Iterable<T>, ValidationError> {
|
||||
const ListOption.pure({this.choices = const [], T? defaultValue})
|
||||
: super.pure(defaultValue);
|
||||
|
||||
const ListOption.dirty({required this.choices, T? value})
|
||||
: super.dirty(value);
|
||||
|
||||
final Iterable<T> choices;
|
||||
|
||||
@override
|
||||
Iterable<T> get allChoices => choices;
|
||||
|
||||
@override
|
||||
ValidationError get onError => ValidationStandardError.invalid;
|
||||
|
||||
@override
|
||||
ValidationError get onNull => ValidationStandardError.invalid;
|
||||
|
||||
@override
|
||||
bool test(T? element, T value) => element == value;
|
||||
}
|
@ -14,15 +14,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/enums.dart';
|
||||
import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
/// {@template name}
|
||||
/// Form input for a name input.
|
||||
/// {@endtemplate}
|
||||
class Name extends RegexValidator<ValidationStandardError> {
|
||||
/// {@macro name}
|
||||
const Name.pure() : super.pure();
|
||||
const Name.pure([super.value]) : super.pure();
|
||||
|
||||
/// {@macro name}
|
||||
const Name.dirty([super.value = '']) : super.dirty();
|
@ -14,18 +14,18 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/enums.dart';
|
||||
import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
/// {@template password}
|
||||
/// Form input for a password input.
|
||||
/// {@endtemplate}
|
||||
class Password extends RegexValidator<ValidationStandardError> {
|
||||
/// {@macro password}
|
||||
const Password.pure() : super.pure();
|
||||
const Password.pure([super.value]) : super.pure();
|
||||
|
||||
/// {@macro password}
|
||||
const Password.dirty([super.value = '']) : super.dirty();
|
||||
const Password.dirty([super.value]) : super.dirty();
|
||||
|
||||
@override
|
||||
ValidationStandardError get onEmpty => ValidationStandardError.empty;
|
@ -14,15 +14,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/enums.dart';
|
||||
import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
/// {@template phone}
|
||||
/// Form input for a phone input.
|
||||
/// {@endtemplate}
|
||||
class Phone extends RegexValidator<ValidationStandardError> {
|
||||
/// {@macro phone}
|
||||
const Phone.pure() : super.pure();
|
||||
const Phone.pure([super.value]) : super.pure();
|
||||
|
||||
/// {@macro phone}
|
||||
const Phone.dirty([super.value = '']) : super.dirty();
|
@ -14,15 +14,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/enums.dart';
|
||||
import 'package:wyatt_form_bloc/src/validators/inputs/base/text_validator.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
/// {@template text_string}
|
||||
/// Form input for a text input
|
||||
/// {@endtemplate}
|
||||
class TextString extends TextValidator<ValidationStandardError> {
|
||||
/// {@macro text_string}
|
||||
const TextString.pure() : super.pure();
|
||||
const TextString.pure([super.value]) : super.pure();
|
||||
|
||||
/// {@macro text_string}
|
||||
const TextString.dirty([super.value = '']) : super.dirty();
|
23
packages/wyatt_form_bloc/lib/src/domain/domain.dart
Normal file
23
packages/wyatt_form_bloc/lib/src/domain/domain.dart
Normal file
@ -0,0 +1,23 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
export 'entities/form_input.dart';
|
||||
export 'entities/form_input_metadata.dart';
|
||||
export 'form/wyatt_form.dart';
|
||||
export 'form_encoders/form_encoder.dart';
|
||||
export 'form_operations/form_operation.dart';
|
||||
export 'form_validators/form_validator.dart';
|
||||
export 'input_validators/form_input_validator.dart';
|
@ -15,27 +15,36 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
part of 'form.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
class FormInput<Validator extends FormInputValidator<dynamic, ValidationError>>
|
||||
extends Equatable {
|
||||
// ignore: must_be_immutable
|
||||
class FormInput<
|
||||
Value,
|
||||
Validator extends FormInputValidator<Value, ValidationError>,
|
||||
Extra> extends Equatable implements Entity {
|
||||
final String key;
|
||||
final Validator validator;
|
||||
final FormInputMetadata<dynamic> metadata;
|
||||
late FormInputMetadata<Extra> metadata;
|
||||
|
||||
String get name => metadata._name ?? key;
|
||||
String get name => metadata.name ?? key;
|
||||
|
||||
const FormInput(
|
||||
FormInput(
|
||||
this.key,
|
||||
this.validator, {
|
||||
// ignore: avoid_redundant_argument_values
|
||||
this.metadata = const FormInputMetadata<void>(export: true),
|
||||
});
|
||||
FormInputMetadata<Extra>? metadata,
|
||||
}) {
|
||||
this.metadata = metadata ?? FormInputMetadata<Extra>();
|
||||
}
|
||||
|
||||
FormInput copyWith({
|
||||
FormInput<Value, Validator, Extra> copyWith({
|
||||
String? key,
|
||||
Validator? validator,
|
||||
FormInputMetadata? metadata,
|
||||
FormInputMetadata<Extra>? metadata,
|
||||
}) =>
|
||||
FormInput(
|
||||
key ?? this.key,
|
||||
@ -43,11 +52,12 @@ class FormInput<Validator extends FormInputValidator<dynamic, ValidationError>>
|
||||
metadata: metadata ?? this.metadata,
|
||||
);
|
||||
|
||||
FormInput clone() => copyWith(
|
||||
FormInput<Value, Validator, Extra> clone() => copyWith(
|
||||
key: key,
|
||||
validator: validator,
|
||||
metadata: metadata,
|
||||
);
|
||||
|
||||
@override
|
||||
bool? get stringify => true;
|
||||
|
@ -15,33 +15,35 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
part of 'form.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||
|
||||
class FormInputMetadata<T extends Object?> extends Equatable {
|
||||
class FormInputMetadata<Extra> extends Equatable
|
||||
implements Entity {
|
||||
final bool export;
|
||||
final String? _name;
|
||||
final T? extra;
|
||||
final String? name;
|
||||
final Extra? extra;
|
||||
|
||||
const FormInputMetadata({
|
||||
this.export = true,
|
||||
this.name,
|
||||
this.extra,
|
||||
String? name,
|
||||
}) : _name = name;
|
||||
});
|
||||
|
||||
FormInputMetadata<T> copyWith({
|
||||
FormInputMetadata<Extra> copyWith({
|
||||
bool? export,
|
||||
String? name,
|
||||
T? extra,
|
||||
Extra? extra,
|
||||
}) =>
|
||||
FormInputMetadata<T>(
|
||||
FormInputMetadata<Extra>(
|
||||
export: export ?? this.export,
|
||||
name: name ?? _name,
|
||||
name: name ?? this.name,
|
||||
extra: extra ?? this.extra,
|
||||
);
|
||||
|
||||
FormInputMetadata<T> clone() => copyWith(
|
||||
FormInputMetadata<Extra> clone() => copyWith(
|
||||
export: export,
|
||||
name: _name,
|
||||
name: name,
|
||||
extra: extra,
|
||||
);
|
||||
|
||||
@ -49,5 +51,5 @@ class FormInputMetadata<T extends Object?> extends Equatable {
|
||||
bool? get stringify => true;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [export, _name, extra];
|
||||
List<Object?> get props => [export, name, extra];
|
||||
}
|
60
packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart
Normal file
60
packages/wyatt_form_bloc/lib/src/domain/form/wyatt_form.dart
Normal file
@ -0,0 +1,60 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
// ignore_for_file: strict_raw_type
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/form_status.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/entities/form_input.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_operations/form_operation.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form_validators/form_validator.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
abstract class WyattForm extends Equatable {
|
||||
List<FormInput> get inputs;
|
||||
FormValidator get formValidationStrategy;
|
||||
|
||||
bool containsKey(String key);
|
||||
|
||||
FormInput inputOf(String key);
|
||||
Validator validatorOf<
|
||||
Validator extends FormInputValidator<dynamic, ValidationError>>(
|
||||
String key,
|
||||
);
|
||||
Error? errorOf<Error extends ValidationError>(String key);
|
||||
Value? valueOf<Value>(String key);
|
||||
FormInputMetadata<Extra> metadataOf<Extra>(String key);
|
||||
|
||||
List<FormInputValidator<Value, Error>>
|
||||
asValidatorList<Value, Error extends ValidationError>();
|
||||
|
||||
void updateValidator<Value>(
|
||||
String key,
|
||||
FormInputValidator<Value?, ValidationError> dirtyValue,
|
||||
);
|
||||
|
||||
void updateMetadata<Extra>(
|
||||
String key,
|
||||
FormInputMetadata<Extra> metadata,
|
||||
);
|
||||
|
||||
FormStatus validate();
|
||||
WyattForm clone();
|
||||
WyattForm operationWith(FormOperation operation, WyattForm other);
|
||||
WyattForm reset();
|
||||
}
|
@ -14,16 +14,9 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
enum SetOperation {
|
||||
/// Replace entire set with new set.
|
||||
replace,
|
||||
|
||||
/// Keep common elements between sets.
|
||||
intersection,
|
||||
|
||||
/// Remove common elements between sets.
|
||||
difference,
|
||||
|
||||
/// Add new elements to set.
|
||||
union
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
|
||||
// ignore: one_member_abstracts
|
||||
abstract class FormEncoder<Output> {
|
||||
Output encode(WyattForm form);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
|
||||
// ignore: one_member_abstracts
|
||||
abstract class FormOperation {
|
||||
const FormOperation();
|
||||
WyattForm call(WyattForm a, WyattForm b);
|
||||
}
|
@ -14,7 +14,9 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
part of 'form.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/form_status.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
|
||||
/// {@template form_validator}
|
||||
/// A [FormValidator] represents the global validaton state of a Form.
|
||||
@ -23,13 +25,9 @@ abstract class FormValidator {
|
||||
/// {@macro form_validator}
|
||||
const FormValidator();
|
||||
|
||||
bool isPure(FormData form) => form
|
||||
.validators<dynamic, ValidationError>()
|
||||
bool isPure(WyattForm form) => form
|
||||
.asValidatorList<dynamic, ValidationError>()
|
||||
.every((validator) => validator.pure);
|
||||
|
||||
FormStatus validate(FormData form);
|
||||
|
||||
FormStatus rawValidate(
|
||||
List<FormInputValidator<dynamic, ValidationError>> validators,
|
||||
);
|
||||
FormStatus validate(WyattForm form);
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
part of 'form_input_validator.dart';
|
||||
|
||||
abstract class AnyValidator<O, I extends Iterable<O?>,
|
||||
E extends ValidationError> extends FormInputValidator<O?, E> {
|
||||
const AnyValidator.pure(super.value) : super.pure();
|
||||
const AnyValidator.dirty(super.value) : super.dirty();
|
||||
|
||||
I get allChoices;
|
||||
|
||||
bool test(O? element, O value);
|
||||
|
||||
E get onError;
|
||||
|
||||
/// If value is null.
|
||||
E get onNull;
|
||||
|
||||
@override
|
||||
E? validator(O? value) {
|
||||
if (value == null) {
|
||||
return onNull;
|
||||
}
|
||||
if (allChoices.any(
|
||||
(element) => test(element, value),
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
return onError;
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
part of 'form_input_validator.dart';
|
||||
|
||||
/// {@template equality_validator}
|
||||
/// Abstract equality validator validating a value when equals to another.
|
||||
/// {@endtemplate}
|
||||
abstract class EqualityValidator<O extends Object, E extends ValidationError>
|
||||
extends FormInputValidator<O?, E> {
|
||||
const EqualityValidator.pure(super.value) : super.pure();
|
||||
const EqualityValidator.dirty(super.value) : super.dirty();
|
||||
|
||||
O get another;
|
||||
|
||||
/// If values are different.
|
||||
E get onNotEqual;
|
||||
|
||||
/// If value is null.
|
||||
E get onNull;
|
||||
|
||||
@override
|
||||
E? validator(O? value) {
|
||||
if (value == null) {
|
||||
return onNull;
|
||||
}
|
||||
if (value != another) {
|
||||
return onNotEqual;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -14,7 +14,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
part of 'form.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/form_input_status.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
|
||||
part 'regex_validator.dart';
|
||||
part 'text_validator.dart';
|
||||
part 'nullable_validator.dart';
|
||||
part 'equality_validator.dart';
|
||||
part 'any_validator.dart';
|
||||
|
||||
/// {@template form_input_validator}
|
||||
/// A [FormInputValidator] represents the value of a single form input field.
|
||||
@ -39,21 +47,21 @@ part of 'form.dart';
|
||||
/// }
|
||||
/// ```
|
||||
/// {@endtemplate}
|
||||
abstract class FormInputValidator<V, E extends ValidationError>
|
||||
abstract class FormInputValidator<Value, Error extends ValidationError>
|
||||
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);
|
||||
const FormInputValidator.pure(Value value) : this._(value);
|
||||
|
||||
/// Constructor which create a `dirty` [FormInputValidator] with a
|
||||
/// given value.
|
||||
const FormInputValidator.dirty(V value) : this._(value, false);
|
||||
const FormInputValidator.dirty(Value 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;
|
||||
final Value? value;
|
||||
|
||||
/// If the [FormInputValidator] is pure (has been touched/modified).
|
||||
/// Typically when the `FormInputValidator` is initially created,
|
||||
@ -80,7 +88,7 @@ abstract class FormInputValidator<V, E extends ValidationError>
|
||||
|
||||
/// Returns a validation error if the [FormInputValidator] is invalid.
|
||||
/// Returns `null` if the [FormInputValidator] is valid.
|
||||
E? get error => validator(value);
|
||||
Error? get error => validator(value);
|
||||
|
||||
/// Whether the [FormInputValidator] value is valid according to the
|
||||
/// overridden `validator`.
|
||||
@ -96,7 +104,7 @@ abstract class FormInputValidator<V, E extends ValidationError>
|
||||
|
||||
/// A function that must return a validation error if the provided
|
||||
/// [value] is invalid and `null` otherwise.
|
||||
E? validator(V value);
|
||||
Error? validator(Value? value);
|
||||
|
||||
@override
|
||||
bool? get stringify => true;
|
@ -14,19 +14,24 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/validators/inputs/base/text_validator.dart';
|
||||
part of 'form_input_validator.dart';
|
||||
|
||||
class EnumValidator<E> extends TextValidator<ValidationStandardError> {
|
||||
/// {@macro text_string}
|
||||
const EnumValidator.pure() : super.pure();
|
||||
/// {@template nullable_validator}
|
||||
/// Abstract nullable validator not validating null values.
|
||||
/// {@endtemplate}
|
||||
abstract class NullableValidator<O extends Object, E extends ValidationError>
|
||||
extends FormInputValidator<O?, E> {
|
||||
const NullableValidator.pure(super.value) : super.pure();
|
||||
const NullableValidator.dirty(super.value) : super.dirty();
|
||||
|
||||
/// {@macro text_string}
|
||||
EnumValidator.dirty(E value) : super.dirty(value.toString());
|
||||
/// If value is null.
|
||||
E get onNull;
|
||||
|
||||
@override
|
||||
ValidationStandardError get onEmpty => ValidationStandardError.empty;
|
||||
|
||||
@override
|
||||
ValidationStandardError get onNull => ValidationStandardError.invalid;
|
||||
E? validator(O? value) {
|
||||
if (value == null) {
|
||||
return onNull;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -14,20 +14,21 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/form/form.dart';
|
||||
part of 'form_input_validator.dart';
|
||||
|
||||
/// {@template regex_validator}
|
||||
/// Abstract regex validator for form input.
|
||||
/// {@endtemplate}
|
||||
abstract class RegexValidator<E extends ValidationError>
|
||||
extends FormInputValidator<String, E> {
|
||||
const RegexValidator.pure() : super.pure('');
|
||||
const RegexValidator.dirty([super.value = '']) : super.dirty();
|
||||
extends FormInputValidator<String?, E> {
|
||||
const RegexValidator.pure(super.value) : super.pure();
|
||||
const RegexValidator.dirty(super.value) : super.dirty();
|
||||
|
||||
RegExp get regex;
|
||||
|
||||
/// If the value is **not** null, but empty.
|
||||
E get onEmpty;
|
||||
|
||||
/// If value does not conform to regex.
|
||||
E get onError;
|
||||
|
@ -14,13 +14,12 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/form/form.dart';
|
||||
part of 'form_input_validator.dart';
|
||||
|
||||
abstract class TextValidator<E extends ValidationError>
|
||||
extends FormInputValidator<String, E> {
|
||||
const TextValidator.pure() : super.pure('');
|
||||
const TextValidator.dirty([super.value = '']) : super.dirty();
|
||||
extends FormInputValidator<String?, E> {
|
||||
const TextValidator.pure(super.value) : super.pure();
|
||||
const TextValidator.dirty(super.value) : super.dirty();
|
||||
|
||||
/// If the value is **not** null, but empty.
|
||||
E get onEmpty;
|
@ -1,184 +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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
part of 'form.dart';
|
||||
|
||||
class FormData extends Equatable {
|
||||
final List<FormInput> _inputs;
|
||||
|
||||
const FormData(this._inputs);
|
||||
const FormData.empty() : this(const <FormInput>[]);
|
||||
|
||||
/// Returns all inputs as a list
|
||||
List<FormInput> inputs() => _inputs;
|
||||
|
||||
/// Returns the input for the associated key
|
||||
FormInput inputOf(String key) {
|
||||
if (contains(key)) {
|
||||
return _inputs.firstWhere((input) => input.key == key);
|
||||
} else {
|
||||
throw Exception('FormInput with key `$key` does not exist in form');
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates a input (perform a replace at index).
|
||||
void updateInput(String key, FormInput input) {
|
||||
if (contains(key)) {
|
||||
final index = _inputs.indexOf(
|
||||
inputOf(key),
|
||||
);
|
||||
_inputs[index] = input;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns all associated validators as a list
|
||||
List<FormInputValidator<V, E>> validators<V, E extends ValidationError>() =>
|
||||
_inputs
|
||||
.map<FormInputValidator<V, E>>(
|
||||
(input) => input.validator as FormInputValidator<V, E>,
|
||||
)
|
||||
.toList();
|
||||
|
||||
/// 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<T>(String key) => inputOf(key).validator as T;
|
||||
|
||||
/// Updates validator of a given input. (perform copyWith)
|
||||
void updateValidator<V>(
|
||||
String key,
|
||||
FormInputValidator<V, ValidationError> dirtyValue,
|
||||
) {
|
||||
if (contains(key)) {
|
||||
final index = _inputs.indexOf(
|
||||
inputOf(key),
|
||||
);
|
||||
_inputs[index] = _inputs[index].copyWith(validator: dirtyValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a validation error if the [FormInputValidator] is invalid.
|
||||
/// Returns null if the [FormInputValidator] is valid.
|
||||
E? errorOf<E extends ValidationError>(String key) =>
|
||||
(inputOf(key).validator as FormInputValidator<dynamic, E>).error;
|
||||
|
||||
/// The value of the associated [FormInputValidator]. For example,
|
||||
/// if you have a FormInputValidator for FirstName, the value could be 'Joe'.
|
||||
V valueOf<V>(String key) =>
|
||||
(inputOf(key).validator as FormInputValidator<V, dynamic>).value;
|
||||
|
||||
/// Returns `true` if the [FormInputValidator] is not valid.
|
||||
/// Same as `E? errorOf<V, E>(String key) != null`
|
||||
bool isNotValid(String key) => !inputOf(key).validator.valid;
|
||||
|
||||
/// Returns all associated metadata as a list
|
||||
List<FormInputMetadata<M>> metadata<M>() => _inputs
|
||||
.map<FormInputMetadata<M>>(
|
||||
(input) => input.metadata as FormInputMetadata<M>,
|
||||
)
|
||||
.toList();
|
||||
|
||||
/// Returns the metadata associated. With `M` the type of extra data.
|
||||
FormInputMetadata<M> metadataOf<M>(String key) =>
|
||||
inputOf(key).metadata as FormInputMetadata<M>;
|
||||
|
||||
/// Updates metadata of a given input. (perform copyWith)
|
||||
void updateMetadata<M>(String key, FormInputMetadata<M> meta) {
|
||||
if (contains(key)) {
|
||||
final index = _inputs.indexOf(
|
||||
inputOf(key),
|
||||
);
|
||||
_inputs[index] = _inputs[index].copyWith(metadata: meta);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if this contains an input with the given key.
|
||||
bool contains(String key) => _inputs.any((input) => input.key == key);
|
||||
|
||||
/// Makes an intersection set operation and returns newly created [FormData]
|
||||
FormData intersection(FormData other) {
|
||||
final List<FormInput> inputs = <FormInput>[];
|
||||
|
||||
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<FormInput> inputs = <FormInput>[];
|
||||
|
||||
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<FormInput> inputs = <FormInput>[];
|
||||
|
||||
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() => FormData(
|
||||
_inputs.map((input) => input.clone()).toList(),
|
||||
);
|
||||
|
||||
/// Export this to [Map] format.
|
||||
Map<String, dynamic> toMap() {
|
||||
final map = <String, dynamic>{};
|
||||
for (final input in _inputs) {
|
||||
if (input.metadata.export) {
|
||||
map[input.name] = input.validator.value;
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// Export this to [String] format.
|
||||
String toJson() => jsonEncode(toMap());
|
||||
|
||||
@override
|
||||
bool? get stringify => true;
|
||||
|
||||
@override
|
||||
List<Object?> get props => _inputs;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/form_status.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/set_operations.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
|
||||
part 'form_data_state.dart';
|
||||
|
||||
abstract class FormDataCubit<State extends FormDataState> extends Cubit<State> {
|
||||
FormDataCubit(super.initialState) : super();
|
||||
|
||||
FutureOr<void> dataChanged<Value>(
|
||||
String key,
|
||||
FormInputValidator<Value, ValidationError> dirtyValue,
|
||||
);
|
||||
|
||||
FutureOr<void> update(
|
||||
WyattForm form, {
|
||||
SetOperation operation = SetOperation.replace,
|
||||
});
|
||||
|
||||
FutureOr<void> validate();
|
||||
|
||||
FutureOr<void> reset();
|
||||
|
||||
FutureOr<void> submit();
|
||||
}
|
@ -16,35 +16,19 @@
|
||||
|
||||
part of 'form_data_cubit.dart';
|
||||
|
||||
class FormDataState extends Equatable {
|
||||
abstract class FormDataState extends Equatable {
|
||||
/// Global status of a form.
|
||||
final FormStatus status;
|
||||
|
||||
|
||||
/// FormData with all inputs, and associated metadata.
|
||||
final FormData data;
|
||||
final WyattForm form;
|
||||
|
||||
/// Optional error message.
|
||||
final String? errorMessage;
|
||||
|
||||
const FormDataState({
|
||||
required this.data,
|
||||
required this.form,
|
||||
this.status = FormStatus.pure,
|
||||
this.errorMessage,
|
||||
});
|
||||
|
||||
FormDataState copyWith({
|
||||
FormStatus? status,
|
||||
FormData? data,
|
||||
String? errorMessage,
|
||||
}) => FormDataState(
|
||||
status: status ?? this.status,
|
||||
data: data ?? this.data,
|
||||
errorMessage: errorMessage ?? this.errorMessage,
|
||||
);
|
||||
|
||||
@override
|
||||
bool? get stringify => true;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [status, data, errorMessage];
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:wyatt_form_bloc/src/core/enums/form_status.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/set_operations.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/validation_error.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/form/wyatt_form.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/input_validators/form_input_validator.dart';
|
||||
import 'package:wyatt_form_bloc/src/presentation/features/form_data/form_data_cubit.dart';
|
||||
|
||||
part 'form_data_state_impl.dart';
|
||||
|
||||
abstract class FormDataCubitImpl extends FormDataCubit<FormDataStateImpl> {
|
||||
FormDataCubitImpl(WyattForm form) : super(FormDataStateImpl(form: form));
|
||||
|
||||
@override
|
||||
FutureOr<void> dataChanged<Value>(
|
||||
String key,
|
||||
FormInputValidator<Value, ValidationError> dirtyValue,
|
||||
) {
|
||||
final form = state.form.clone();
|
||||
|
||||
try {
|
||||
form.updateValidator(key, dirtyValue);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
form: form,
|
||||
status: form.validate(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<void> update(
|
||||
WyattForm form, {
|
||||
SetOperation operation = SetOperation.replace,
|
||||
}) {
|
||||
final WyattForm newForm = operation.operation.call(state.form, form);
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
form: newForm,
|
||||
status: newForm.validate(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<void> reset() {
|
||||
final form = state.form.reset();
|
||||
emit(
|
||||
state.copyWith(
|
||||
form: form,
|
||||
status: form.validate(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<void> validate() {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: state.form.validate(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
part of 'form_data_cubit_impl.dart';
|
||||
|
||||
class FormDataStateImpl extends FormDataState {
|
||||
const FormDataStateImpl({
|
||||
required super.form,
|
||||
super.status = FormStatus.pure,
|
||||
super.errorMessage,
|
||||
});
|
||||
|
||||
FormDataStateImpl copyWith({
|
||||
FormStatus? status,
|
||||
WyattForm? form,
|
||||
String? errorMessage,
|
||||
}) =>
|
||||
FormDataStateImpl(
|
||||
status: status ?? this.status,
|
||||
form: form ?? this.form,
|
||||
errorMessage: errorMessage ?? this.errorMessage,
|
||||
);
|
||||
|
||||
@override
|
||||
bool? get stringify => true;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [status, form, errorMessage];
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||
|
||||
class InputBuilder<Cubit extends FormDataCubit> extends StatelessWidget {
|
||||
const InputBuilder({required this.field, required this.builder, super.key});
|
||||
|
||||
final String field;
|
||||
|
||||
final Widget Function(
|
||||
BuildContext context,
|
||||
Cubit cubit,
|
||||
FormDataState state,
|
||||
String field,
|
||||
bool inputValid,
|
||||
) builder;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
BlocBuilder<Cubit, FormDataState>(
|
||||
builder: (context, state) {
|
||||
final cubit = context.read<Cubit>();
|
||||
final inputValid = state.form.validatorOf(field).valid;
|
||||
return builder.call(context, cubit, state, field, inputValid);
|
||||
},
|
||||
);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:wyatt_form_bloc/src/domain/entities/form_input_metadata.dart';
|
||||
import 'package:wyatt_form_bloc/src/presentation/presentation.dart';
|
||||
|
||||
class InputBuilderMetadata<Cubit extends FormDataCubit, Extra>
|
||||
extends StatelessWidget {
|
||||
const InputBuilderMetadata({
|
||||
required this.field,
|
||||
required this.builder,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final String field;
|
||||
|
||||
final Widget Function(
|
||||
BuildContext context,
|
||||
Cubit cubit,
|
||||
FormDataState state,
|
||||
String field,
|
||||
bool inputValid,
|
||||
FormInputMetadata<Extra>? metadata,
|
||||
) builder;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => BlocBuilder<Cubit, FormDataState>(
|
||||
builder: (context, state) {
|
||||
final cubit = context.read<Cubit>();
|
||||
final inputValid = state.form.validatorOf(field).valid;
|
||||
final metadata = state.form.metadataOf<Extra>(field);
|
||||
return builder.call(
|
||||
context,
|
||||
cubit,
|
||||
state,
|
||||
field,
|
||||
inputValid,
|
||||
metadata,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:wyatt_form_bloc/src/core/enums/form_status.dart';
|
||||
import 'package:wyatt_form_bloc/src/presentation/features/form_data/form_data_cubit.dart';
|
||||
|
||||
class SubmitBuilder<Cubit extends FormDataCubit> extends StatelessWidget {
|
||||
const SubmitBuilder({required this.builder, super.key});
|
||||
|
||||
final Widget Function(BuildContext context, Cubit cubit, FormStatus status)
|
||||
builder;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => BlocBuilder<Cubit, FormDataState>(
|
||||
buildWhen: (previous, current) => previous.status != current.status,
|
||||
builder: (context, state) => builder.call(
|
||||
context,
|
||||
context.read<Cubit>(),
|
||||
state.status,
|
||||
),
|
||||
);
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
export 'features/form_data/form_data_cubit.dart';
|
||||
export 'features/form_data_impl/form_data_cubit_impl.dart';
|
||||
export 'features/widgets/input_builder.dart';
|
||||
export 'features/widgets/input_builder_metadata.dart';
|
||||
export 'features/widgets/submit_builder.dart';
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
export 'cubit/form_data_cubit.dart';
|
||||
export 'enums/enums.dart';
|
||||
export 'form/form.dart';
|
||||
export 'validators/validators.dart';
|
||||
export 'core/core.dart';
|
||||
export 'data/data.dart';
|
||||
export 'domain/domain.dart';
|
||||
export 'presentation/presentation.dart';
|
||||
|
@ -1,39 +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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/enums.dart';
|
||||
import 'package:wyatt_form_bloc/src/validators/inputs/base/regex_validator.dart';
|
||||
|
||||
/// {@template iban}
|
||||
/// Form input for an IBAN input.
|
||||
/// {@endtemplate}
|
||||
class Iban extends RegexValidator<ValidationStandardError> {
|
||||
/// {@macro iban}
|
||||
const Iban.pure() : super.pure();
|
||||
|
||||
/// {@macro iban}
|
||||
const Iban.dirty([super.value = '']) : super.dirty();
|
||||
|
||||
@override
|
||||
ValidationStandardError get onEmpty => ValidationStandardError.empty;
|
||||
@override
|
||||
ValidationStandardError get onError => ValidationStandardError.invalid;
|
||||
|
||||
@override
|
||||
RegExp get regex => RegExp(
|
||||
r'^(?:((?:IT|SM)\d{2}[A-Z]{1}\d{22})|(NL\d{2}[A-Z]{4}\d{10})|(LV\d{2}[A-Z]{4}\d{13})|((?:BG|GB|IE)\d{2}[A-Z]{4}\d{14})|(GI\d{2}[A-Z]{4}\d{15})|(RO\d{2}[A-Z]{4}\d{16})|(MT\d{2}[A-Z]{4}\d{23})|(NO\d{13})|((?:DK|FI)\d{16})|((?:SI)\d{17})|((?:AT|EE|LU|LT)\d{18})|((?:HR|LI|CH)\d{19})|((?:DE|VA)\d{20})|((?:AD|CZ|ES|MD|SK|SE)\d{22})|(PT\d{23})|((?:IS)\d{24})|((?:BE)\d{14})|((?:FR|MC|GR)\d{25})|((?:PL|HU|CY)\d{26}))$',
|
||||
);
|
||||
}
|
@ -1,50 +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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_form_bloc/src/enums/enums.dart';
|
||||
import 'package:wyatt_form_bloc/src/form/form.dart';
|
||||
|
||||
/// {@template list_option}
|
||||
/// Form input for a list input
|
||||
/// {@endtemplate}
|
||||
class ListOption<T>
|
||||
extends FormInputValidator<List<T>, ValidationStandardError> {
|
||||
/// {@macro list_option}
|
||||
const ListOption.pure({List<T>? defaultValue})
|
||||
: super.pure(defaultValue ?? const []);
|
||||
|
||||
/// {@macro list_option}
|
||||
const ListOption.dirty({List<T>? value}) : super.dirty(value ?? const []);
|
||||
|
||||
ListOption<T> select(T? v) {
|
||||
if (v == null) {
|
||||
return this;
|
||||
}
|
||||
if (value.contains(v)) {
|
||||
final List<T> newValue = List.from(value)..remove(v);
|
||||
return ListOption<T>.dirty(value: newValue);
|
||||
} else {
|
||||
final List<T> newValue = List.from(value)..add(v);
|
||||
return ListOption<T>.dirty(value: newValue);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
ValidationStandardError? validator(List<T>? value) =>
|
||||
value?.isNotEmpty ?? false == true
|
||||
? null
|
||||
: ValidationStandardError.invalid;
|
||||
}
|
@ -3,15 +3,33 @@ description: Manage forms in Dart & Flutter with Bloc
|
||||
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_form_bloc
|
||||
version: 0.0.6
|
||||
|
||||
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||
|
||||
environment:
|
||||
sdk: '>=2.17.2 <3.0.0'
|
||||
sdk: ">=2.17.2 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
bloc: ^8.1.0
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
flutter_bloc: ^8.1.0
|
||||
equatable: ^2.0.5
|
||||
|
||||
wyatt_architecture:
|
||||
git:
|
||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||
ref: wyatt_architecture-v0.0.2-dev.0
|
||||
path: packages/wyatt_architecture
|
||||
|
||||
wyatt_type_utils:
|
||||
git:
|
||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||
ref: wyatt_type_utils-v0.0.3+1
|
||||
path: packages/wyatt_type_utils
|
||||
|
||||
dev_dependencies:
|
||||
test: ^1.21.4
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
wyatt_analysis:
|
||||
git:
|
||||
|
Loading…
x
Reference in New Issue
Block a user