Stepper.Core 0.0.6

dotnet add package Stepper.Core --version 0.0.6
                    
NuGet\Install-Package Stepper.Core -Version 0.0.6
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Stepper.Core" Version="0.0.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Stepper.Core" Version="0.0.6" />
                    
Directory.Packages.props
<PackageReference Include="Stepper.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Stepper.Core --version 0.0.6
                    
#r "nuget: Stepper.Core, 0.0.6"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Stepper.Core@0.0.6
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Stepper.Core&version=0.0.6
                    
Install as a Cake Addin
#tool nuget:?package=Stepper.Core&version=0.0.6
                    
Install as a Cake Tool

Stepper

NuGet Version License

Stepper is a state management library derived from classical FRP implementation such as reactive-banana with the idea of TEA (The Elm Architecture) embedded.

Core Concepts

In Functional Reactive Programming (FRP):

  • Event represents discrete occurrences over time (TMsg).
  • Behavior represents continuous values over time (TModel).

Stepper implements this duality by accumulating discrete messages to transition a model state, isolating asynchronous side effects using declarative commands (TCmd) and an interpreter.

Installation

dotnet add package Stepper.Core

Architecture

  1. Messages (TMsg) are received from external sources (e.g., UI events) or the interpreter.
  2. The message stream is merged and serialized.
  3. The state transitions are processed sequentially via the Update function in Transition.
  4. The updated Model (TModel) is emitted to observers.
  5. Generated Commands (TCmd) are processed by the Interpreter's Process function, which translates commands into new messages to complete the feedback loop.

Usage

1. Define Types

public record PaletteModel(string Query, bool IsLoading, List<string> Results);

public abstract record PaletteMsg
{
    public record QueryChanged(string Query) : PaletteMsg;
    public record ResultsFetched(List<string> Results) : PaletteMsg;
    public record SearchError(string Error) : PaletteMsg;
}

public abstract record PaletteCmd
{
    public record FetchFromApi(string Query) : PaletteCmd;
    public record ReportAnalytics(string Event) : PaletteCmd;
}

2. Define Transition

var transition = new Transition<PaletteModel, PaletteMsg, PaletteCmd>(
    Init: (new PaletteModel("", false, new()), default),
    Update: state =>
    {
        var (model, msg) = state;
        return msg switch
        {
            PaletteMsg.QueryChanged(var q) when string.IsNullOrWhiteSpace(q) =>
                (model with { Query = q, IsLoading = false, Results = new() }, default),

            PaletteMsg.QueryChanged(var q) =>
                (model with { Query = q, IsLoading = true }, new PaletteCmd.FetchFromApi(q)),

            PaletteMsg.ResultsFetched(var results) =>
                (model with { IsLoading = false, Results = results }, new PaletteCmd.ReportAnalytics("Search Completed")),

            PaletteMsg.SearchError =>
                (model with { IsLoading = false, Results = new() }, default),

            _ => (model, default)
        };
    }
);

3. Define Interpreter

using System.Reactive.Linq;

var interpreter = new Interpreter<PaletteCmd, PaletteMsg>(cmds =>
{
    var searchStream = cmds.OfType<PaletteCmd.FetchFromApi>();
    var analyticsStream = cmds.OfType<PaletteCmd.ReportAnalytics>();

    var searchMsgs = searchStream
        .Select(cmd => SearchMockApi(cmd.Query))
        .Switch();

    var analyticsMsgs = analyticsStream
        .Select(cmd => UploadAnalyticsApi(cmd.Event))
        .Merge();

    return Observable.Merge(searchMsgs, analyticsMsgs);
});

4. Run the Program

var program = new Program<PaletteModel, PaletteMsg, PaletteCmd>(transition, interpreter);
var userInput = new Subject<PaletteMsg>();

using var subscription = program.Run(userInput).Subscribe(model =>
{
    Console.WriteLine($"Query: {model.Query}, Loading: {model.IsLoading}, Results: {model.Results.Count}");
});

userInput.OnNext(new PaletteMsg.QueryChanged("f"));
userInput.OnNext(new PaletteMsg.QueryChanged("fo"));
userInput.OnNext(new PaletteMsg.QueryChanged("for")); 

Threading & Scheduling

Stepper's state transitions are serialized internally. When binding to a UI framework, configure the thread scheduling on the subscription:

program.Run(userInput)
    .ObserveOn(RxApp.MainThreadScheduler) // or your framework's UI scheduler
    .Subscribe(model => {
        // Update UI elements
    });

License

This project is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.6 119 7/19/2026
0.0.5 127 6/30/2026
0.0.4 109 6/30/2026
0.0.3 109 6/30/2026
0.0.2 108 6/30/2026