[go: up one dir, main page]

input_forms 0.0.4 copy "input_forms: ^0.0.4" to clipboard
input_forms: ^0.0.4 copied to clipboard

A comprehensive Flutter input_forms package providing pre-built, customizable form components for rapid application development. Includes email, password, date picker, and more form fields with built- [...]

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:input_forms/input_forms.dart';

void main() {
  runApp(const InputFormsExampleApp());
}

class InputFormsExampleApp extends StatelessWidget {
  const InputFormsExampleApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Input Forms Package Demo',
      theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
      home: const InputFormsHomePage(),
    );
  }
}

class InputFormsHomePage extends StatefulWidget {
  const InputFormsHomePage({Key? key}) : super(key: key);

  @override
  State<InputFormsHomePage> createState() => _InputFormsHomePageState();
}

class _InputFormsHomePageState extends State<InputFormsHomePage> {
  int _currentIndex = 0;

  final List<Widget> _pages = [
    const BasicFormPage(),
    const AdvancedFormPage(),
    const EnterpriseFormPage(),
    const FeatureShowcasePage(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Input Forms Package Demo'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        elevation: 2,
      ),
      body: _pages[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        currentIndex: _currentIndex,
        onTap: (index) => setState(() => _currentIndex = index),
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.edit_outlined),
            label: 'Basic Forms',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings_outlined),
            label: 'Advanced',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business_outlined),
            label: 'Enterprise',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.star_outlined),
            label: 'Showcase',
          ),
        ],
      ),
    );
  }
}

// Basic Form Page - Demonstrates core fields
class BasicFormPage extends StatefulWidget {
  const BasicFormPage({Key? key}) : super(key: key);

  @override
  State<BasicFormPage> createState() => _BasicFormPageState();
}

class _BasicFormPageState extends State<BasicFormPage> {
  final _formKey = GlobalKey<FormState>();
  final _controllers = <String, TextEditingController>{};
  String? _selectedCountry;

  @override
  void initState() {
    super.initState();
    // Initialize controllers
    for (final field in [
      'email',
      'password',
      'confirmPassword',
      'username',
      'phone',
      'dob',
    ]) {
      _controllers[field] = TextEditingController();
    }
  }

  @override
  void dispose() {
    _controllers.values.forEach((controller) => controller.dispose());
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Form(
        key: _formKey,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Header
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Basic Form Fields',
                      style: Theme.of(context).textTheme.headlineSmall
                          ?.copyWith(fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 8),
                    Text(
                      'Demonstrates core input form components with validation.',
                      style: Theme.of(
                        context,
                      ).textTheme.bodyMedium?.copyWith(color: Colors.grey[600]),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 24),

            // Email Field
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Email Field',
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 12),
                    EmailField(
                      controller: _controllers['email'],
                      label: 'Business Email',
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),

            // Password Fields
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Password Fields',
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 12),
                    PasswordField(
                      controller: _controllers['password'],
                      label: 'Password',
                    ),
                    const SizedBox(height: 16),
                    ConfirmPasswordField(
                      passwordController: _controllers['password'],
                      confirmController: _controllers['confirmPassword'],
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),

            // Username Field
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Username Field',
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 12),
                    UsernameField(
                      controller: _controllers['username'],
                      validator: (value) {
                        if (value == null || value.length < 3) {
                          return 'Username must be at least 3 characters';
                        }
                        if (!RegExp(r'^[a-zA-Z0-9_]+$').hasMatch(value)) {
                          return 'Only letters, numbers, and underscores allowed';
                        }
                        return null;
                      },
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),

            // Phone Field
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'International Phone Field',
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 12),
                    PhoneField(
                      controller: _controllers['phone'],
                      label: 'Phone Number',
                      initialCountryCode: '+1',
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),

            // Date Fields
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Date Fields',
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 12),
                    DOBField(
                      controller: _controllers['dob'],
                      label: 'Date of Birth',
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),

            // Dropdown Field
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Dropdown Field',
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 12),
                    DropdownField<String>(
                      label: 'Country',
                      items: const [
                        'United States',
                        'Canada',
                        'United Kingdom',
                        'Australia',
                        'Germany',
                        'France',
                        'Japan',
                        'India',
                      ],
                      value: _selectedCountry,
                      itemLabel: (item) => item,
                      onChanged: (value) =>
                          setState(() => _selectedCountry = value),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 32),

            // Submit Button
            SizedBox(
              width: double.infinity,
              child: ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState!.validate()) {
                    _showSuccessDialog('Basic Form');
                  }
                },
                style: ElevatedButton.styleFrom(
                  padding: const EdgeInsets.all(16),
                ),
                child: const Text('Submit Basic Form'),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _showSuccessDialog(String formType) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('$formType Submitted!'),
        content: const Text('All validations passed successfully.'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('OK'),
          ),
        ],
      ),
    );
  }
}

