smart_form_toolkit 0.0.3 copy "smart_form_toolkit: ^0.0.3" to clipboard
smart_form_toolkit: ^0.0.3 copied to clipboard

An advanced, platform-aware Flutter form framework with unified state management, generic type support, and deep native parity.

example/lib/main.dart

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Smart Form Toolkit Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final SmartFormController _formController = SmartFormController();
  final SmartFormController _jsonFormController = SmartFormController();

  final List<Map<String, dynamic>> _formSchema1 = [
    {
      'type': 'text',
      'name': 'full_name',
      'label': 'Full Name',
      'hint': 'Enter your first and last name',
      'validation': {
        'required': true,
        'minLength': 3,
        'requiredError': 'Full name is strictly required',
      },
      'decoration': {
        'borderRadius': 16,
        'padding': {
          'vertical': 16,
          'horizontal': 20,
        },
        'fillColor': '#F5F5F5',
        'borderColor': '#E0E0E0',
        'borderWidth': 1.5,
        'prefixIcon': 'person',
        'labelStyle': {
          'fontSize': 14,
          'fontWeight': 'semibold',
          'color': '#616161',
        },
        'hintStyle': {
          'fontSize': 14,
          'color': '#9E9E9E',
        },
      },
    },
    {
      'type': 'text',
      'name': 'full_name',
      'label': 'Full Name',
      'hint': 'Enter your first and last name',
      'validation': {
        'required': true,
        'minLength': 3,
        'requiredError': 'Full name is strictly required',
      },
      'decoration': {
        'borderRadius': 16,
        'padding': {
          'vertical': 16,
          'horizontal': 20,
        },
        'fillColor': '#F5F5F5',
        'borderColor': '#E0E0E0',
        'borderWidth': 1.5,
        'prefixIcon': 'person',
        'labelStyle': {
          'fontSize': 14,
          'fontWeight': 'semibold',
          'color': '#616161',
        },
        'hintStyle': {
          'fontSize': 14,
          'color': '#9E9E9E',
        },
      },
    },
    {
      'type': 'email',
      'name': 'user_email',
      'label': 'Email Address',
      'hint': 'name@example.com',
      'validation': {
        'required': true,
        'email': true,
      },
      'decoration': {
        'borderRadius': 16,
        'padding': {
          'vertical': 16,
          'horizontal': 20,
        },
        'fillColor': '#F5F5F5',
        'borderColor': '#E0E0E0',
        'borderWidth': 1.5,
        'prefixIcon': 'email',
      },
    },
  ];

  final List<Map<String, dynamic>> _formSchema2 = [
    {
      'type': 'password',
      'name': 'user_password',
      'label': 'Password',
      'hint': 'Choose a secure password',
      'enablePasswordToggle': true,
      'validation': {
        'required': true,
        'minLength': 6,
      },
      'decoration': {
        'borderRadius': 16,
        'padding': {
          'vertical': 16,
          'horizontal': 20,
        },
        'fillColor': '#F5F5F5',
        'borderColor': '#E0E0E0',
        'borderWidth': 1.5,
        'prefixIcon': 'lock',
      },
    },
    {
      'type': 'choice',
      'name': 'account_type',
      'label': 'Account Type',
      'validation': {
        'required': true,
      },
      'options': [
        {'value': 'personal', 'label': 'Personal'},
        {'value': 'business', 'label': 'Business'},
      ],
    },
    {
      'type': 'choice',
      'name': 'experience',
      'label': 'Years of Experience',
      'layout': 'segmented',
      'validation': {
        'required': true,
      },
      'options': [
        {'value': 'entry', 'label': '0-2 years'},
        {'value': 'mid', 'label': '3-5 years'},
        {'value': 'senior', 'label': '5+ years'},
      ],
    },
    {
      'type': 'toggle',
      'name': 'notifications',
      'label': 'Enable Notifications',
      'value': true,
    },
  ];

  List<Map<String, dynamic>>? _currentSchema;
  int _selectedSchemaIndex = -1;

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Smart Form Toolkit'),
          centerTitle: true,
          elevation: 0,
          bottom: const TabBar(
            tabs: [
              Tab(text: 'Standard API', icon: Icon(Icons.code)),
              Tab(text: 'Dynamic JSON', icon: Icon(Icons.dynamic_form)),
            ],
          ),
        ),
        body: TabBarView(
          children: [
            _buildStandardForm(context),
            _buildDynamicJsonForm(context),
          ],
        ),
      ),
    );
  }

  Widget _buildStandardForm(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(24.0),
      child: SmartForm(
        controller: _formController,
        showDefaultSubmitButton: false,
        onSubmit: (values) {
          debugPrint('Standard Form Submitted: $values');
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(
              content: Text('Form Success! Username: ${values['username']}'),
              backgroundColor: Colors.green,
              duration: const Duration(seconds: 3),
            ),
          );
        },
        fields: [
          SmartField.text(
            name: 'username',
            label: 'Username',
            hint: 'Enter your username',
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Please enter a username';
              }
              return null;
            },
            decoration: const FieldDecoration(
              borderRadius: 16,
              padding: EdgeInsets.symmetric(vertical: 16, horizontal: 20),
              fillColor: Color(0xFFF5F5F5),
              borderColor: Color(0xFFE0E0E0),
              borderWidth: 1.5,
            ),
          ),
          const SizedBox(height: 20),
          SmartField.password(
            name: 'password',
            label: 'Password',
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Please enter a password';
              }
              if (value.length < 6) {
                return 'Password must be at least 6 characters';
              }
              return null;
            },
            decoration: const FieldDecoration(
              borderRadius: 16,
              padding: EdgeInsets.symmetric(vertical: 16, horizontal: 20),
              fillColor: Color(0xFFF5F5F5),
              borderColor: Color(0xFFE0E0E0),
              borderWidth: 1.5,
            ),
          ),
          const SizedBox(height: 20),
          SmartField.choice<String>(
            name: 'gender',
            label: 'Gender',
            layout: ChoiceLayout.wrap,
            validator: (value) {
              if (value == null) {
                return 'Please select a gender';
              }
              return null;
            },
            options: [
              const ChoiceOption(
                value: 'male',
                label: 'Male',
              ),
              const ChoiceOption(
                value: 'female',
                label: 'Female',
              ),
              const ChoiceOption(
                value: 'other',
                label: 'Other',
              ),
            ],
          ),
          const SizedBox(height: 40),
          ElevatedButton.icon(
            onPressed: () async {
              await _formController.submit();
            },
            icon: const Icon(Icons.send),
            label: const Text('Submit Form'),
            style: ElevatedButton.styleFrom(
              minimumSize: const Size(double.infinity, 56),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(16),
              ),
              backgroundColor: Theme.of(context).colorScheme.primary,
              foregroundColor: Colors.white,
              textStyle: const TextStyle(
                fontSize: 16,
                fontWeight: FontWeight.w600,
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildDynamicJsonForm(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(24.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Row(
            children: [
              Expanded(
                child: ElevatedButton(
                  onPressed: () {
                    setState(() {
                      _jsonFormController.reset();
                      _currentSchema = _formSchema1;
                      _selectedSchemaIndex = 0;
                    });
                  },
                  style: ElevatedButton.styleFrom(
                    backgroundColor: _selectedSchemaIndex == 0
                        ? Theme.of(context).colorScheme.primary
                        : Theme.of(context).colorScheme.secondaryContainer,
                    foregroundColor: _selectedSchemaIndex == 0
                        ? Colors.white
                        : Theme.of(context).colorScheme.onSecondaryContainer,
                  ),
                  child: const Text('Load Schema 1'),
                ),
              ),
              const SizedBox(width: 12),
              Expanded(
                child: ElevatedButton(
                  onPressed: () {
                    setState(() {
                      _jsonFormController.reset();
                      _currentSchema = _formSchema2;
                      _selectedSchemaIndex = 1;
                    });
                  },
                  style: ElevatedButton.styleFrom(
                    backgroundColor: _selectedSchemaIndex == 1
                        ? Theme.of(context).colorScheme.primary
                        : Theme.of(context).colorScheme.secondaryContainer,
                    foregroundColor: _selectedSchemaIndex == 1
                        ? Colors.white
                        : Theme.of(context).colorScheme.onSecondaryContainer,
                  ),
                  child: const Text('Load Schema 2'),
                ),
              ),
            ],
          ),
          const SizedBox(height: 16),
          OutlinedButton.icon(
            onPressed: () {
              setState(() {
                _jsonFormController.reset();
                _currentSchema = null;
                _selectedSchemaIndex = -1;
              });
            },
            icon: const Icon(Icons.close),
            label: const Text('Clear Form'),
          ),
          const SizedBox(height: 32),
          if (_currentSchema != null)
            SmartFormBuilder(
              controller: _jsonFormController,
              schema: _currentSchema!,
              spacing: 20,
              showDefaultSubmitButton: false,
              onSubmit: (values) {
                debugPrint('Dynamic Form Submitted: $values');
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(
                    content: Text('Dynamic Form Data Saved!'),
                    backgroundColor: Colors.green,
                    duration: Duration(seconds: 3),
                  ),
                );
              },
              submitButton: ElevatedButton.icon(
                onPressed: () async {
                  await _jsonFormController.submit();
                },
                icon: const Icon(Icons.rocket_launch),
                label: const Text('Submit Dynamic Form'),
                style: ElevatedButton.styleFrom(
                  minimumSize: const Size(double.infinity, 56),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(16),
                  ),
                  backgroundColor: Theme.of(context).colorScheme.primary,
                  foregroundColor: Colors.white,
                  textStyle: const TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.w600,
                  ),
                ),
              ),
            ),
          if (_currentSchema == null)
            Container(
              padding: const EdgeInsets.all(32),
              decoration: BoxDecoration(
                color: Theme.of(context).colorScheme.secondaryContainer,
                borderRadius: BorderRadius.circular(16),
              ),
              child: Column(
                children: [
                  Icon(
                    Icons.dynamic_form,
                    size: 64,
                    color: Theme.of(context).colorScheme.onSecondaryContainer,
                  ),
                  const SizedBox(height: 16),
                  Text(
                    'Select a schema above to load a form',
                    style: TextStyle(
                      fontSize: 16,
                      color: Theme.of(context).colorScheme.onSecondaryContainer,
                    ),
                    textAlign: TextAlign.center,
                  ),
                ],
              ),
            ),
        ],
      ),
    );
  }
}
3
likes
160
points
9
downloads

Documentation

API reference

Publisher

verified publishergreelogix.com

Weekly Downloads

An advanced, platform-aware Flutter form framework with unified state management, generic type support, and deep native parity.

Homepage
Repository (GitHub)
View/report issues

Topics

#form #validation #adaptive #components #ui

License

MIT (license)

Dependencies

cupertino_icons, flutter

More

Packages that depend on smart_form_toolkit