fst 0.3.0 copy "fst: ^0.3.0" to clipboard
fst: ^0.3.0 copied to clipboard

State tree interface implementation for Flutter + Flutter specific APIs

example/lib/main.dart

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

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

const $modifier = Context<bool>(#modifier);
const $count = Context<int>(#count);

class IntCounter extends Impl<int> {
  final int initialValue;

  const IntCounter(super.n, [this.initialValue = 0]);

  @override
  int init(StateTreeNode n) => initialValue;

  void increment([covariant int delta = 1]) => value += delta;
  void decrement([covariant int delta = 1]) => value -= delta;
  void reset() => value = 0;
}

class ModifierImpl extends Impl<bool> {
  const ModifierImpl(super.n);

  @override
  bool init(StateTreeNode n) => false;

  void onKey(RawKeyEvent e) {
    value = e.isShiftPressed;
  }
}

class AppCounter extends IntCounter implements IncrementFABApi, ResetButtonApi {
  const AppCounter(super.n);
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: StateTreeBuilder<bool>(
        (context, n, child) {
          final impl = n.impl(ModifierImpl.new);
          $modifier.of(n).provide(impl.value);

          final focusNode = n.init(FocusNode.new);

          return RawKeyboardListener(
            focusNode: focusNode,
            autofocus: true,
            onKey: impl.onKey,
            child: child,
          );
        },
        child: StateTreeBuilder<int>(
          (context, n, child) {
            final impl = n.impl(AppCounter.new);

            $count.of(n)
              ..provide(impl.value)
              ..map((v) => v < 25, Home.$incrementEnabled);

            IncrementFAB.$api.of(n).provide(impl);
            ResetButton.$api.of(n).provide(impl);

            return child;
          },
          child: StateTreeBuilder(
            (context, n, child) {
              final c = n.watch($count);
              n.call(
                (count) {
                  if (c % 10 != 0 || c == 0) return;

                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Count is multiple of 10')),
                  );
                },
                c,
                mode: InvocationMode.postFrame,
              );

              return child;
            },
            child: const Home(),
          ),
        ),
      ),
    );
  }
}

class Home extends StateTreeWidget<void> {
  static const $incrementEnabled = Context<bool>(#increment_fab_enabled);

  const Home({super.key});

  @override
  Widget build(BuildContext context, StateTreeNode n) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('State Tree Example'),
        actions: const [
          ResetButton(),
        ],
      ),
      body: Center(
        child: StateTreeBuilder((context, n, _) {
          final count = n.watch($count);
          return Text('Count: $count');
        }),
      ),
      floatingActionButton: n.query(
        $incrementEnabled,
        (e) => e ? const IncrementFAB() : null,
      ),
    );
  }
}

abstract interface class IncrementFABApi {
  void increment([int delta = 1]);
}

class IncrementFAB extends StateTreeWidget {
  static const $api = Context<IncrementFABApi>(#increment_fab_api);

  const IncrementFAB({super.key});

  @override
  Widget build(BuildContext context, StateTreeNode n) {
    final api = n.read($api);

    return FloatingActionButton(
      onPressed: () {
        final incrementBy10 = n.read($modifier);
        api.increment(incrementBy10 ? 10 : 1);
      },
      child: const Icon(Icons.add),
    );
  }
}

abstract interface class ResetButtonApi {
  void reset();
}

class ResetButton extends StateTreeWidget {
  static const $api = Context<ResetButtonApi>(#reset_button_api);

  const ResetButton({super.key});

  @override
  Widget build(BuildContext context, StateTreeNode n) {
    return IconButton(
      onPressed: n.read($api).reset,
      icon: const Icon(Icons.refresh),
    );
  }
}
2
likes
120
points
61
downloads

Publisher

verified publisherlesnitsky.dev

Weekly Downloads

State tree interface implementation for Flutter + Flutter specific APIs

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, state_tree_interface

More

Packages that depend on fst