@kdit/process-flow
v0.1.4
Published
Reusable, decoupled process-flow diagram engine (testcase / execution / automation modes) for BQ apps.
Readme
@kdit/process-flow
Reusable, decoupled process-flow diagram engine shared by the BQ apps
(bq_uxrepository and bqautomationfrontend). Renders swimlane / process flow
diagrams in three modes — testcase, execution, automation — using a
scoped Zustand store and an inversion-of-control props contract.
One source of truth: fix or extend the flow once here, bump the version, and both apps pick it up via
npm.
Install
npm i @kdit/process-flowPeer dependencies
The package does not bundle these — the consuming app provides its single
copy (critical for React, the antd theme, and the @xyflow/react context):
react@^18.3, react-dom@^18.3, antd@^4.8, @xyflow/react@^12.10,
zustand@^4.4 || ^5, styled-components@^5.2, formik@^2.2, yup@^0.32,
lodash@^4.17, lucide-react@^1.11. (@ant-design/icons is optional — it
ships transitively with antd v4.)
Tailwind
The components are styled with Tailwind utility classes. The package ships no
compiled Tailwind CSS — your app's Tailwind build must scan the package output.
Add to tailwind.config.js:
content: [
// ...your globs
"./node_modules/@kdit/process-flow/dist/**/*.js",
],@xyflow/react's stylesheet is imported by the package automatically (your
bundler resolves it from your installed copy) — no manual CSS import needed.
TypeScript
The package is written in TypeScript and ships its own declarations
(exports["."].types), so no @types/... install is needed. The public data
and injection contract is exported as types — e.g.:
import { ProcessFlow, toFlowData } from "@kdit/process-flow";
import type { FlowData, ProcessFlowActions, ProcessFlowMode } from "@kdit/process-flow";Usage
import { ProcessFlow } from "@kdit/process-flow";
<ProcessFlow
mode="testcase" // "testcase" | "execution" | "automation"
data={flowData} // from the package's toFlowData(...)
actions={actions} // your Redux-wired handlers (IoC)
pendingStates={pending}
isLoading={isLoading}
isError={isError}
slots={{ RichTextEditor }} // injected app components (see below)
config={{ videoRecordIcon, screenshotIcons }}
ProcessDetailModal={ProcessDetailModal} // host-specific, injected
/>;See INTEGRATION.md for the full per-app wiring (what each app keeps locally vs. imports from the package) and the publish workflow.
The injection contract ("plug-and-play")
Everything app-specific is provided from the outside. The package owns the generic engine; the consumer owns data, side effects, and design-system pieces.
| Channel | What you pass | Why it's injected |
| --- | --- | --- |
| data | toFlowData(swimlaneData, testCaseId) output | Pure transform shipped by the package; you call it with your Redux/API data |
| actions | ~21 onX handlers (add/edit/delete/connect/move/erase…) | All mutations run in your app (Redux/API). The store wraps them for clipboard/eraser bookkeeping |
| pendingStates | { isAdding, isDeleting, … } | Disable UI during your async mutations |
| slots.RichTextEditor | your Quill component | Apps disagree on react-quill vs react-quill-new; package stays neutral. Falls back to a <textarea> if omitted |
| ProcessDetailModal (prop) | host modal component | Redux + Axios + the step-table subtree are app-specific |
| config.videoRecordIcon | icon URL/asset | Host asset, used by the swimlane video-capture toggle |
| config.screenshotIcons | { single, multiple } (svg/url) | Automation-mode screenshot badge icons; built-in fallback provided |
| slots.ItemStatus (execution) | host status selector | Optional; StepStatusModal has a built-in antd Select fallback |
The injected RichTextEditor must accept the props the modals pass:
{ theme, value, onChange, modules, formats, placeholder }. Use the exported
RICH_TEXT_MODULES / RICH_TEXT_FORMATS to match the original toolbar.
Public API
| Export | Purpose |
| --- | --- |
| ProcessFlow (default + named) | Main entry; selects the mode |
| ProcessFlowCanvas | Lower-level canvas if you build a custom mode |
| toFlowData, findApiSwimlane, findApiProcess, getProcessName, getSwimlaneName | Pure testcase data transforms |
| executionToFlowData | Pure execution data transform |
| NEW_ITEM_ID, resequenceLane, swimlaneSeqReqsForAdd/Delete/Move | Sequencing helpers for your adapter |
| statusIdFromResult, RESULT_TO_STATUS_ID | Automation status mapping |
| RICH_TEXT_MODULES, RICH_TEXT_FORMATS, makeUserOnlyOnChange, makeUserOnlyOnChangeWithLen | Build the injected editor |
| AddStepModal | Reused by the host's ProcessDetailModal |
| StatusPill, AssigneeBadge, ScreenshotIndicator | Reusable mode UI |
| createProcessFlowStore, ProcessFlowStoreProvider, useProcessFlowStore, useProcessFlowStoreApi, useStableStore | Store primitives |
Build
npm run build # vite library build → dist/process-flow.js (+ lazy mode chunks)Execution and automation modes are lazy-loaded, so a testcase-only consumer never eagerly pulls their module graphs.