// Advanced Form Page - Demonstrates searchable dropdowns and location
class AdvancedFormPage extends StatefulWidget {
  const AdvancedFormPage({Key? key}) : super(key: key);

  @override
  State<AdvancedFormPage> createState() => _AdvancedFormPageState();
}

class _AdvancedFormPageState extends State<AdvancedFormPage> {
  final _formKey = GlobalKey<FormState>();
  String? _selectedSkill;
  List<String> _selectedLanguages = [];
  LocationData? _selectedLocation;

  final _skills = [
    'Flutter Development',
    'React Development',
    'Node.js Development',
    'Python Development',
    'Java Development',
    'DevOps Engineering',
    'Data Science',
    'Machine Learning',
    'UI/UX Design',
    'Product Management',
  ];

  final _languages = [
    'English',
    'Spanish',
    'French',
    'German',
    'Chinese',
    'Japanese',
    'Portuguese',
    'Russian',
    'Arabic',
    'Hindi',
  ];

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Form(
        key: _formKey,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Header
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Advanced Form Fields',
                      style: Theme.of(context).textTheme.headlineSmall
                          ?.copyWith(fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 8),
                    Text(
                      'Features searchable dropdowns and location selection.',
                      style: Theme.of(
                        context,
                      ).textTheme.bodyMedium?.copyWith(color: Colors.grey[600]),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 24),

            // Searchable Dropdown
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Searchable Dropdown',
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 12),
                    SearchableDropdownField<String>(
                      label: 'Primary Skill',
                      items: _skills,
                      value: _selectedSkill,
                      itemLabel: (item) => item,
                      onChanged: (value) =>
                          setState(() => _selectedSkill = value),
                      searchHintText: 'Search skills...',
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),

            // Multi-Select Searchable Dropdown
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Multi-Select Searchable Dropdown',
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 12),
                    SearchableDropdownField<String>(
                      label: 'Languages',
                      items: _languages,
                      enableMultiSelect: true,
                      selectedValues: _selectedLanguages,
                      itemLabel: (item) => item,
                      onMultiSelectChanged: (values) =>
                          setState(() => _selectedLanguages = values),
                      searchHintText: 'Search languages...',
                      showSelectedItemsChips: true,
                      maxSelectedItemsToShow: 3,
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),

            // Location Field
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Location Field with Maps',
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 12),
                    LocationField(
                      label: 'Work Location',
                      value: _selectedLocation,
                      onChanged: (location) =>
                          setState(() => _selectedLocation = location),
                      mapProvider: MapProvider.openStreetMap,
                      enableLocationSearch: true,
                      enableMapSelection: true,
                      showCurrentLocationButton: true,
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 32),

            // Submit Button
            SizedBox(
              width: double.infinity,
              child: ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState!.validate()) {
                    _showResultDialog();
                  }
                },
                style: ElevatedButton.styleFrom(
                  padding: const EdgeInsets.all(16),
                ),
                child: const Text('Submit Advanced Form'),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _showResultDialog() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Advanced Form Results'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('Primary Skill: ${_selectedSkill ?? 'None'}'),
            const SizedBox(height: 8),
            Text('Languages: ${_selectedLanguages.join(', ')}'),
            const SizedBox(height: 8),
            Text('Location: ${_selectedLocation?.formattedAddress ?? 'None'}'),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('OK'),
          ),
        ],
      ),
    );
  }
}

// Enterprise Form Page - Demonstrates file upload and signatures
class EnterpriseFormPage extends StatefulWidget {
  const EnterpriseFormPage({Key? key}) : super(key: key);

  @override
  State<EnterpriseFormPage> createState() => _EnterpriseFormPageState();
}

