universal_validator 1.0.1
universal_validator: ^1.0.1 copied to clipboard
A comprehensive Flutter package providing reusable form validators, smart input widgets, and formatting utilities for email, phone, password, PAN, GST, and more with built-in localization support.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:universal_validator/universal_validator.dart';
void main() {
runApp(const UniversalValidatorExample());
}
class UniversalValidatorExample extends StatelessWidget {
const UniversalValidatorExample({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Universal Validator Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const ValidationDemoPage(),
);
}
}
class ValidationDemoPage extends StatefulWidget {
const ValidationDemoPage({super.key});
@override
State<ValidationDemoPage> createState() => _ValidationDemoPageState();
}
class _ValidationDemoPageState extends State<ValidationDemoPage> {
final _formKey = GlobalKey<FormState>();
final Map<String, ValidationResult> _validationResults = {};
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Universal Validator Demo'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Header
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Icon(
Icons.verified_user,
size: 48,
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 8),
Text(
'Universal Validator',
style: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(height: 4),
Text(
'Comprehensive form validation for Flutter',
style: Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.center,
),
],
),
),
),
const SizedBox(height: 24),
// Email Field
_buildSectionTitle('Email Validation'),
SmartTextField(
fieldType: FieldType.email,
decoration: const InputDecoration(
labelText: 'Email Address',
hintText: 'Enter your email',
prefixIcon: Icon(Icons.email),
border: OutlineInputBorder(),
),
showSuccessIndicator: true,
onValidationChanged: (result) {
setState(() {
_validationResults['email'] = result;
});
},
),
_buildValidationStatus('email'),
const SizedBox(height: 20),
// Phone Field
_buildSectionTitle('Phone Number Validation'),
SmartTextField(
fieldType: FieldType.phone,
decoration: const InputDecoration(
labelText: 'Phone Number',
hintText: 'Enter phone number (+country code or 10 digits)',
prefixIcon: Icon(Icons.phone),
border: OutlineInputBorder(),
),
showSuccessIndicator: true,
onValidationChanged: (result) {
setState(() {
_validationResults['phone'] = result;
});
},
),
_buildValidationStatus('phone'),
const SizedBox(height: 20),
// Password Field
_buildSectionTitle('Password Validation'),
SmartTextField(
fieldType: FieldType.password,
decoration: const InputDecoration(
labelText: 'Password',
hintText: 'Enter a strong password',
prefixIcon: Icon(Icons.lock),
border: OutlineInputBorder(),
),
obscureText: true,
showSuccessIndicator: true,
onValidationChanged: (result) {
setState(() {
_validationResults['password'] = result;
});
},
),
_buildValidationStatus('password'),
const SizedBox(height: 20),
// Name Field
_buildSectionTitle('Name Validation'),
SmartTextField(
fieldType: FieldType.name,
decoration: const InputDecoration(
labelText: 'Full Name',
hintText: 'Enter your full name',
prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
),
showSuccessIndicator: true,
onValidationChanged: (result) {
setState(() {
_validationResults['name'] = result;
});
},
),
_buildValidationStatus('name'),
const SizedBox(height: 20),
// PAN Field
_buildSectionTitle('PAN Card Validation (Indian)'),
SmartTextField(
fieldType: FieldType.pan,
decoration: const InputDecoration(
labelText: 'PAN Number',
hintText: 'Enter PAN (AAAAA9999A format)',
prefixIcon: Icon(Icons.credit_card),
border: OutlineInputBorder(),
),
showSuccessIndicator: true,
onValidationChanged: (result) {
setState(() {
_validationResults['pan'] = result;
});
},
),
_buildValidationStatus('pan'),
const SizedBox(height: 20),
// GST Field
_buildSectionTitle('GST Number Validation (Indian)'),
SmartTextField(
fieldType: FieldType.gst,
decoration: const InputDecoration(
labelText: 'GST Number',
hintText: 'Enter GST number (15 digits)',
prefixIcon: Icon(Icons.business),
border: OutlineInputBorder(),
),
showSuccessIndicator: true,
onValidationChanged: (result) {
setState(() {
_validationResults['gst'] = result;
});
},
),
_buildValidationStatus('gst'),
const SizedBox(height: 32),
// Validation Summary
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Validation Summary',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 12),
..._validationResults.entries.map((entry) {
final fieldName = entry.key;
final result = entry.value;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
children: [
Icon(
result.isValid ? Icons.check_circle : Icons.error,
color: result.isValid ? Colors.green : Colors.red,
size: 20,
),
const SizedBox(width: 8),
Text(
'${fieldName.toUpperCase()}: ${result.isValid ? 'Valid' : 'Invalid'}',
style: TextStyle(
color: result.isValid ? Colors.green : Colors.red,
fontWeight: FontWeight.w500,
),
),
],
),
);
}).toList(),
if (_validationResults.isEmpty)
const Text(
'Start typing in the fields above to see validation results',
style: TextStyle(color: Colors.grey),
),
],
),
),
),
const SizedBox(height: 24),
// Example Usage
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Example Valid Inputs',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 12),
_buildExampleItem('Email', 'user@example.com'),
_buildExampleItem('Phone', '+919876543210 or 9876543210'),
_buildExampleItem('Password', 'MySecure123!'),
_buildExampleItem('Name', 'John Doe or Mary-Jane'),
_buildExampleItem('PAN', 'ABCDE1234F'),
_buildExampleItem('GST', '22AAAAA0000A1ZC'),
],
),
),
),
],
),
),
),
);
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text(
title,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
);
}
Widget _buildValidationStatus(String fieldKey) {
final result = _validationResults[fieldKey];
if (result == null) return const SizedBox.shrink();
return Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Row(
children: [
Icon(
result.isValid ? Icons.check_circle_outline : Icons.error_outline,
size: 16,
color: result.isValid ? Colors.green : Colors.red,
),
const SizedBox(width: 4),
Expanded(
child: Text(
result.isValid
? 'Valid ${fieldKey}'
: result.errorMessage ?? 'Invalid ${fieldKey}',
style: TextStyle(
fontSize: 12,
color: result.isValid ? Colors.green : Colors.red,
),
),
),
],
),
);
}
Widget _buildExampleItem(String label, String example) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 2.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 80,
child: Text(
'$label:',
style: const TextStyle(fontWeight: FontWeight.w500),
),
),
Expanded(
child: Text(
example,
style: const TextStyle(
fontFamily: 'monospace',
color: Colors.blue,
),
),
),
],
),
);
}
}