@habit.analytics/habit-claims-journey-components
v1.0.10
Published
Visual graph-based journey builder and step-by-step form runner React widgets for claims workflows
Readme
Journey Builder & Form Runner
A visual graph-based form builder and step-by-step form runner, built as two independent, embeddable React widgets.
Builder — drag-and-drop field specs onto a canvas, connect them with conditional edges, and export a portable JourneySpec JSON.
Runner — feed that JSON into a self-contained form engine that navigates users through the journey, evaluates branching conditions, and collects answers.
Architecture
┌─────────────────────────────────────────────────────┐
│ Host Application │
│ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ JourneyBuilderWidget │ │ FormRunnerWidget │ │
│ │ │ │ │ │
│ │ specs ──► Catalog │ │ journey ──► Engine │ │
│ │ Canvas │ │ Widgets │ │
│ │ Props │ │ History │ │
│ │ │ │ Summary │ │
│ │ onSave(journey) ◄── │ │ onSubmit(answers) ◄─ │ │
│ │ onChange(journey) ◄─ │ │ │ │
│ └──────────────────────┘ └──────────────────────┘ │
│ │
│ Both consume JourneySpec + types from │
│ src/types/journey.ts │
└─────────────────────────────────────────────────────┘Tech Stack
| Layer | Technology |
|---|---|
| UI framework | React 18 + TypeScript |
| Graph canvas | @xyflow/react (React Flow v12) |
| State management | Zustand (scoped per widget instance) |
| Edge conditions | json-logic-js |
| Styling | Tailwind CSS + shadcn/ui |
| Build tool | Vite |
Quick Start
# Clone and install
git clone <YOUR_GIT_URL>
cd journey-builder
npm install
# Start dev server
npm run devThe demo app runs at http://localhost:5173:
/— Builder with sample property specs/runner— Runner loaded from the builder's current graph
Installation (as a library)
npm install journey-builderimport {
JourneyBuilderWidget,
FormRunnerWidget,
} from 'journey-builder';
import type {
JourneySpec,
ClaimPropertySpec,
} from 'journey-builder';Usage
JourneyBuilderWidget
The visual graph editor. Provide field specifications and receive the journey graph via callbacks.
import { JourneyBuilderWidget } from 'journey-builder';
function BuilderPage({ specs, existingJourney }) {
return (
<JourneyBuilderWidget
specs={specs}
journey={existingJourney}
onSave={(journey) => saveToApi(journey)}
onChange={(journey) => console.log('Graph changed', journey)}
/>
);
}Props
| Prop | Type | Required | Description |
|---|---|---|---|
| specs | ClaimPropertySpec[] | ✅ | Field specifications shown in the drag-and-drop catalog |
| journey | JourneySpec \| null | — | Existing journey to load on mount |
| onSave | (spec: JourneySpec) => void | — | Called when the user clicks Export/Save |
| onChange | (spec: JourneySpec) => void | — | Called on every graph mutation (node/edge add, move, delete, edit) |
FormRunnerWidget
The step-by-step form engine. Provide a journey spec and receive collected answers.
import { FormRunnerWidget } from 'journey-builder';
function RunnerPage({ journey }) {
return (
<FormRunnerWidget
journey={journey}
onSubmit={(answers) => submitToApi(answers)}
/>
);
}Props
| Prop | Type | Required | Description |
|---|---|---|---|
| journey | JourneySpec | ✅ | The journey graph to run |
| specs | ClaimPropertySpec[] | — | Optional specs for label/schema lookups |
| onSubmit | (answers: Record<string, unknown>) => void | — | Called on form submission. Defaults to copying JSON to clipboard |
Data Types
ClaimPropertySpec
A field definition from your data model.
interface ClaimPropertySpec {
id: string;
namespace: string; // e.g. "insured.full_name"
claimspec_id: string;
parent_id: string | null;
order_index: number;
schema: string; // e.g. "v1_string", "v2_date-1", "v2_currency-1"
label: string; // Human-readable label
options: ClaimPropertySpecOption[] | null;
help_text: string | null;
placeholder: string | null;
// ...additional display fields
}JourneySpec
The portable journey graph format — output of the Builder, input of the Runner.
interface JourneySpec {
journey_id: string;
claimspec_id: string;
version: string;
nodes: JourneySpecNode[];
edges: JourneySpecEdge[];
start_node_id: string | null;
}JourneySpecNode
interface JourneySpecNode {
node_id: string;
question_key: string; // Namespace used as answer key
source_property_spec_id: string;
schema: string;
options?: ClaimPropertySpecOption[];
actor: 'customer' | 'operator';
bindings: { target_namespace: string }[];
ui: { widget: string };
layout: { x: number; y: number };
label_override?: string;
required?: boolean;
}JourneySpecEdge
interface JourneySpecEdge {
edge_id: string;
from_node_id: string;
to_node_id: string;
condition: Record<string, unknown> | null; // JSON Logic expression
priority: number;
is_default: boolean;
}Supported Schema Types
| Schema | Widget | Validation |
|---|---|---|
| v1_string | Text input | — |
| v2_single_option_select-1 | Dropdown select | Must pick an option |
| v2_date-1 | Date picker | Valid date |
| v2_currency-1 | Currency input | Numeric |
| v2_single_asset_upload | File upload | — |
| v2_phone-1 | Phone with country code | Length check |
| v2_email-1 | Email input | Format regex |
Nodes support widget overrides — any field can adopt a different widget (e.g., a string field rendered as an email input).
Builder Features
- Drag-and-drop specs from a searchable, filterable catalog
- Custom nodes — create fields not tied to existing specs
- Visual edge condition editor — AND/OR rules with comparison operators
- Advanced JSON Logic mode — direct editing for complex conditions
- Condition testing panel — validate edge logic with sample data
- Graph validation — detects loops, orphans, missing conditions, duplicate bindings
- Auto-layout — automatic graph arrangement
- Keyboard shortcuts — Delete, Ctrl+Z/Y (undo/redo), Ctrl+C/V (copy/paste), Ctrl+D (duplicate)
- Import/Export — full-fidelity JourneySpec JSON via file upload or paste
- Path highlighting — visual tracking during preview
Runner Features
- Step-by-step navigation with progress bar
- Conditional branching — JSON Logic evaluation at each edge
- Answer history — scrollable list with jump-back navigation
- Schema-aware widgets — renders the correct input for each field type
- Required field enforcement — blocks navigation until valid
- Review screen — summary of all answers before submission
- Bindings propagation — answers auto-mapped to target namespaces
Project Structure
src/
├── index.ts # Barrel exports
├── types/journey.ts # Shared types & schema helpers
├── components/
│ ├── journey-builder/
│ │ ├── JourneyBuilderWidget.tsx # ◀ Entry point widget
│ │ ├── JourneyBuilder.tsx # Layout (catalog + canvas + props panel)
│ │ ├── JourneyCanvas.tsx # React Flow canvas
│ │ ├── QuestionNode.tsx # Custom node component
│ │ ├── SpecsCatalog.tsx # Draggable spec list
│ │ ├── PropertiesPanel.tsx # Node/edge property editors
│ │ ├── NodePropertiesEditor.tsx
│ │ ├── EdgePropertiesEditor.tsx
│ │ ├── ConditionalEdge.tsx # Custom edge with labels
│ │ ├── CreateNodeDialog.tsx # Custom field creation
│ │ ├── ImportJourneyDialog.tsx
│ │ ├── FormPreviewPanel.tsx # Inline preview
│ │ ├── GraphValidationPanel.tsx # Validation results
│ │ ├── edge-editor/ # Condition editing components
│ │ └── preview-widgets/ # Schema-specific input widgets
│ ├── runner/
│ │ ├── FormRunnerWidget.tsx # ◀ Entry point widget
│ │ └── AnswerHistoryList.tsx
│ └── ui/ # shadcn/ui components
├── stores/
│ └── journeyBuilderStore.ts # Zustand store (internal)
├── lib/
│ └── graph-validation.ts # Validation engine
└── pages/ # Demo app pages
├── Index.tsx
└── Runner.tsxLicense
MIT
