bloc_signals_replay

pub package style: very good analysis

Replay, undo, and redo state tracking utilities for BlocSignal and CubitSignal state containers.


🌐 Ecosystem Packages

The BlocSignal monorepo consists of 10 modular packages:

Package Version Description
bloc_signals pub Core pure Dart reactive state primitives bridging BLoC & Signals
bloc_signals_flutter pub Flutter UI bindings, providers, builders, listeners & selectors
bloc_signals_jaspr pub Jaspr web component integration and state binding for BlocSignal
bloc_signals_riverpod pub Bidirectional Riverpod 2/3 interop adapters & provider extensions
bloc_signals_hydrate pub Automated synchronous local state persistence & hydration
bloc_signals_replay pub Undo & redo state history tracking for CubitSignal and BlocSignal
bloc_signals_otel pub OpenTelemetry tracing and span generation for state transitions
bloc_signals_devtools pub Universal DevTools telemetry observer using dart:developer
bloc_signals_test pub Declarative unit testing utilities (blocSignalTest)
bloc_signals_lint pub Custom analyzer lint rules & automated IDE quick-fixes

⚡ Overview

bloc_signals_replay brings automatic undo and redo state management capabilities to BlocSignal and CubitSignal, mirroring Felix Angelov's replay_bloc package architecture.

  • ReplayCubit / ReplayCubitMixin: Undo and redo stack support for method-driven CubitSignal containers.
  • ReplayBloc / ReplayBlocMixin: Undo and redo stack support for event-driven BlocSignal containers, with synthetic _Undo and _Redo transition tracing.
  • _ChangeStack: Configurable history limits and shouldReplay state filtering.

🚀 Quick Start

ReplayCubit

Extend ReplayCubit to automatically track state changes:

import 'package:bloc_signals_replay/bloc_signals_replay.dart';

class CounterCubit extends ReplayCubit<int> {
  CounterCubit() : super(0);

  void increment() => emit(stateValue + 1);
}

void main() {
  final cubit = CounterCubit();

  cubit.increment(); // state is 1
  print(cubit.canUndo); // true

  cubit.undo();      // state reverts to 0
  print(cubit.canRedo); // true

  cubit.redo();      // state becomes 1
}

ReplayBloc

Extend ReplayBloc for event-driven state containers:

import 'package:bloc_signals_replay/bloc_signals_replay.dart';

sealed class CounterEvent extends ReplayEvent {
  const CounterEvent();
}

final class Increment extends CounterEvent {
  const Increment();
}

class CounterBloc extends ReplayBloc<CounterEvent, int> {
  CounterBloc() : super(0) {
    on<Increment>((event, emit) => emit(stateValue + 1));
  }
}

void main() {
  final bloc = CounterBloc();

  bloc.add(const Increment()); // state is 1
  bloc.undo();                 // state is 0
  bloc.redo();                 // state is 1
}

Stack Bounds & State Filtering

Pass a limit parameter or override shouldReplay to control undo/redo behavior:

class BoundedCubit extends ReplayCubit<int> {
  // Cap undo stack depth to 5 states
  BoundedCubit() : super(0, limit: 5);

  // Skip even states during replay
  @override
  bool shouldReplay(int state) => !state.isEven;
}

Libraries

bloc_signals_replay
Replay, undo, and redo state tracking utilities for BlocSignal state containers.