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 🙏

© 2026 – Pkg Stats / Ryan Hefner

qp-workflow-react

v1.0.15

Published

React designer, inbox, and runner for the Chd.Workflow .NET engine. Open-source sample that hosts both: https://github.com/mehmet-yoldas/Chd.Examples

Readme

qp-workflow-react

npm TypeScript React License: MIT

qp-workflow-react is the React + TypeScript companion package for the Chd.Workflow backend engine. It is React-only (no Vue). It provides ready-to-use UI pieces for both workflow design and workflow execution.

The package is designed for teams that want to move quickly without rebuilding workflow UI from scratch for every project.

It includes:

  • a visual workflow designer (TreeDesigner),
  • a runtime workflow runner (WorkflowRunner),
  • an instance inbox (WorkflowInbox),
  • a TypeScript API client,
  • React hooks for custom experiences,
  • localization (English / Turkish),
  • external form helpers,
  • named host form components (FormType.Component),
  • an admin modal for workflow notification settings.

Although it pairs naturally with Chd.Workflow, the client and components can also work with another backend if the same REST contract is respected.

Chd.Workflow is the engine. This package is the UI. Chd.Examples is the host that runs both. See Architecture.


Table of Contents


Architecture

Chd.Workflow, this package, and Chd.Examples are separate projects on one contract.

| Piece | Role | Start here | |---|---|---| | Chd.Workflow | .NET engine. Definitions, instances, actions, guards, and the REST API. This package calls that API. | NuGet · source | | qp-workflow-react | React designer, inbox, and runner. It does not store workflow state. | Installation · Quick start | | Chd.Examples | Open sample that hosts both. Leave, purchase, and support flows you can click through. | API · UI · how to run |

TreeDesigner edits a definition, WorkflowInbox lists instances, and WorkflowRunner executes one instance. Chd.Examples hosts those components against a running API.


Why this package exists

A workflow UI is usually more than just a form.

A real workflow screen often needs to:

  • load the current workflow state,
  • render fields based on the current node,
  • validate inputs,
  • show available transitions,
  • support confirmation or comment requirements,
  • handle guard failures,
  • load dropdown options from the backend,
  • support external forms,
  • support multiple languages,
  • give designers a way to edit the workflow visually.

If every project builds this from zero, teams spend a lot of time repeating the same work.

qp-workflow-react solves that by packaging the repeated parts into reusable building blocks.

This lets teams focus on:

  • business logic,
  • design customization,
  • backend actions and rules,
  • project-specific workflows.

Main capabilities

Visual workflow design

TreeDesigner provides a visual tree-based editing experience.

Runtime workflow execution

WorkflowRunner renders the active node, fields, history, and available actions.

Inbox

WorkflowInbox lists instances from GET /instances (running by default).

Custom workflow UX with hooks

The React hook export lets you build your own UI while reusing state loading and transition logic.

API abstraction

WorkflowClient wraps the REST API in a simple TypeScript class.

External form support

Helpers make it easier to connect non-React or external pages to the same workflow.

Localization

English and Turkish translations are available out of the box.

Notification admin UI

A ready modal exists for notification settings management when the backend exposes those endpoints.


Installation

npm install qp-workflow-react

Runnable host + UI: Chd.Examples. See Architecture.

Peer dependencies:

  • react >= 18
  • react-dom >= 18

This package builds around a backend that follows the Chd.Workflow REST contract.


Package exports

The package currently exports the following main items:

Core API and types

  • WorkflowClient
  • WorkflowClientError
  • all public workflow types from src/types

React hook export

  • useWorkflowReact

Designer exports

  • TreeDesigner
  • createDefaultWorkflowDefinition

Runtime exports

  • WorkflowRunner
  • WorkflowInbox

External form helpers

  • buildExternalFormUrl
  • parseWorkflowParams
  • useWorkflowParams
  • useWorkflowExternalForm

Host/admin export

  • WorkflowHostNotificationSettingsModal

Localization exports

  • LocaleProvider
  • useLocale
  • getLocale
  • locales
  • locale-related types

Quick start

A basic end-to-end scenario usually has two parts.

1. Design a workflow

import { TreeDesigner } from 'qp-workflow-react';

