@habit.analytics/habit-claims-journey-components 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +296 -0
- package/dist/favicon.ico +0 -0
- package/dist/index.cjs +299 -0
- package/dist/index.mjs +23534 -0
- package/dist/placeholder.svg +1 -0
- package/dist/robots.txt +14 -0
- package/dist/style.css +1 -0
- package/package.json +130 -0
- package/src/index.ts +21 -0
- package/src/types/journey.ts +228 -0
- package/src/types/json-logic-js.d.ts +5 -0
package/README.md
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# Journey Builder & Form Runner
|
|
2
|
+
|
|
3
|
+
A visual graph-based form builder and step-by-step form runner, built as two independent, embeddable React widgets.
|
|
4
|
+
|
|
5
|
+
**Builder** — drag-and-drop field specs onto a canvas, connect them with conditional edges, and export a portable `JourneySpec` JSON.
|
|
6
|
+
|
|
7
|
+
**Runner** — feed that JSON into a self-contained form engine that navigates users through the journey, evaluates branching conditions, and collects answers.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
┌─────────────────────────────────────────────────────┐
|
|
15
|
+
│ Host Application │
|
|
16
|
+
│ │
|
|
17
|
+
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
|
18
|
+
│ │ JourneyBuilderWidget │ │ FormRunnerWidget │ │
|
|
19
|
+
│ │ │ │ │ │
|
|
20
|
+
│ │ specs ──► Catalog │ │ journey ──► Engine │ │
|
|
21
|
+
│ │ Canvas │ │ Widgets │ │
|
|
22
|
+
│ │ Props │ │ History │ │
|
|
23
|
+
│ │ │ │ Summary │ │
|
|
24
|
+
│ │ onSave(journey) ◄── │ │ onSubmit(answers) ◄─ │ │
|
|
25
|
+
│ │ onChange(journey) ◄─ │ │ │ │
|
|
26
|
+
│ └──────────────────────┘ └──────────────────────┘ │
|
|
27
|
+
│ │
|
|
28
|
+
│ Both consume JourneySpec + types from │
|
|
29
|
+
│ src/types/journey.ts │
|
|
30
|
+
└─────────────────────────────────────────────────────┘
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Tech Stack
|
|
36
|
+
|
|
37
|
+
| Layer | Technology |
|
|
38
|
+
|---|---|
|
|
39
|
+
| UI framework | React 18 + TypeScript |
|
|
40
|
+
| Graph canvas | `@xyflow/react` (React Flow v12) |
|
|
41
|
+
| State management | Zustand (scoped per widget instance) |
|
|
42
|
+
| Edge conditions | `json-logic-js` |
|
|
43
|
+
| Styling | Tailwind CSS + shadcn/ui |
|
|
44
|
+
| Build tool | Vite |
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Clone and install
|
|
52
|
+
git clone <YOUR_GIT_URL>
|
|
53
|
+
cd journey-builder
|
|
54
|
+
npm install
|
|
55
|
+
|
|
56
|
+
# Start dev server
|
|
57
|
+
npm run dev
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The demo app runs at `http://localhost:5173`:
|
|
61
|
+
- `/` — Builder with sample property specs
|
|
62
|
+
- `/runner` — Runner loaded from the builder's current graph
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Installation (as a library)
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npm install journey-builder
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import {
|
|
74
|
+
JourneyBuilderWidget,
|
|
75
|
+
FormRunnerWidget,
|
|
76
|
+
} from 'journey-builder';
|
|
77
|
+
|
|
78
|
+
import type {
|
|
79
|
+
JourneySpec,
|
|
80
|
+
ClaimPropertySpec,
|
|
81
|
+
} from 'journey-builder';
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Usage
|
|
87
|
+
|
|
88
|
+
### JourneyBuilderWidget
|
|
89
|
+
|
|
90
|
+
The visual graph editor. Provide field specifications and receive the journey graph via callbacks.
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { JourneyBuilderWidget } from 'journey-builder';
|
|
94
|
+
|
|
95
|
+
function BuilderPage({ specs, existingJourney }) {
|
|
96
|
+
return (
|
|
97
|
+
<JourneyBuilderWidget
|
|
98
|
+
specs={specs}
|
|
99
|
+
journey={existingJourney}
|
|
100
|
+
onSave={(journey) => saveToApi(journey)}
|
|
101
|
+
onChange={(journey) => console.log('Graph changed', journey)}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### Props
|
|
108
|
+
|
|
109
|
+
| Prop | Type | Required | Description |
|
|
110
|
+
|---|---|---|---|
|
|
111
|
+
| `specs` | `ClaimPropertySpec[]` | ✅ | Field specifications shown in the drag-and-drop catalog |
|
|
112
|
+
| `journey` | `JourneySpec \| null` | — | Existing journey to load on mount |
|
|
113
|
+
| `onSave` | `(spec: JourneySpec) => void` | — | Called when the user clicks Export/Save |
|
|
114
|
+
| `onChange` | `(spec: JourneySpec) => void` | — | Called on every graph mutation (node/edge add, move, delete, edit) |
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### FormRunnerWidget
|
|
119
|
+
|
|
120
|
+
The step-by-step form engine. Provide a journey spec and receive collected answers.
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import { FormRunnerWidget } from 'journey-builder';
|
|
124
|
+
|
|
125
|
+
function RunnerPage({ journey }) {
|
|
126
|
+
return (
|
|
127
|
+
<FormRunnerWidget
|
|
128
|
+
journey={journey}
|
|
129
|
+
onSubmit={(answers) => submitToApi(answers)}
|
|
130
|
+
/>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### Props
|
|
136
|
+
|
|
137
|
+
| Prop | Type | Required | Description |
|
|
138
|
+
|---|---|---|---|
|
|
139
|
+
| `journey` | `JourneySpec` | ✅ | The journey graph to run |
|
|
140
|
+
| `specs` | `ClaimPropertySpec[]` | — | Optional specs for label/schema lookups |
|
|
141
|
+
| `onSubmit` | `(answers: Record<string, unknown>) => void` | — | Called on form submission. Defaults to copying JSON to clipboard |
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Data Types
|
|
146
|
+
|
|
147
|
+
### `ClaimPropertySpec`
|
|
148
|
+
|
|
149
|
+
A field definition from your data model.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
interface ClaimPropertySpec {
|
|
153
|
+
id: string;
|
|
154
|
+
namespace: string; // e.g. "insured.full_name"
|
|
155
|
+
claimspec_id: string;
|
|
156
|
+
parent_id: string | null;
|
|
157
|
+
order_index: number;
|
|
158
|
+
schema: string; // e.g. "v1_string", "v2_date-1", "v2_currency-1"
|
|
159
|
+
label: string; // Human-readable label
|
|
160
|
+
options: ClaimPropertySpecOption[] | null;
|
|
161
|
+
help_text: string | null;
|
|
162
|
+
placeholder: string | null;
|
|
163
|
+
// ...additional display fields
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### `JourneySpec`
|
|
168
|
+
|
|
169
|
+
The portable journey graph format — output of the Builder, input of the Runner.
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
interface JourneySpec {
|
|
173
|
+
journey_id: string;
|
|
174
|
+
claimspec_id: string;
|
|
175
|
+
version: string;
|
|
176
|
+
nodes: JourneySpecNode[];
|
|
177
|
+
edges: JourneySpecEdge[];
|
|
178
|
+
start_node_id: string | null;
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### `JourneySpecNode`
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
interface JourneySpecNode {
|
|
186
|
+
node_id: string;
|
|
187
|
+
question_key: string; // Namespace used as answer key
|
|
188
|
+
source_property_spec_id: string;
|
|
189
|
+
schema: string;
|
|
190
|
+
options?: ClaimPropertySpecOption[];
|
|
191
|
+
actor: 'customer' | 'operator';
|
|
192
|
+
bindings: { target_namespace: string }[];
|
|
193
|
+
ui: { widget: string };
|
|
194
|
+
layout: { x: number; y: number };
|
|
195
|
+
label_override?: string;
|
|
196
|
+
required?: boolean;
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### `JourneySpecEdge`
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
interface JourneySpecEdge {
|
|
204
|
+
edge_id: string;
|
|
205
|
+
from_node_id: string;
|
|
206
|
+
to_node_id: string;
|
|
207
|
+
condition: Record<string, unknown> | null; // JSON Logic expression
|
|
208
|
+
priority: number;
|
|
209
|
+
is_default: boolean;
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Supported Schema Types
|
|
216
|
+
|
|
217
|
+
| Schema | Widget | Validation |
|
|
218
|
+
|---|---|---|
|
|
219
|
+
| `v1_string` | Text input | — |
|
|
220
|
+
| `v2_single_option_select-1` | Dropdown select | Must pick an option |
|
|
221
|
+
| `v2_date-1` | Date picker | Valid date |
|
|
222
|
+
| `v2_currency-1` | Currency input | Numeric |
|
|
223
|
+
| `v2_single_asset_upload` | File upload | — |
|
|
224
|
+
| `v2_phone-1` | Phone with country code | Length check |
|
|
225
|
+
| `v2_email-1` | Email input | Format regex |
|
|
226
|
+
|
|
227
|
+
Nodes support **widget overrides** — any field can adopt a different widget (e.g., a string field rendered as an email input).
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Builder Features
|
|
232
|
+
|
|
233
|
+
- **Drag-and-drop** specs from a searchable, filterable catalog
|
|
234
|
+
- **Custom nodes** — create fields not tied to existing specs
|
|
235
|
+
- **Visual edge condition editor** — AND/OR rules with comparison operators
|
|
236
|
+
- **Advanced JSON Logic mode** — direct editing for complex conditions
|
|
237
|
+
- **Condition testing panel** — validate edge logic with sample data
|
|
238
|
+
- **Graph validation** — detects loops, orphans, missing conditions, duplicate bindings
|
|
239
|
+
- **Auto-layout** — automatic graph arrangement
|
|
240
|
+
- **Keyboard shortcuts** — Delete, Ctrl+Z/Y (undo/redo), Ctrl+C/V (copy/paste), Ctrl+D (duplicate)
|
|
241
|
+
- **Import/Export** — full-fidelity JourneySpec JSON via file upload or paste
|
|
242
|
+
- **Path highlighting** — visual tracking during preview
|
|
243
|
+
|
|
244
|
+
## Runner Features
|
|
245
|
+
|
|
246
|
+
- **Step-by-step navigation** with progress bar
|
|
247
|
+
- **Conditional branching** — JSON Logic evaluation at each edge
|
|
248
|
+
- **Answer history** — scrollable list with jump-back navigation
|
|
249
|
+
- **Schema-aware widgets** — renders the correct input for each field type
|
|
250
|
+
- **Required field enforcement** — blocks navigation until valid
|
|
251
|
+
- **Review screen** — summary of all answers before submission
|
|
252
|
+
- **Bindings propagation** — answers auto-mapped to target namespaces
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Project Structure
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
src/
|
|
260
|
+
├── index.ts # Barrel exports
|
|
261
|
+
├── types/journey.ts # Shared types & schema helpers
|
|
262
|
+
├── components/
|
|
263
|
+
│ ├── journey-builder/
|
|
264
|
+
│ │ ├── JourneyBuilderWidget.tsx # ◀ Entry point widget
|
|
265
|
+
│ │ ├── JourneyBuilder.tsx # Layout (catalog + canvas + props panel)
|
|
266
|
+
│ │ ├── JourneyCanvas.tsx # React Flow canvas
|
|
267
|
+
│ │ ├── QuestionNode.tsx # Custom node component
|
|
268
|
+
│ │ ├── SpecsCatalog.tsx # Draggable spec list
|
|
269
|
+
│ │ ├── PropertiesPanel.tsx # Node/edge property editors
|
|
270
|
+
│ │ ├── NodePropertiesEditor.tsx
|
|
271
|
+
│ │ ├── EdgePropertiesEditor.tsx
|
|
272
|
+
│ │ ├── ConditionalEdge.tsx # Custom edge with labels
|
|
273
|
+
│ │ ├── CreateNodeDialog.tsx # Custom field creation
|
|
274
|
+
│ │ ├── ImportJourneyDialog.tsx
|
|
275
|
+
│ │ ├── FormPreviewPanel.tsx # Inline preview
|
|
276
|
+
│ │ ├── GraphValidationPanel.tsx # Validation results
|
|
277
|
+
│ │ ├── edge-editor/ # Condition editing components
|
|
278
|
+
│ │ └── preview-widgets/ # Schema-specific input widgets
|
|
279
|
+
│ ├── runner/
|
|
280
|
+
│ │ ├── FormRunnerWidget.tsx # ◀ Entry point widget
|
|
281
|
+
│ │ └── AnswerHistoryList.tsx
|
|
282
|
+
│ └── ui/ # shadcn/ui components
|
|
283
|
+
├── stores/
|
|
284
|
+
│ └── journeyBuilderStore.ts # Zustand store (internal)
|
|
285
|
+
├── lib/
|
|
286
|
+
│ └── graph-validation.ts # Validation engine
|
|
287
|
+
└── pages/ # Demo app pages
|
|
288
|
+
├── Index.tsx
|
|
289
|
+
└── Runner.tsx
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## License
|
|
295
|
+
|
|
296
|
+
MIT
|
package/dist/favicon.ico
ADDED
|
Binary file
|