multi_step_flow 0.3.0+2 copy "multi_step_flow: ^0.3.0+2" to clipboard
multi_step_flow: ^0.3.0+2 copied to clipboard

A platform-agnostic solution for managing multi-step flows with support for different flow types, validation, and customization.

example/multi_step_flow_example.dart

import 'package:multi_step_flow/multi_step_flow.dart';

void main() {
  // Create custom steps
  final steps = [
    FlowStep<RegistrationData>(
      id: 'personal_info',
      title: 'Personal Information',
      description: 'Enter your personal details',
      // Make the first step skippable so navigation is enabled
      isSkippable: true,
      data: RegistrationData(
        type: StepType.personal,
        fields: {'name': '', 'email': ''},
        isValid: true, // Pre-validate for navigation
      ),
    ),
    FlowStep<RegistrationData>(
      id: 'account_details',
      title: 'Account Details',
      description: 'Set up your account credentials',
      data: RegistrationData(
        type: StepType.account,
        fields: {'username': '', 'password': ''},
      ),
    ),
    FlowStep<RegistrationData>(
      id: 'confirmation',
      title: 'Confirmation',
      description: 'Review and confirm your information',
      isSkippable: true,
      data: RegistrationData(
        type: StepType.confirmation,
        fields: {
          'showTermsCheckbox': true,
          'requiredFields': ['name', 'email'],
          'termsAccepted': false,
        },
      ),
    ),
  ];

  // Initialize flow bloc with steps and configuration
  final bloc = FlowBloc<RegistrationData>(
    steps: steps,
    configuration: const FlowConfiguration(
      allowBackNavigation: true,
      autoAdvanceOnValidation: true,
    ),
  );

  // Ensure the first step is validated so navigation works
  bloc.validateStep(true);

  // Listen to flow state changes
  bloc.stream.listen((state) {
    print('Current step: ${state.currentStep.id}');
    print('Status: ${state.status}');
  });

  // Example usage of the bloc API
  performFlow(bloc);
}

Future<void> performFlow(FlowBloc<RegistrationData> bloc) async {
  try {
    // Move to next step
    bloc.nextStep();
    print('Moved to next step');

    // Validate the current step
    bloc.validateStep(true);
    print('Validated current step');

    // Skip a step if it's skippable
    if (bloc.state.currentStep.isSkippable) {
      bloc.skipStep();
      print('Skipped optional step');
    }

    // Complete the flow
    bloc.completeFlow();
    print('Flow completed');
  } catch (e) {
    print('Flow error: $e');
  } finally {
    // Cleanup
    bloc.close();
    print('Bloc closed');
  }
}

/// Simple enum to identify step type
enum StepType { personal, account, confirmation }

/// Example step data implementation without using freezed
class RegistrationData {
  final StepType type;
  final Map<String, dynamic> fields;
  final bool isValid;

  const RegistrationData({
    required this.type,
    required this.fields,
    this.isValid = false,
  });

  // Get a field value
  T? getValue<T>(String key) {
    if (fields.containsKey(key)) {
      final value = fields[key];
      if (value is T) return value;
    }
    return null;
  }

  // Create a copy with updated fields
  RegistrationData copyWith({
    StepType? type,
    Map<String, dynamic>? fields,
    bool? isValid,
  }) {
    return RegistrationData(
      type: type ?? this.type,
      fields: fields != null ? Map.from(fields) : Map.from(this.fields),
      isValid: isValid ?? this.isValid,
    );
  }
}

/// Helper for form validation
class EmailInput {
  const EmailInput.pure() : value = '';
  const EmailInput.dirty(this.value);

  final String value;

  String? validator(String? value) {
    if (value == null || value.isEmpty) return 'Email is required';
    if (!value.contains('@')) return 'Invalid email format';
    return null;
  }
}

/// Helper for password validation
class PasswordInput {
  const PasswordInput.pure() : value = '';
  const PasswordInput.dirty(this.value);

  final String value;

  String? validator(String? value) {
    if (value == null || value.isEmpty) return 'Password is required';
    if (value.length < 8) return 'Password must be at least 8 characters';
    return null;
  }
}
1
likes
140
points
5
downloads

Publisher

unverified uploader

Weekly Downloads

A platform-agnostic solution for managing multi-step flows with support for different flow types, validation, and customization.

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

bloc, formz, freezed_annotation, hydrated_bloc, json_annotation, meta

More

Packages that depend on multi_step_flow