<TreeDesigner
  apiUrl="http://localhost:5088/api/workflow"
  headers={{ 'X-Workflow-User': 'admin', 'X-Workflow-Roles': 'Admin' }}
  initialDefinitionId="leave-request"
  locale="en"
  enableFormEditor
  onSaved={(definition) => console.log('saved', definition.id)}
/>

2. Run a workflow instance

import { WorkflowRunner, WorkflowClient } from 'qp-workflow-react';

const client = new WorkflowClient({
  apiUrl: 'http://localhost:5088/api/workflow',
  headers: {
    'X-Workflow-User': 'employee',
    'X-Workflow-Roles': 'Employee',
  },
});

const instance = await client.createInstance('leave-request', {
  employeeId: '123'
});

<WorkflowRunner
  apiUrl="http://localhost:5088/api/workflow"
  headers={{ 'X-Workflow-User': 'employee', 'X-Workflow-Roles': 'Employee' }}
  instanceId={instance.id}
  locale="en"
  theme="dark"
  onCompleted={(result) => console.log('completed', result.id)}
/>

Main components

TreeDesigner

TreeDesigner is the main visual workflow editor.

It is useful when you want to:

  • create nodes visually,
  • manage transitions,
  • choose action handlers,
  • choose guard handlers,
  • set allowed roles/groups,
  • edit form fields (palette, resize, optional Split two-column layout),
  • set node timeout + timeout action,
  • save definitions through the REST API.

Basic usage

<TreeDesigner
  apiUrl="http://localhost:5088/api/workflow"
  headers={{ 'X-Workflow-User': 'admin', 'X-Workflow-Roles': 'Admin' }}
  initialDefinitionId="leave-request"
  locale="en"
  enableFormEditor
  onSaved={(definition) => console.log(definition.id)}
/>

Main props

| Prop | Type | Description | |---|---|---| | apiUrl | string | Base workflow API URL | | headers? | Record<string, string> | Forwarded on designer fetches (auth, X-Workflow-User, X-Workflow-Roles) | | initialDefinitionId? | string | Definition id to load first | | onSaved? | (saved) => void | Called after successful save | | locale? | 'en' \| 'tr' | UI language | | enableFormEditor? | boolean | Enables field editing UI |

Practical notes

  • The component loads action metadata from /actions.
  • It loads guard metadata from /guards.
  • It loads participant group data from /admin/participant-groups.
  • It can create a default definition if the requested definition does not exist.

Because the designer reads action metadata from the backend, both modern class-based actions and legacy controller-style actions can appear in the same action picker when the host exposes them.

This makes it suitable for both new workflow design and editing existing definitions.


WorkflowRunner

WorkflowRunner is the runtime execution component.

It is useful when you want a ready-made UI that:

  • loads the workflow state,
  • renders the current step fields,
  • validates values,
  • displays available transitions,
  • handles comments and confirmations,
  • supports dark and light themes,
  • refreshes state after transitions.

Basic usage

<WorkflowRunner
  apiUrl="http://localhost:5088/api/workflow"
  headers={{ 'X-Workflow-User': 'manager', 'X-Workflow-Roles': 'Manager' }}
  instanceId="instance-abc123"
  locale="en"
  theme="dark"
  formComponents={{ HostBudgetForm }}
  onTransition={(action, state) => console.log(action, state)}
  onCompleted={(instance) => console.log(instance.id)}
  onError={(error) => console.error(error)}
/>

Main props

| Prop | Type | Description | |---|---|---| | apiUrl | string | Base workflow API URL | | headers? | Record<string, string> | Forwarded on API calls | | instanceId | string | Instance to render | | formComponents? | Record<string, Component> | Named React forms for FormType.Component | | theme? | 'dark' \| 'light' | Runner theme | | locale? | 'en' \| 'tr' | UI language | | debug? | boolean | Shows extra debug data | | onCompleted? | (instance) => void | Called when the workflow reaches completion | | onTransition? | (action, newState) => void | Called after successful transition | | onError? | (error) => void | Called on workflow errors | | loadingComponent? | ReactNode | Custom loading UI | | errorComponent? | (error, retry) => ReactNode | Custom error UI | | completedComponent? | (node, instance) => ReactNode | Custom completion UI | | className? | string | Custom CSS class | | style? | CSSProperties | Inline style override |

Built-in behavior

