npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@nachiketnkulkarni/ui-workflow

v1.0.2

Published

Config-driven UI workflow engine with React bindings

Readme

@nachiketnkulkarni/ui-workflow

A lightweight, type-safe, UI workflow engine for React applications.
Designed for building frontend workflow logic optimized specifically for:

  • UI-driven flows
  • Auto-running steps
  • Config-first JSON/DSL
  • TypeScript-first safety
  • Simple React integration

This package enables you to define workflows declaratively using JSON, plug in backend/local logic through a handler registry, and render/drive workflows through React hooks.


✨ Features

  • Config-first workflow definition (JSON/DSL)
  • Auto-running workflow engine
    • Automatically progresses through auto states until stable
  • TypeScript-first runtime and definitions
  • React bindings
    • WorkflowProvider
    • useWorkflow()
  • Pluggable handlers
    • API calls
    • Local validations
    • Async logic
  • Supports GUARD logic, ACTION logic, onEnter, onExit
  • Fully controlled workflow instance state
  • Workflow history tracking
  • Highly modular and extensible

📦 Installation

npm install @nachiketnkulkarni/ui-workflow

or

yarn add @nachiketnkulkarni/ui-workflow

🧠 Core Concepts

States

Each workflow state has a type:

| Type | Meaning | | ------ | ----------------------------------------- | | task | Requires UI/user action | | auto | Runs automatically with no UI interaction | | end | Terminal state of workflow |


Transitions

Each state contains transitions that may contain:

  • event — user-triggered or system-triggered event
  • guard — boolean condition to allow/block transition
  • action — logic executed during transition

Auto-running Logic

auto states immediately run:

  1. onEnter action
  2. All event-less transitions
  3. Each transition guard is evaluated
  4. First valid guard wins
  5. Transitions again
  6. Until reaching a non-auto or end state

This enables backend-like workflow execution on the client.


🧩 JSON/DSL Workflow Definition Example

{
  "id": "cash-withdrawal",
  "version": 1,
  "initialState": "enterDetails",
  "states": {
    "enterDetails": {
      "kind": "task",
      "label": "Enter PIN & Amount",
      "transitions": [
        {
          "target": "checkPin",
          "event": "SUBMIT"
        }
      ]
    },
    "checkPin": {
      "kind": "auto",
      "onEnter": "atm.checkPin",
      "transitions": [
        { "target": "failed", "guard": "atm.guard.pinInvalid" },
        { "target": "checkUserExists", "guard": "atm.guard.pinValid" }
      ]
    },
    "failed": { "kind": "end" },
    "completed": { "kind": "end" }
  }
}

🔧 Handler Registry

Handlers connect workflow to your API logic or business logic.

import { HandlerRegistry } from "@nachiketnkulkarni/ui-workflow";

export const atmHandlers: HandlerRegistry<WithdrawalContext> = {
  "atm.checkPin": async (ctx) => {
    const result = await api.verifyPin(ctx.pin);
    ctx.pinValid = result.valid;
  },

  "atm.guard.pinValid": (ctx) => ctx.pinValid === true,
  "atm.guard.pinInvalid": (ctx) => ctx.pinValid === false,
};

Handlers can be either:

  • Guard functions → return boolean
  • Action functions → return void / promise

Resolved automatically by the compiler.


⚙️ Compiling Workflow JSON + Handlers

import config from "./atmConfig.json";
import { compileWorkflowConfig } from "@nachiketnkulkarni/ui-workflow";
import { atmHandlers } from "./handlers";

export const atmWorkflow = compileWorkflowConfig(config, atmHandlers);

⚛️ React Integration

Wrapping the workflow

import { WorkflowProvider, useWorkflow } from "@nachiketnkulkarni/ui-workflow";

export function WithdrawalFlow() {
  const initialCtx = { pin: "", amount: 0 };

  return (
    <WorkflowProvider workflow={atmWorkflow} initialContext={initialCtx}>
      <WithdrawScreen />
    </WorkflowProvider>
  );
}

Using the workflow inside React

function WithdrawScreen() {
  const { instance, send, currentState, updateContext } =
    useWorkflow<WithdrawalContext>();

  if (currentState.id === "enterDetails") {
    return (
      <>
        <input
          onChange={(e) => updateContext((ctx) => (ctx.pin = e.target.value))}
        />
        <button onClick={() => send("SUBMIT")}>Submit</button>
      </>
    );
  }

  if (currentState.type === "auto") {
    return <p>Processing {currentState.label}...</p>;
  }

  if (currentState.id === "completed") {
    return <p>Withdrawal completed!</p>;
  }

  return null;
}

🧪 Example Workflow Execution

enterDetails (task)
 --SUBMIT→ checkPin (auto)
 → onEnter: call verifyPin API
 → guard checks
 → checkUserExists (auto)
 → checkAccount (auto)
 → checkBalance (auto)
 → debitAccount (auto)
 → completed (end)

User interacts only once, engine handles the rest.


🧱 API Reference (Summary)

compileWorkflowConfig(config, handlers)

Compiles JSON workflow + handler registry → runtime workflow.


WorkflowProvider

Props:

| Prop | Type | Description | | ---------------- | -------- | -------------------------- | | workflow | Workflow | Compiled workflow | | initialContext | object | Initial workflow context | | onTransition? | callback | Hook for logging/analytics |


useWorkflow()

Returns:

| Key | Description | | ------------------- | ------------------------ | | instance | Full workflow instance | | currentState | Current workflow state | | send(event) | Trigger event | | can(event) | Check if event is valid | | updateContext(fn) | Mutate context immutably | | setContext(ctx) | Replace context |


💡 Why This Library?

This library is:

  • purpose-built for UI flows (forms, wizards, process automation)
  • simpler to learn
  • JSON-friendly for non-dev workflow authors
  • excellent for banking, onboarding, checkout, KYC, approvals, multi-step ops
  • supports async actions naturally (API calls inside auto states)

🧭 Roadmap

  • [ ] Visual Workflow Designer / Graph Viewer
  • [ ] Auto-generated TypeScript types from JSON schema
  • [ ] Workflow validation tool (workflow validate myflow.json)
  • [ ] DevTools for React + workflow instance inspection
  • [ ] Persistent workflow sessions with storage adapters (localStorage, backend)