class _EnterpriseFormPageState extends State<EnterpriseFormPage> {
  final _formKey = GlobalKey<FormState>();
  List<UploadedFile>? _uploadedDocuments;
  SignatureData? _signature;

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Form(
        key: _formKey,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Header
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Enterprise Form Fields',
                      style: Theme.of(context).textTheme.headlineSmall
                          ?.copyWith(fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 8),
                    Text(
                      'Advanced file upload and digital signature capabilities.',
                      style: Theme.of(
                        context,
                      ).textTheme.bodyMedium?.copyWith(color: Colors.grey[600]),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 24),

            // File Upload Field
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Advanced File Upload',
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 12),
                    FileUploadField(
                      label: 'Business Documents',
                      uploadMode: UploadMode.multiple,
                      allowedTypes: const [
                        FileType.document,
                        FileType.pdf,
                        FileType.image,
                      ],
                      maxFiles: 5,
                      maxFileSize: 10 * 1024 * 1024, // 10MB
                      enableAIAnalysis: true,
                      showAdvancedInfo: true,
                      value: _uploadedDocuments,
                      onChanged: (files) =>
                          setState(() => _uploadedDocuments = files),
                      validator: (files) {
                        if (files == null || files.isEmpty) {
                          return 'Please upload at least one document';
                        }
                        return null;
                      },
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),

            // Digital Signature Field
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Digital Signature',
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const SizedBox(height: 12),
                    SignatureField(
                      label: 'Legal Signature',
                      signatureType: SignatureType.digital,
                      authLevel: AuthenticationLevel.enterprise,
                      enableBiometricCapture: true,
                      enableDigitalSigning: true,
                      showSignatureInfo: true,
                      showBiometricInfo: true,
                      value: _signature,
                      onChanged: (sig) => setState(() => _signature = sig),
                      validator: (signature) {
                        if (signature == null || signature.isEmpty) {
                          return 'Digital signature is required';
                        }
                        return null;
                      },
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 32),

            // Submit Button
            SizedBox(
              width: double.infinity,
              child: ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState!.validate()) {
                    _showEnterpriseResultDialog();
                  }
                },
                style: ElevatedButton.styleFrom(
                  padding: const EdgeInsets.all(16),
                  backgroundColor: Colors.green,
                  foregroundColor: Colors.white,
                ),
                child: const Text('Submit Enterprise Form'),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _showEnterpriseResultDialog() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Enterprise Form Submitted'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Documents: ${_uploadedDocuments?.length ?? 0} files uploaded',
            ),
            const SizedBox(height: 8),
            Text(
              'Signature: ${_signature?.isAuthenticated == true ? 'Digitally signed' : 'Basic signature'}',
            ),
            const SizedBox(height: 16),
            Container(
              padding: const EdgeInsets.all(12),
              decoration: BoxDecoration(
                color: Colors.green[50],
                borderRadius: BorderRadius.circular(8),
                border: Border.all(color: Colors.green[300]!),
              ),
              child: Row(
                children: [
                  Icon(Icons.security, color: Colors.green[600], size: 20),
                  const SizedBox(width: 8),
                  Expanded(
                    child: Text(
                      'Enterprise-grade security applied',
                      style: TextStyle(
                        color: Colors.green[700],
                        fontWeight: FontWeight.w500,
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('OK'),
          ),
        ],
      ),
    );
  }
}