The runner already handles many common tasks:

  • loading GET /instances/{id}/state,
  • rendering fields by type,
  • preserving and updating form values,
  • showing validation errors,
  • calling transition endpoints,
  • handling requiresConfirmation,
  • handling requiresComment,
  • handling guard failures returned by the backend,
  • loading field options when needed,
  • grouping fields after a Split,
  • persisting File / Image as a small data URL on the instance,
  • rendering RichText with the built-in editor,
  • showing a history strip,
  • redirecting FormType.External and mounting FormType.Component.

This is often enough for production usage without writing a custom runtime screen.


WorkflowInbox

Lists instance summaries from GET /instances.

Default filter is Running. Change refreshToken after create / transition so the list reloads.

import { WorkflowInbox } from 'qp-workflow-react';

<WorkflowInbox
  apiUrl="http://localhost:5088/api/workflow"
  headers={{ 'X-Workflow-User': 'manager', 'X-Workflow-Roles': 'Manager' }}
  locale="en"
  theme="dark"
  selectedId={instanceId}
  refreshToken={inboxKey}
  onSelect={(row) => setInstanceId(row.id)}
/>

| Prop | Type | Description | |---|---|---| | apiUrl | string | Base workflow API URL | | headers? | Record<string, string> | Identity / auth headers | | locale? | 'en' \| 'tr' | UI language | | theme? | 'dark' \| 'light' | Theme | | selectedId? | string | Highlighted row | | definitionId? | string | Optional definition filter | | refreshToken? | number \| string | Change to reload | | onSelect? | (row) => void | Row click |


WorkflowHostNotificationSettingsModal

This modal is intended for host/admin screens.

It communicates with:

  • GET /admin/notification-settings
  • PUT /admin/notification-settings

It helps manage workflow notification-related settings such as:

  • SMTP host,
  • SMTP port,
  • SMTP user,
  • password presence,
  • from email,
  • SSL usage,
  • subject and body templates,
  • group member resolution SQL,
  • email column name.

Example

import { WorkflowHostNotificationSettingsModal } from 'qp-workflow-react';

<WorkflowHostNotificationSettingsModal
  open={open}
  onClose={() => setOpen(false)}
  apiUrl="http://localhost:5088/api/workflow"
  locale="en"
/>

A 503 response usually means the backend host has not enabled the required persistence service for this admin area.


Hook usage

The package exports the React hook as useWorkflowReact.

This hook is useful when:

  • WorkflowRunner is too opinionated for your screen,
  • you want your own layout,
  • you still want to reuse workflow loading and transition logic.

Example

import { useWorkflowReact, WorkflowClient } from 'qp-workflow-react';

const client = new WorkflowClient({
  apiUrl: 'http://localhost:5088/api/workflow',
  headers: { 'X-Workflow-User': 'employee', 'X-Workflow-Roles': 'Employee' },
});

function CustomRunner({ instanceId }: { instanceId: string }) {
  const {
    state,
    currentNode,
    fields,
    availableActions,
    values,
    errors,
    isLoading,
    error,
    setValue,
    transition,
    reload,
  } = useWorkflowReact({ client, instanceId });

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>{error.message}</p>;

  return (
    <div>
      <h2>{currentNode?.title ?? currentNode?.name}</h2>

      {fields.map(field => (
        <div key={field.name}>
          <label>{field.label ?? field.name}</label>
          <input
            value={String(values[field.name] ?? '')}
            onChange={e => setValue(field.name, e.target.value)}
          />
          {errors[field.name] && <div>{errors[field.name]}</div>}
        </div>
      ))}

      {availableActions.map(action => (
        <button key={action.id} onClick={() => transition(action.action)}>
          {action.label ?? action.action}
        </button>
      ))}

      <button onClick={() => reload()}>Reload</button>
    </div>
  );
}

What the hook returns

The hook exposes:

  • current workflow state,
  • current node,
  • fields,
  • available actions,
  • history,
  • breadcrumb,
  • form values,
  • validation errors,
  • loading/error state,
  • helpers such as setValue, setValues, transition, validate, reload, createInstance, cancel.

This is a good option when you need a custom UI but do not want to rebuild the workflow data layer yourself.


Client API

WorkflowClient is a TypeScript wrapper around the workflow REST API.

It is framework-agnostic at the data level and can be used outside the ready React components.

Basic setup

