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

A versatile suite of UI components and flow management tools for building dynamic onboarding and dashboards in Flutter.

example/lib/main.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flowboard_flutter/flowboard.dart';
import 'paywall_widget.dart';
import 'signup_widget.dart';
import 'end_demo_widget.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  Flowboard.init(
    apiToken:
        "eyJhbGciOiJSUzI1NiIsImtpZCI6ImZsb3dib2FyZC1rZXktMSJ9.eyJ1c2VySWQiOiJjbGllbnRfMTIzIiwiYXBwSWQiOiJXM0VSQzVzR1hsZVZnWWlxYmhLUCIsInNjb3BlcyI6WyJwYXl3YWxsOnJlYWQiLCJvbmJvYXJkOnJlYWQiLCJvbmJvYXJkOndyaXRlIl0sImlhdCI6MTc3MjEyNzY4MSwiaXNzIjoiZmxvd2JvYXJkLWF1dGgiLCJhdWQiOiJmbG93Ym9hcmQtYXBpIiwianRpIjoiYjhmNjNkZGItNTUyMS00MWFkLTgzM2UtZmY3NzFjNmZmMDljIiwiZXhwIjoyMDg3NzAzNjgxfQ.g3F3w4pCP_5BKBl6qhz8bAop2ocNNZnJQfxEj8z-H08K6h3p7vAL_LgdaTSbjaJZbOx-I_0ckR2tj46Z0mH_3bqj4zAh7SFK0qDGtyNC5So6KIcEhOCgMRvk-FvNxvsm850SyCtYFA-TG2zp4tj6FMuy4Pb6Hvthf3MBNUEcjTLOzppMLhQgeY2QzBUVDuoxsoZ-oqqX8CiZCJ4RHqLV4zeIuY4AniHLa_FYYwYNyp7x74-JiwOBffBq0_PDT9YeVRTLDTUvalh5Z2NLqyHzSgMcQORKvdpu3CObs9pjerbIxKT-ayx0TWVW7u19On9vhCVage97pC9Fdw0hiNH6xg",
    debug: true,
  );
  runApp(const MyApp());
}

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final TextEditingController _jsonController = TextEditingController();
  String _jsonStatus = '';

  void _loadButtonStrokeDemoJson() {
    final demoFlow = {
      'flow_id': 'button_stroke_effects_demo',
      'screens': [
        {
          'id': 'button_styles',
          'padding': 20,
          'children': [
            {
              'type': 'text',
              'properties': {
                'text': 'Button stroke/effects preview',
                'fontSize': 18,
                'fontWeight': 'bold',
              },
            },
            {
              'type': 'button',
              'properties': {
                'label': 'Default (no stroke/effects)',
                'color': '0xFF1E88E5',
              },
            },
            {
              'type': 'button',
              'properties': {
                'label': 'Inside stroke',
                'color': '0xFF43A047',
                'stroke': {
                  'enabled': true,
                  'color': '#FFFFFF',
                  'opacity': 0.8,
                  'width': 2,
                  'position': 'inside',
                },
              },
            },
            {
              'type': 'button',
              'properties': {
                'label': 'Center stroke',
                'color': '0xFFFB8C00',
                'stroke': {
                  'enabled': true,
                  'color': '#3E2723',
                  'opacity': 1,
                  'width': 2,
                  'position': 'center',
                },
              },
            },
            {
              'type': 'button',
              'properties': {
                'label': 'Outside stroke + multi shadow',
                'color': '0xFF8E24AA',
                'stroke': {
                  'enabled': true,
                  'color': '#000000',
                  'opacity': 0.25,
                  'width': 3,
                  'position': 'outside',
                },
                'effects': [
                  {
                    'type': 'dropShadow',
                    'enabled': true,
                    'x': 0,
                    'y': 4,
                    'blur': 12,
                    'spread': 0,
                    'color': '#000000',
                    'opacity': 0.2,
                  },
                  {
                    'type': 'dropShadow',
                    'enabled': true,
                    'x': 0,
                    'y': 10,
                    'blur': 24,
                    'spread': 0,
                    'color': '#000000',
                    'opacity': 0.12,
                  },
                ],
              },
            },
          ],
        },
      ],
    };

    _jsonController.text = const JsonEncoder.withIndent('  ').convert(demoFlow);
    setState(() {
      _jsonStatus =
          'Button stroke/effects demo JSON loaded. Tap "Launch Pasted JSON".';
    });
  }

  @override
  void dispose() {
    _jsonController.dispose();
    super.dispose();
  }

  Future<void> _launchApiFlow(BuildContext context) async {
    try {
      await Flowboard.launchOnboarding(
        context,
        customScreenBuilder: _buildCustomScreenRouter,
        onOnboardEnd: (formData) {
          debugPrint('Onboarding ended with data: $formData');
          Navigator.of(
            context,
          ).push(MaterialPageRoute(builder: (context) => const EndDemoPage()));
        },
      );
    } catch (e) {
      if (!context.mounted) return;
      ScaffoldMessenger.of(
        context,
      ).showSnackBar(SnackBar(content: Text('Error: $e')));
    }
  }

  Future<void> _launchInjectedJsonFlow(BuildContext context) async {
    final raw = _jsonController.text.trim();
    if (raw.isEmpty) {
      setState(() {
        _jsonStatus = 'Paste a JSON payload first.';
      });
      return;
    }

    try {
      final decoded = jsonDecode(raw);
      if (decoded is! Map<String, dynamic>) {
        setState(() {
          _jsonStatus = 'JSON must be an object.';
        });
        return;
      }

      final flowData = Map<String, dynamic>.from(decoded);
      final screens = flowData['screens'];
      if (screens is! List || screens.isEmpty) {
        setState(() {
          _jsonStatus = 'JSON must include a non-empty "screens" array.';
        });
        return;
      }

      final flowId = flowData['flow_id'];
      if (flowId is! String || flowId.trim().isEmpty) {
        flowData['flow_id'] = 'injected_flow';
      }

      setState(() {
        _jsonStatus = 'Injected flow loaded (${screens.length} screens).';
      });

      if (!context.mounted) return;
      await Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) => FlowboardFlow(
            data: flowData,
            customScreenBuilder: _buildCustomScreenRouter,
            onOnboardEnd: (formData) {
              debugPrint('Injected flow ended with data: $formData');
              Navigator.of(context).push(
                MaterialPageRoute(builder: (context) => const EndDemoPage()),
              );
            },
          ),
          fullscreenDialog: true,
        ),
      );
    } catch (e) {
      setState(() {
        _jsonStatus = 'Invalid JSON: $e';
      });
    }
  }

  Future<void> _launchButtonEffectsDemo(BuildContext context) async {
    final flowData = _buttonEffectsDemoFlow();
    if (!context.mounted) return;
    await Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => FlowboardFlow(
          data: flowData,
          customScreenBuilder: _buildCustomScreenRouter,
        ),
        fullscreenDialog: true,
      ),
    );
  }

  Map<String, dynamic> _buttonEffectsDemoFlow() {
    return {
      'flow_id': 'button_effects_demo',
      'screens': [
        {
          'id': 'button_styles',
          'padding': 20,
          'children': [
            {
              'type': 'text',
              'properties': {
                'text': 'Button stroke/effects demo',
                'fontSize': 20,
                'fontWeight': 'bold',
              },
            },
            {
              'type': 'button',
              'properties': {'label': 'Default (no effects)'},
            },
            {
              'type': 'button',
              'properties': {
                'label': 'Inside stroke',
                'color': '0xFFFFFFFF',
                'textColor': '0xFF111111',
                'stroke': {
                  'enabled': true,
                  'color': '#111111',
                  'opacity': 0.35,
                  'width': 2,
                  'position': 'inside',
                },
              },
            },
            {
              'type': 'button',
              'properties': {
                'label': 'Center stroke',
                'color': '0xFFFFFFFF',
                'textColor': '0xFF111111',
                'stroke': {
                  'enabled': true,
                  'color': '#111111',
                  'opacity': 0.5,
                  'width': 2,
                  'position': 'center',
                },
              },
            },
            {
              'type': 'button',
              'properties': {
                'label': 'Outside stroke + shadows',
                'color': '0xFFFFFFFF',
                'textColor': '0xFF111111',
                'stroke': {
                  'enabled': true,
                  'color': '#3B82F6',
                  'opacity': 1,
                  'width': 2,
                  'position': 'outside',
                },
                'effects': [
                  {
                    'type': 'dropShadow',
                    'enabled': true,
                    'x': 0,
                    'y': 4,
                    'blur': 12,
                    'spread': 0,
                    'color': '#000000',
                    'opacity': 0.2,
                  },
                  {
                    'type': 'dropShadow',
                    'enabled': true,
                    'x': 0,
                    'y': 10,
                    'blur': 20,
                    'spread': -4,
                    'color': '#2563EB',
                    'opacity': 0.25,
                  },
                ],
              },
            },
            {
              'type': 'button',
              'action': 'next',
              'properties': {'label': 'Finish'},
            },
          ],
        },
      ],
    };
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Flowboard Test')),
        body: Builder(
          builder: (context) {
            return SingleChildScrollView(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  ElevatedButton(
                    onPressed: () => _launchApiFlow(context),
                    child: const Text('Launch Onboarding (API)'),
                  ),
                  const SizedBox(height: 12),
                  OutlinedButton(
                    onPressed: () async {
                      await Flowboard.reinit();
                      if (!context.mounted) return;
                      ScaffoldMessenger.of(context).showSnackBar(
                        const SnackBar(
                          content: Text(
                            'Re-initialized! (Cache cleared, fresh fetch triggered)',
                          ),
                        ),
                      );
                    },
                    child: const Text('Re-initialize SDK'),
                  ),
                  const SizedBox(height: 20),
                  const Divider(),
                  const SizedBox(height: 12),
                  const Text(
                    'Inject JSON (no API)',
                    style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
                  ),
                  const SizedBox(height: 8),
                  OutlinedButton(
                    onPressed: _loadButtonStrokeDemoJson,
                    child: const Text('Load Button Stroke/Effects Demo JSON'),
                  ),
                  const SizedBox(height: 8),
                  ElevatedButton(
                    onPressed: () => _launchInjectedJsonFlow(context),
                    child: const Text('Launch Pasted JSON'),
                  ),
                  const SizedBox(height: 8),
                  ElevatedButton(
                    onPressed: () => _launchButtonEffectsDemo(context),
                    child: const Text('Launch Button Effects Demo'),
                  ),
                  const SizedBox(height: 8),
                  TextField(
                    controller: _jsonController,
                    minLines: 8,
                    maxLines: 14,
                    keyboardType: TextInputType.multiline,
                    decoration: const InputDecoration(
                      hintText: 'Paste flow JSON here (with "screens")',
                      border: OutlineInputBorder(),
                    ),
                  ),
                  const SizedBox(height: 8),
                  if (_jsonStatus.isNotEmpty)
                    Text(_jsonStatus, style: const TextStyle(fontSize: 12)),
                ],
              ),
            );
          },
        ),
      ),
    );
  }
}

/// Router for custom screens - handles different custom screen types
Widget _buildCustomScreenRouter(FlowboardContext ctx) {
  final screenId = ctx.screenData['id'] as String?;

  switch (screenId) {
    case 'paywall':
      return PaywallPage(ctx: ctx);
    case 'signup':
      return SignupPage(ctx: ctx);
    default:
      // Fallback for unknown screen IDs
      return Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('Unknown custom screen: $screenId'),
              const SizedBox(height: 16),
              ElevatedButton(
                onPressed: ctx.onNext,
                child: const Text('Continue'),
              ),
            ],
          ),
        ),
      );
  }
}
0
likes
125
points
236
downloads

Documentation

API reference

Publisher

verified publisherflow-board.co

Weekly Downloads

A versatile suite of UI components and flow management tools for building dynamic onboarding and dashboards in Flutter.

Homepage

License

MIT (license)

Dependencies

archive, device_info_plus, expressions, flutter, font_awesome_flutter, google_fonts, http, in_app_review, intl, lottie, mask_text_input_formatter, package_info_plus, path_provider, permission_handler, petitparser, platform, shared_preferences, url_launcher, uuid, win32

More

Packages that depend on flowboard_flutter