// Feature Showcase Page - Highlights all capabilities
class FeatureShowcasePage extends StatelessWidget {
  const FeatureShowcasePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // Header
          Card(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    'Input Forms Package',
                    style: Theme.of(context).textTheme.headlineSmall?.copyWith(
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 8),
                  Text(
                    'A comprehensive Flutter package for form inputs with advanced features.',
                    style: Theme.of(
                      context,
                    ).textTheme.bodyMedium?.copyWith(color: Colors.grey[600]),
                  ),
                ],
              ),
            ),
          ),
          const SizedBox(height: 24),

          // Features Grid
          _buildFeatureGrid(context),

          const SizedBox(height: 24),

          // Technical Specifications
          _buildTechnicalSpecs(context),
        ],
      ),
    );
  }

  Widget _buildFeatureGrid(BuildContext context) {
    final features = [
      _Feature(
        'Email Validation',
        'Advanced regex patterns with custom validation',
        Icons.email,
        Colors.blue,
      ),
      _Feature(
        'Password Security',
        'Strength indicators and security requirements',
        Icons.lock,
        Colors.red,
      ),
      _Feature(
        'Phone Numbers',
        '195+ countries with validation rules',
        Icons.phone,
        Colors.green,
      ),
      _Feature(
        'Search Dropdowns',
        'Real-time filtering with multi-select',
        Icons.search,
        Colors.purple,
      ),
      _Feature(
        'Location Maps',
        'Google Maps & OpenStreetMap integration',
        Icons.location_on,
        Colors.orange,
      ),
      _Feature(
        'File Upload',
        'AI analysis with virus scanning',
        Icons.upload_file,
        Colors.teal,
      ),
      _Feature(
        'Digital Signatures',
        'Biometric capture with encryption',
        Icons.draw,
        Colors.indigo,
      ),
      _Feature(
        'Date Pickers',
        'Age validation and constraints',
        Icons.calendar_today,
        Colors.brown,
      ),
    ];

    return GridView.builder(
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        childAspectRatio: 1.1,
        crossAxisSpacing: 16,
        mainAxisSpacing: 16,
      ),
      itemCount: features.length,
      itemBuilder: (context, index) {
        final feature = features[index];
        return Card(
          elevation: 2,
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Container(
                  padding: const EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    color: feature.color.withOpacity(0.1),
                    shape: BoxShape.circle,
                  ),
                  child: Icon(feature.icon, color: feature.color, size: 32),
                ),
                const SizedBox(height: 12),
                Text(
                  feature.title,
                  style: Theme.of(
                    context,
                  ).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.bold),
                  textAlign: TextAlign.center,
                ),
                const SizedBox(height: 8),
                Text(
                  feature.description,
                  style: Theme.of(
                    context,
                  ).textTheme.bodySmall?.copyWith(color: Colors.grey[600]),
                  textAlign: TextAlign.center,
                  maxLines: 2,
                  overflow: TextOverflow.ellipsis,
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Widget _buildTechnicalSpecs(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Technical Specifications',
              style: Theme.of(
                context,
              ).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 16),
            _buildSpecItem(
              '๐Ÿ“ฑ',
              'Platform Support',
              'iOS, Android, Web, Desktop',
            ),
            _buildSpecItem(
              '๐ŸŽจ',
              'UI Framework',
              'Material Design 3 with custom theming',
            ),
            _buildSpecItem(
              '๐Ÿ”’',
              'Security',
              'Encryption, Digital signatures, Biometrics',
            ),
            _buildSpecItem(
              '๐ŸŒ',
              'Internationalization',
              'RTL support, Multiple languages',
            ),
            _buildSpecItem(
              'โ™ฟ',
              'Accessibility',
              'Screen reader support, Keyboard navigation',
            ),
            _buildSpecItem('๐Ÿš€', 'Performance', 'Optimized for large datasets'),
            _buildSpecItem(
              '๐Ÿงช',
              'Testing',
              'Comprehensive unit and widget tests',
            ),
            _buildSpecItem(
              '๐Ÿ“ฆ',
              'Package Size',
              'Modular exports, Tree-shaking friendly',
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildSpecItem(String emoji, String title, String description) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(emoji, style: const TextStyle(fontSize: 20)),
          const SizedBox(width: 12),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  title,
                  style: const TextStyle(
                    fontWeight: FontWeight.w600,
                    fontSize: 14,
                  ),
                ),
                Text(
                  description,
                  style: TextStyle(color: Colors.grey[600], fontSize: 13),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _Feature {
  final String title;
  final String description;
  final IconData icon;
  final Color color;

  _Feature(this.title, this.description, this.icon, this.color);
}
2
likes
110
points
31
downloads

Publisher

verified publishernocorps.org

Weekly Downloads

A comprehensive Flutter input_forms package providing pre-built, customizable form components for rapid application development. Includes email, password, date picker, and more form fields with built-in validation.

Homepage
Repository (GitHub)
View/report issues

Topics

#form #widget #validation #material-design #input-fields

Documentation

API reference

Funding

Consider supporting this project:

github.com

License

unknown (license)

Dependencies

flutter, intl

More

Packages that depend on input_forms