import { WorkflowClient } from 'qp-workflow-react';

const client = new WorkflowClient({
  apiUrl: 'http://localhost:5088/api/workflow',
  headers: {
    'X-Workflow-User': 'employee',
    'X-Workflow-Roles': 'Employee',
  },
  onError: (error) => console.error(error)
});

Helpful runtime methods

client.setAuthToken('Bearer token');
client.clearAuthToken();
client.setApiUrl('https://example.com/api/workflow');

Main methods

Definitions

  • getDefinitions(tenantId?)
  • getDefinition(id)
  • createDefinition(definition)
  • updateDefinition(id, definition)
  • deleteDefinition(id)

Instances

  • getInstances({ status?, definitionId?, tenantId? })
  • getInstance(id)
  • getState(instanceId)
  • createInstance(definitionId, data?, userId?)
  • transition(instanceId, action, data?, userId?, comment?)
  • validate(instanceId, data)
  • getFieldOptions(instanceId, fieldName)
  • cancel(instanceId, request?)

Admin

  • getNotificationAdminSettings()
  • updateNotificationAdminSettings(body)

Error model

The client throws WorkflowClientError.

Important properties include:

  • message
  • status
  • errors?

This is useful when you want to surface backend validation details directly in your UI.

Working with legacy backend actions

The React package does not need a separate legacy mode.

If the backend exposes legacy controller-style actions through the normal /actions metadata endpoint, they are treated the same way as other workflow actions in the designer and runtime flow.

In practice this means:

  • the designer can select a legacy action by name,
  • external forms can submit the same field payload,
  • the backend decides whether the action is implemented by IWorkflowAction or by a legacy annotated controller/service method.

TypeScript model overview

The package exports a broad public type model that mirrors the backend contract.

Important examples include:

Enums and union types

  • NodeType
  • FieldType
  • FormType
  • WorkflowStatus
  • RuleType
  • ButtonStyle

Core models

  • FieldOption
  • Field
  • Transition
  • Rule
  • RuleMapping
  • Node
  • WorkflowDefinition
  • WorkflowInstance
  • WorkflowInstanceSummary
  • HistoryEntry
  • WorkflowState

Metadata models

  • WorkflowActionInfo
  • WorkflowInputProperty
  • WorkflowOutputProperty
  • WorkflowGuardInfo
  • WorkflowRuleInfo

Client models

  • WorkflowClientOptions
  • CreateInstanceRequest
  • TransitionRequest
  • CancelRequest
  • ValidationResult
  • WorkflowNotificationAdminSettings

This makes the package pleasant to use in TypeScript-heavy projects because both component usage and API usage remain strongly typed.


Field system and validation

The field system supports both backend-aligned field types and frontend-friendly validation behavior.

Supported field types

Current public field type support includes:

  • Text
  • TextArea
  • Number
  • Decimal
  • Date
  • DateTime
  • Time
  • Checkbox
  • Radio
  • Dropdown
  • MultiSelect
  • File
  • Image
  • RichText
  • Hidden
  • Email
  • Phone
  • Currency
  • Section
  • Split (starts an optional two-column row; without it, fields stay single column)

File and Image persist as { name, contentType, dataUrl } on instance data (keep under about 4 MB).

Validation behavior

The runtime supports practical validation such as:

  • required checks,
  • min and max values,
  • max length,
  • regex validation,
  • type-based validation for number/date/email/phone/currency.

Field options

For selectable fields, options can come from:

  • static field configuration,
  • backend field option endpoints.

Visibility support

The field model also includes support for visibility expressions and guard-related visibility metadata.

This helps advanced forms stay dynamic without requiring every project to write custom visibility logic from zero.


External form integration

External forms are useful when the workflow step should be completed in another page or system.

Examples:

  • a legacy MVC/Razor page,
  • an older admin form,
  • a third-party hosted screen,
  • a specialized custom data entry module.

Helper: buildExternalFormUrl

This helper creates a URL with workflow context parameters.

Typical values added include:

  • workflowInstanceId
  • workflowNodeId
  • workflowDefinitionId
  • workflowActions
  • workflowCallback

Helper: parseWorkflowParams

Reads workflow context from query string.

Hook: useWorkflowParams

Convenient React wrapper over parseWorkflowParams().

Hook: useWorkflowExternalForm

A higher-level helper for external form pages.

It helps with:

  • reading workflow context,
  • calling transition APIs,
  • managing loading and error state,
  • returning to the callback URL after submission.

Example

import { useWorkflowExternalForm } from 'qp-workflow-react';

function ExternalApprovalPage() {
  const workflow = useWorkflowExternalForm({
    apiUrl: '/api/workflow'
  });

  async function submitApprove() {
    await workflow.submit('approve', {
      note: 'Approved from external page'
    });
  }

  return (
    <div>
      <button onClick={submitApprove} disabled={workflow.loading}>
        Approve
      </button>
      {workflow.error && <p>{workflow.error}</p>}
      {workflow.success && <p>{workflow.success}</p>}
    </div>
  );
}

This is especially useful when not every workflow step should stay inside the main React runner screen.


Localization

The package currently includes English and Turkish locale support.

Basic usage

import { getLocale } from 'qp-workflow-react';

const t = getLocale('en');
console.log(t.common.save);

Provider-based usage

import { LocaleProvider } from 'qp-workflow-react';

<LocaleProvider locale="tr">
  <App />
</LocaleProvider>

Supported locale codes

  • 'en'
  • 'tr'

Where localization is used

Localization is used in areas such as:

  • common labels,
  • runner UI,
  • designer UI,
  • validation messages,
  • action labels,
  • host notification settings modal.

This makes the package easier to adopt in multilingual internal systems.


Backend contract

This package is designed around the Chd.Workflow backend contract.

Expected endpoints

| Method | Path | |---|---| | GET | /definitions | | GET | /definitions/{id} | | POST | /definitions | | PUT | /definitions/{id} | | DELETE | /definitions/{id} | | GET | /instances | | GET | /instances/{id} | | GET | /instances/{id}/state | | GET | /instances/{id}/field-options/{fieldName} | | POST | /instances | | POST | /instances/{id}/transition | | POST | /instances/{id}/validate | | POST | /instances/{id}/cancel | | GET | /actions | | GET | /actions/grouped | | GET | /guards | | GET | /rules | | GET | /rules/grouped | | GET | /rules/{name} | | GET | /admin/notification-settings | | PUT | /admin/notification-settings | | GET | /admin/participant-groups |

JSON style expectations

The package assumes a backend that behaves similarly to the current Chd.Workflow implementation.

In practice, that means:

  • camelCase JSON is preferred,
  • enum values should be serialized in a compatible way,
  • error payloads should include error and optionally errors.

Identity headers used by the sample and demo:

  • X-Workflow-User
  • X-Workflow-Roles

A real host should send a JWT instead. Empty AllowedRoles on a node means anyone can act.

If you build your own compatible backend, the React package can still be reused.


Build and publish

Important package information from the current project setup:

  • package name: qp-workflow-react
  • build tool: tsup
  • output: dist
  • peer dependencies: React 18+

Common commands

npm install
npm run build
npm run dev
npm run typecheck

Publish notes

When publishing, keep these fields correct in package.json:

  • name
  • version
  • description
  • main
  • module
  • types
  • repository
  • license
  • files

These details matter because the package is intended to be consumed as a reusable npm library, not only as a local project.

Runnable host + UI: Chd.Examples. After changing this package, run npm run build so file: consumers see the new dist.


Troubleshooting

Designer cannot load actions or guards

Check that the backend API is running and that:

  • /actions works,
  • /guards works,
  • CORS is configured correctly,
  • the API URL is correct.

Participant groups are empty

Check /admin/participant-groups. If the backend does not implement or register participant directory support, the list may be empty.

Transition fails with validation messages

The backend may be returning field-level validation details. Catch WorkflowClientError and inspect error.errors.

Guard failure is returned from the backend

A denied guard usually comes back with code = "GUARD_FAILED". This means the transition was blocked intentionally by workflow logic.

Notification settings modal returns not available

A 503 usually means the backend host has not enabled the notification admin settings service.

Inbox stays empty

Confirm GET /instances?status=Running and that the current user headers are sent. Rebuild this package if a local file: consumer still shows an old UI.

External form flow does not return properly

Check:

  • query string parameters,
  • callback URL value,
  • transition call success,
  • whether the page is opened in the same window or inside an iframe.

License

MIT License. See LICENSE.


Chd.Workflow · open sample · Architecture.