@daltonr/pathwrite-react 0.4.0 → 0.6.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 CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  usePath, // React-specific
19
19
  usePathContext, // React-specific
20
20
  PathProvider, // React-specific
21
+ PathEngine, // Re-exported from core (value + type)
21
22
  PathData, // Re-exported from core
22
23
  PathDefinition, // Re-exported from core
23
24
  PathEvent, // Re-exported from core
@@ -54,7 +55,7 @@ function MyPathHost() {
54
55
  <p>Step {snapshot.stepIndex + 1} of {snapshot.stepCount}</p>
55
56
  <button onClick={previous} disabled={snapshot.isNavigating}>Back</button>
56
57
  <button onClick={next} disabled={snapshot.isNavigating}>
57
- {snapshot.isLastStep ? "Finish" : "Next"}
58
+ {snapshot.isLastStep ? "Complete" : "Next"}
58
59
  </button>
59
60
  <button onClick={cancel}>Cancel</button>
60
61
  </>
@@ -106,6 +107,7 @@ function NavButtons() {
106
107
 
107
108
  | Option | Type | Description |
108
109
  |--------|------|-------------|
110
+ | `engine` | `PathEngine` | An externally-managed engine (e.g. from `createPersistedEngine()`). When provided, `usePath` subscribes to it instead of creating a new one; snapshot is seeded immediately from the engine's current state. The caller is responsible for the engine's lifecycle. Must be a stable reference. |
109
111
  | `onEvent` | `(event: PathEvent) => void` | Called for every engine event. The callback ref is kept current — changing it does **not** re-subscribe to the engine. |
110
112
 
111
113
  ### Return value
@@ -187,23 +189,55 @@ import { PathShell } from "@daltonr/pathwrite-react";
187
189
  />
188
190
  ```
189
191
 
192
+ > **⚠️ Important: `steps` Keys Must Match Step IDs**
193
+ >
194
+ > The keys in the `steps` object **must exactly match** the step IDs from your path definition:
195
+ >
196
+ > ```typescript
197
+ > const myPath: PathDefinition = {
198
+ > id: 'signup',
199
+ > steps: [
200
+ > { id: 'details' }, // ← Step ID
201
+ > { id: 'review' } // ← Step ID
202
+ > ]
203
+ > };
204
+ > ```
205
+ >
206
+ > ```tsx
207
+ > <PathShell
208
+ > path={myPath}
209
+ > steps={{
210
+ > details: <DetailsForm />, // ✅ Matches "details" step
211
+ > review: <ReviewPanel />, // ✅ Matches "review" step
212
+ > foo: <FooPanel /> // ❌ No step with id "foo"
213
+ > }}
214
+ > />
215
+ > ```
216
+ >
217
+ > If a key doesn't match any step ID, PathShell will render:
218
+ > **`No content for step "foo"`**
219
+ >
220
+ > **💡 Tip:** Use your IDE's "Go to Definition" on the step ID in your path definition, then copy-paste the exact string when creating the `steps` object. This ensures perfect matching and avoids typos.
221
+
190
222
  ### Props
191
223
 
192
224
  | Prop | Type | Default | Description |
193
225
  |------|------|---------|-------------|
194
226
  | `path` | `PathDefinition` | *required* | The path to run. |
227
+ | `engine` | `PathEngine` | — | An externally-managed engine. When provided, `PathShell` skips its own `start()` and drives the UI from this engine. |
195
228
  | `steps` | `Record<string, ReactNode>` | *required* | Map of step ID → content to render. |
196
229
  | `initialData` | `PathData` | `{}` | Initial data passed to `engine.start()`. |
197
230
  | `autoStart` | `boolean` | `true` | Start the path automatically on mount. |
198
231
  | `onComplete` | `(data: PathData) => void` | — | Called when the path completes. |
199
232
  | `onCancel` | `(data: PathData) => void` | — | Called when the path is cancelled. |
200
233
  | `onEvent` | `(event: PathEvent) => void` | — | Called for every engine event. |
201
- | `backLabel` | `string` | `"Back"` | Back button label. |
234
+ | `backLabel` | `string` | `"Previous"` | Previous button label. |
202
235
  | `nextLabel` | `string` | `"Next"` | Next button label. |
203
- | `finishLabel` | `string` | `"Finish"` | Finish button label (last step). |
236
+ | `completeLabel` | `string` | `"Complete"` | Complete button label (last step). |
204
237
  | `cancelLabel` | `string` | `"Cancel"` | Cancel button label. |
205
238
  | `hideCancel` | `boolean` | `false` | Hide the Cancel button. |
206
- | `hideProgress` | `boolean` | `false` | Hide the progress indicator. |
239
+ | `hideProgress` | `boolean` | `false` | Hide the progress indicator. Also hidden automatically for single-step top-level paths. |
240
+ | `footerLayout` | `"wizard" \| "form" \| "auto"` | `"auto"` | Footer button layout. `"auto"` uses `"form"` for single-step top-level paths, `"wizard"` otherwise. `"wizard"`: Back on left, Cancel+Submit on right. `"form"`: Cancel on left, Submit on right, no Back button. |
207
241
  | `className` | `string` | — | Extra CSS class on the root element. |
208
242
  | `renderHeader` | `(snapshot) => ReactNode` | — | Render prop to replace the progress header. |
209
243
  | `renderFooter` | `(snapshot, actions) => ReactNode` | — | Render prop to replace the navigation footer. |
@@ -223,7 +257,7 @@ Use `renderHeader` and `renderFooter` to replace the built-in progress bar or na
223
257
  <div>
224
258
  <button onClick={actions.previous} disabled={snapshot.isFirstStep}>Back</button>
225
259
  <button onClick={actions.next} disabled={!snapshot.canMoveNext}>
226
- {snapshot.isLastStep ? "Finish" : "Next"}
260
+ {snapshot.isLastStep ? "Complete" : "Next"}
227
261
  </button>
228
262
  </div>
229
263
  )}
@@ -232,6 +266,39 @@ Use `renderHeader` and `renderFooter` to replace the built-in progress bar or na
232
266
 
233
267
  `PathShellActions` contains: `next`, `previous`, `cancel`, `goToStep`, `goToStepChecked`, `setData`, `restart`.
234
268
 
269
+ ### Resetting the path
270
+
271
+ Use the `key` prop to reset `<PathShell>` to step 1. Changing `key` forces React to discard the old component and mount a fresh one — this is idiomatic React and requires no new API:
272
+
273
+ ```tsx
274
+ const [formKey, setFormKey] = useState(0);
275
+
276
+ <PathShell
277
+ key={formKey}
278
+ path={myPath}
279
+ initialData={{ name: "" }}
280
+ onComplete={handleDone}
281
+ steps={{ details: <DetailsForm /> }}
282
+ />
283
+
284
+ <button onClick={() => setFormKey(k => k + 1)}>Try Again</button>
285
+ ```
286
+
287
+ Incrementing `formKey` discards the old shell and mounts a completely fresh one — path engine, child component state, and DOM are all reset.
288
+
289
+ If your "Try Again" button is inside the success/cancelled panel you conditionally render after completion, the pattern is even simpler:
290
+
291
+ ```tsx
292
+ const [isActive, setIsActive] = useState(true);
293
+
294
+ {isActive
295
+ ? <PathShell path={myPath} onComplete={() => setIsActive(false)} steps={...} />
296
+ : <SuccessPanel onRetry={() => setIsActive(true)} />
297
+ }
298
+ ```
299
+
300
+ React function components have no instance, so there is no `ref.restart()` method. The `key` prop achieves the same result and is the React-idiomatic way to reset any component tree.
301
+
235
302
  ### Context sharing
236
303
 
237
304
  `<PathShell>` provides a path context automatically — step components rendered inside it can call `usePathContext()` without a separate `<PathProvider>`:
package/dist/index.d.ts CHANGED
@@ -1,7 +1,18 @@
1
1
  import type { PropsWithChildren, ReactElement, ReactNode } from "react";
2
- import { PathData, PathDefinition, PathEvent, PathSnapshot } from "@daltonr/pathwrite-core";
2
+ import { PathData, PathDefinition, PathEngine, PathEvent, PathSnapshot } from "@daltonr/pathwrite-core";
3
3
  export interface UsePathOptions {
4
- /** Called for every engine event (stateChanged, completed, cancelled, resumed). */
4
+ /**
5
+ * An externally-managed `PathEngine` to subscribe to — for example, the engine
6
+ * returned by `createPersistedEngine()` from `@daltonr/pathwrite-store-http`.
7
+ *
8
+ * When provided:
9
+ * - `usePath` will **not** create its own engine.
10
+ * - The snapshot is seeded immediately from the engine's current state.
11
+ * - The engine lifecycle (start / cleanup) is the **caller's responsibility**.
12
+ * - `PathShell` will skip its own `autoStart` call.
13
+ */
14
+ engine?: PathEngine;
15
+ /** Called for every engine event (stateChanged, completed, cancelled, resumed). The callback ref is kept current — changing it does **not** re-subscribe to the engine. */
5
16
  onEvent?: (event: PathEvent) => void;
6
17
  }
7
18
  export interface UsePathReturn<TData extends PathData = PathData> {
@@ -51,6 +62,12 @@ export declare function usePathContext<TData extends PathData = PathData>(): Use
51
62
  export interface PathShellProps {
52
63
  /** The path definition to drive. */
53
64
  path: PathDefinition<any>;
65
+ /**
66
+ * An externally-managed engine — for example, the engine returned by
67
+ * `createPersistedEngine()`. When supplied, `PathShell` will skip its own
68
+ * `start()` call and drive the UI from the provided engine instead.
69
+ */
70
+ engine?: PathEngine;
54
71
  /** Map of step ID → content. The shell renders `steps[snapshot.stepId]` for the current step. */
55
72
  steps: Record<string, ReactNode>;
56
73
  /** Initial data passed to `engine.start()`. */
@@ -63,18 +80,25 @@ export interface PathShellProps {
63
80
  onCancel?: (data: PathData) => void;
64
81
  /** Called for every engine event. */
65
82
  onEvent?: (event: PathEvent) => void;
66
- /** Label for the Back button. Defaults to `"Back"`. */
83
+ /** Label for the Previous button. Defaults to `"Previous"`. */
67
84
  backLabel?: string;
68
85
  /** Label for the Next button. Defaults to `"Next"`. */
69
86
  nextLabel?: string;
70
- /** Label for the Finish button (shown on the last step). Defaults to `"Finish"`. */
71
- finishLabel?: string;
87
+ /** Label for the Complete button (shown on the last step). Defaults to `"Complete"`. */
88
+ completeLabel?: string;
72
89
  /** Label for the Cancel button. Defaults to `"Cancel"`. */
73
90
  cancelLabel?: string;
74
91
  /** If true, hide the Cancel button. Defaults to `false`. */
75
92
  hideCancel?: boolean;
76
- /** If true, hide the progress indicator. Defaults to `false`. */
93
+ /** If true, hide the progress indicator. Also hidden automatically when the path has only one step. Defaults to `false`. */
77
94
  hideProgress?: boolean;
95
+ /**
96
+ * Footer layout mode:
97
+ * - `"auto"` (default): Uses "form" for single-step top-level paths, "wizard" otherwise.
98
+ * - `"wizard"`: Back button on left, Cancel and Submit together on right.
99
+ * - `"form"`: Cancel on left, Submit alone on right. Back button never shown.
100
+ */
101
+ footerLayout?: "wizard" | "form" | "auto";
78
102
  /** Optional extra CSS class on the root element. */
79
103
  className?: string;
80
104
  /** Render prop to replace the entire header (progress area). Receives the snapshot. */
@@ -108,5 +132,6 @@ export interface PathShellActions {
108
132
  * />
109
133
  * ```
110
134
  */
111
- export declare function PathShell({ path: pathDef, steps, initialData, autoStart, onComplete, onCancel, onEvent, backLabel, nextLabel, finishLabel, cancelLabel, hideCancel, hideProgress, className, renderHeader, renderFooter, }: PathShellProps): ReactElement;
112
- export type { PathData, PathDefinition, PathEvent, PathSnapshot, PathStep, PathStepContext, SerializedPathState } from "@daltonr/pathwrite-core";
135
+ export declare function PathShell({ path: pathDef, engine: externalEngine, steps, initialData, autoStart, onComplete, onCancel, onEvent, backLabel, nextLabel, completeLabel, cancelLabel, hideCancel, hideProgress, footerLayout, className, renderHeader, renderFooter, }: PathShellProps): ReactElement;
136
+ export type { PathData, FieldErrors, PathDefinition, PathEvent, PathSnapshot, PathStep, PathStepContext, SerializedPathState } from "@daltonr/pathwrite-core";
137
+ export { PathEngine } from "@daltonr/pathwrite-core";
package/dist/index.js CHANGED
@@ -4,17 +4,31 @@ import { PathEngine } from "@daltonr/pathwrite-core";
4
4
  // usePath hook
5
5
  // ---------------------------------------------------------------------------
6
6
  export function usePath(options) {
7
- // Stable engine instance for the lifetime of the hook
7
+ // Use provided engine or create a stable new one for this hook's lifetime.
8
+ // options.engine must be a stable reference (don't recreate on every render).
8
9
  const engineRef = useRef(null);
9
10
  if (engineRef.current === null) {
10
- engineRef.current = new PathEngine();
11
+ engineRef.current = options?.engine ?? new PathEngine();
11
12
  }
12
13
  const engine = engineRef.current;
13
14
  // Keep the onEvent callback current without changing the subscribe identity
14
15
  const onEventRef = useRef(options?.onEvent);
15
16
  onEventRef.current = options?.onEvent;
16
- // Cached snapshot updated only inside the subscribe callback
17
+ // Seed immediately from existing engine state essential when restoring a
18
+ // persisted path (the engine is already started before usePath is called).
19
+ // We track whether we've seeded to avoid calling engine.snapshot() on every
20
+ // re-render (React evaluates useRef's argument each time).
21
+ const seededRef = useRef(false);
17
22
  const snapshotRef = useRef(null);
23
+ if (!seededRef.current) {
24
+ seededRef.current = true;
25
+ try {
26
+ snapshotRef.current = engine.snapshot();
27
+ }
28
+ catch {
29
+ snapshotRef.current = null;
30
+ }
31
+ }
18
32
  const subscribe = useCallback((callback) => engine.subscribe((event) => {
19
33
  if (event.type === "stateChanged" || event.type === "resumed") {
20
34
  snapshotRef.current = event.snapshot;
@@ -65,6 +79,14 @@ export function usePathContext() {
65
79
  }
66
80
  return ctx;
67
81
  }
82
+ // ---------------------------------------------------------------------------
83
+ // Helpers
84
+ // ---------------------------------------------------------------------------
85
+ /** Converts a camelCase or lowercase field key to a display label.
86
+ * e.g. "firstName" → "First Name", "email" → "Email" */
87
+ function formatFieldKey(key) {
88
+ return key.replace(/([A-Z])/g, " $1").replace(/^./, c => c.toUpperCase()).trim();
89
+ }
68
90
  /**
69
91
  * Default UI shell that renders a progress indicator, step content, and navigation
70
92
  * buttons. Pass a `steps` map to define per-step content.
@@ -81,8 +103,9 @@ export function usePathContext() {
81
103
  * />
82
104
  * ```
83
105
  */
84
- export function PathShell({ path: pathDef, steps, initialData = {}, autoStart = true, onComplete, onCancel, onEvent, backLabel = "Back", nextLabel = "Next", finishLabel = "Finish", cancelLabel = "Cancel", hideCancel = false, hideProgress = false, className, renderHeader, renderFooter, }) {
106
+ export function PathShell({ path: pathDef, engine: externalEngine, steps, initialData = {}, autoStart = true, onComplete, onCancel, onEvent, backLabel = "Previous", nextLabel = "Next", completeLabel = "Complete", cancelLabel = "Cancel", hideCancel = false, hideProgress = false, footerLayout = "auto", className, renderHeader, renderFooter, }) {
85
107
  const pathReturn = usePath({
108
+ engine: externalEngine,
86
109
  onEvent(event) {
87
110
  onEvent?.(event);
88
111
  if (event.type === "completed")
@@ -92,10 +115,11 @@ export function PathShell({ path: pathDef, steps, initialData = {}, autoStart =
92
115
  }
93
116
  });
94
117
  const { snapshot, start, next, previous, cancel, goToStep, goToStepChecked, setData, restart } = pathReturn;
95
- // Auto-start on mount
118
+ // Auto-start on mount — skipped when an external engine is provided since
119
+ // the caller is responsible for starting it (e.g. via createPersistedEngine).
96
120
  const startedRef = useRef(false);
97
121
  useEffect(() => {
98
- if (autoStart && !startedRef.current) {
122
+ if (autoStart && !startedRef.current && !externalEngine) {
99
123
  startedRef.current = true;
100
124
  start(pathDef, initialData);
101
125
  }
@@ -118,16 +142,16 @@ export function PathShell({ path: pathDef, steps, initialData = {}, autoStart =
118
142
  // Header — progress indicator
119
143
  !hideProgress && (renderHeader
120
144
  ? renderHeader(snapshot)
121
- : defaultHeader(snapshot)),
145
+ : (snapshot.stepCount > 1 || snapshot.nestingLevel > 0) && defaultHeader(snapshot)),
122
146
  // Body — step content
123
147
  createElement("div", { className: "pw-shell__body" }, stepContent),
124
- // Validation messages
125
- snapshot.validationMessages.length > 0 && createElement("ul", { className: "pw-shell__validation" }, ...snapshot.validationMessages.map((msg, i) => createElement("li", { key: i, className: "pw-shell__validation-item" }, msg))),
148
+ // Validation messages — labeled by field name
149
+ snapshot.hasAttemptedNext && Object.keys(snapshot.fieldMessages).length > 0 && createElement("ul", { className: "pw-shell__validation" }, ...Object.entries(snapshot.fieldMessages).map(([key, msg]) => createElement("li", { key, className: "pw-shell__validation-item" }, key !== "_" && createElement("span", { className: "pw-shell__validation-label" }, formatFieldKey(key)), msg))),
126
150
  // Footer — navigation buttons
127
151
  renderFooter
128
152
  ? renderFooter(snapshot, actions)
129
153
  : defaultFooter(snapshot, actions, {
130
- backLabel, nextLabel, finishLabel, cancelLabel, hideCancel
154
+ backLabel, nextLabel, completeLabel, cancelLabel, hideCancel, footerLayout
131
155
  })));
132
156
  }
133
157
  // ---------------------------------------------------------------------------
@@ -143,22 +167,40 @@ function defaultHeader(snapshot) {
143
167
  })));
144
168
  }
145
169
  function defaultFooter(snapshot, actions, labels) {
146
- return createElement("div", { className: "pw-shell__footer" }, createElement("div", { className: "pw-shell__footer-left" }, !snapshot.isFirstStep && createElement("button", {
170
+ // Auto-detect layout: single-step top-level paths use "form", everything else uses "wizard"
171
+ const resolvedLayout = labels.footerLayout === "auto"
172
+ ? (snapshot.stepCount === 1 && snapshot.nestingLevel === 0 ? "form" : "wizard")
173
+ : labels.footerLayout;
174
+ const isFormMode = resolvedLayout === "form";
175
+ return createElement("div", { className: "pw-shell__footer" }, createElement("div", { className: "pw-shell__footer-left" },
176
+ // Form mode: Cancel on the left
177
+ isFormMode && !labels.hideCancel && createElement("button", {
178
+ type: "button",
179
+ className: "pw-shell__btn pw-shell__btn--cancel",
180
+ disabled: snapshot.isNavigating,
181
+ onClick: actions.cancel
182
+ }, labels.cancelLabel),
183
+ // Wizard mode: Back on the left
184
+ !isFormMode && !snapshot.isFirstStep && createElement("button", {
147
185
  type: "button",
148
186
  className: "pw-shell__btn pw-shell__btn--back",
149
187
  disabled: snapshot.isNavigating || !snapshot.canMovePrevious,
150
188
  onClick: actions.previous
151
- }, labels.backLabel)), createElement("div", { className: "pw-shell__footer-right" }, !labels.hideCancel && createElement("button", {
189
+ }, labels.backLabel)), createElement("div", { className: "pw-shell__footer-right" },
190
+ // Wizard mode: Cancel on the right
191
+ !isFormMode && !labels.hideCancel && createElement("button", {
152
192
  type: "button",
153
193
  className: "pw-shell__btn pw-shell__btn--cancel",
154
194
  disabled: snapshot.isNavigating,
155
195
  onClick: actions.cancel
156
- }, labels.cancelLabel), createElement("button", {
196
+ }, labels.cancelLabel),
197
+ // Both modes: Submit on the right
198
+ createElement("button", {
157
199
  type: "button",
158
200
  className: "pw-shell__btn pw-shell__btn--next",
159
- disabled: snapshot.isNavigating || !snapshot.canMoveNext,
201
+ disabled: snapshot.isNavigating,
160
202
  onClick: actions.next
161
- }, snapshot.isLastStep ? labels.finishLabel : labels.nextLabel)));
203
+ }, snapshot.isLastStep ? labels.completeLabel : labels.nextLabel)));
162
204
  }
163
205
  // ---------------------------------------------------------------------------
164
206
  // Helpers
@@ -166,4 +208,5 @@ function defaultFooter(snapshot, actions, labels) {
166
208
  function cls(...parts) {
167
209
  return parts.filter(Boolean).join(" ");
168
210
  }
211
+ export { PathEngine } from "@daltonr/pathwrite-core";
169
212
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daltonr/pathwrite-react",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "React adapter for @daltonr/pathwrite-core — hooks, context provider, and optional <PathShell> default UI.",
@@ -26,7 +26,8 @@
26
26
  "types": "./dist/index.d.ts",
27
27
  "import": "./dist/index.js"
28
28
  },
29
- "./styles.css": "./dist/index.css"
29
+ "./styles.css": "./dist/index.css",
30
+ "./dist/index.css": "./dist/index.css"
30
31
  },
31
32
  "main": "dist/index.js",
32
33
  "types": "dist/index.d.ts",
@@ -45,7 +46,7 @@
45
46
  "react": ">=18.0.0"
46
47
  },
47
48
  "dependencies": {
48
- "@daltonr/pathwrite-core": "^0.4.0"
49
+ "@daltonr/pathwrite-core": "^0.6.0"
49
50
  },
50
51
  "devDependencies": {
51
52
  "react": "^18.3.1",
package/src/index.ts CHANGED
@@ -21,7 +21,18 @@ import {
21
21
  // ---------------------------------------------------------------------------
22
22
 
23
23
  export interface UsePathOptions {
24
- /** Called for every engine event (stateChanged, completed, cancelled, resumed). */
24
+ /**
25
+ * An externally-managed `PathEngine` to subscribe to — for example, the engine
26
+ * returned by `createPersistedEngine()` from `@daltonr/pathwrite-store-http`.
27
+ *
28
+ * When provided:
29
+ * - `usePath` will **not** create its own engine.
30
+ * - The snapshot is seeded immediately from the engine's current state.
31
+ * - The engine lifecycle (start / cleanup) is the **caller's responsibility**.
32
+ * - `PathShell` will skip its own `autoStart` call.
33
+ */
34
+ engine?: PathEngine;
35
+ /** Called for every engine event (stateChanged, completed, cancelled, resumed). The callback ref is kept current — changing it does **not** re-subscribe to the engine. */
25
36
  onEvent?: (event: PathEvent) => void;
26
37
  }
27
38
 
@@ -62,10 +73,11 @@ export type PathProviderProps = PropsWithChildren<{
62
73
  // ---------------------------------------------------------------------------
63
74
 
64
75
  export function usePath<TData extends PathData = PathData>(options?: UsePathOptions): UsePathReturn<TData> {
65
- // Stable engine instance for the lifetime of the hook
76
+ // Use provided engine or create a stable new one for this hook's lifetime.
77
+ // options.engine must be a stable reference (don't recreate on every render).
66
78
  const engineRef = useRef<PathEngine | null>(null);
67
79
  if (engineRef.current === null) {
68
- engineRef.current = new PathEngine();
80
+ engineRef.current = options?.engine ?? new PathEngine();
69
81
  }
70
82
  const engine = engineRef.current;
71
83
 
@@ -73,8 +85,20 @@ export function usePath<TData extends PathData = PathData>(options?: UsePathOpti
73
85
  const onEventRef = useRef(options?.onEvent);
74
86
  onEventRef.current = options?.onEvent;
75
87
 
76
- // Cached snapshot updated only inside the subscribe callback
88
+ // Seed immediately from existing engine state essential when restoring a
89
+ // persisted path (the engine is already started before usePath is called).
90
+ // We track whether we've seeded to avoid calling engine.snapshot() on every
91
+ // re-render (React evaluates useRef's argument each time).
92
+ const seededRef = useRef(false);
77
93
  const snapshotRef = useRef<PathSnapshot<TData> | null>(null);
94
+ if (!seededRef.current) {
95
+ seededRef.current = true;
96
+ try {
97
+ snapshotRef.current = engine.snapshot() as PathSnapshot<TData> | null;
98
+ } catch {
99
+ snapshotRef.current = null;
100
+ }
101
+ }
78
102
 
79
103
  const subscribe = useCallback(
80
104
  (callback: () => void) =>
@@ -165,6 +189,16 @@ export function usePathContext<TData extends PathData = PathData>(): UsePathRetu
165
189
  return ctx as UsePathReturn<TData>;
166
190
  }
167
191
 
192
+ // ---------------------------------------------------------------------------
193
+ // Helpers
194
+ // ---------------------------------------------------------------------------
195
+
196
+ /** Converts a camelCase or lowercase field key to a display label.
197
+ * e.g. "firstName" → "First Name", "email" → "Email" */
198
+ function formatFieldKey(key: string): string {
199
+ return key.replace(/([A-Z])/g, " $1").replace(/^./, c => c.toUpperCase()).trim();
200
+ }
201
+
168
202
  // ---------------------------------------------------------------------------
169
203
  // Default UI — PathShell
170
204
  // ---------------------------------------------------------------------------
@@ -172,6 +206,12 @@ export function usePathContext<TData extends PathData = PathData>(): UsePathRetu
172
206
  export interface PathShellProps {
173
207
  /** The path definition to drive. */
174
208
  path: PathDefinition<any>;
209
+ /**
210
+ * An externally-managed engine — for example, the engine returned by
211
+ * `createPersistedEngine()`. When supplied, `PathShell` will skip its own
212
+ * `start()` call and drive the UI from the provided engine instead.
213
+ */
214
+ engine?: PathEngine;
175
215
  /** Map of step ID → content. The shell renders `steps[snapshot.stepId]` for the current step. */
176
216
  steps: Record<string, ReactNode>;
177
217
  /** Initial data passed to `engine.start()`. */
@@ -184,18 +224,25 @@ export interface PathShellProps {
184
224
  onCancel?: (data: PathData) => void;
185
225
  /** Called for every engine event. */
186
226
  onEvent?: (event: PathEvent) => void;
187
- /** Label for the Back button. Defaults to `"Back"`. */
227
+ /** Label for the Previous button. Defaults to `"Previous"`. */
188
228
  backLabel?: string;
189
229
  /** Label for the Next button. Defaults to `"Next"`. */
190
230
  nextLabel?: string;
191
- /** Label for the Finish button (shown on the last step). Defaults to `"Finish"`. */
192
- finishLabel?: string;
231
+ /** Label for the Complete button (shown on the last step). Defaults to `"Complete"`. */
232
+ completeLabel?: string;
193
233
  /** Label for the Cancel button. Defaults to `"Cancel"`. */
194
234
  cancelLabel?: string;
195
235
  /** If true, hide the Cancel button. Defaults to `false`. */
196
236
  hideCancel?: boolean;
197
- /** If true, hide the progress indicator. Defaults to `false`. */
237
+ /** If true, hide the progress indicator. Also hidden automatically when the path has only one step. Defaults to `false`. */
198
238
  hideProgress?: boolean;
239
+ /**
240
+ * Footer layout mode:
241
+ * - `"auto"` (default): Uses "form" for single-step top-level paths, "wizard" otherwise.
242
+ * - `"wizard"`: Back button on left, Cancel and Submit together on right.
243
+ * - `"form"`: Cancel on left, Submit alone on right. Back button never shown.
244
+ */
245
+ footerLayout?: "wizard" | "form" | "auto";
199
246
  /** Optional extra CSS class on the root element. */
200
247
  className?: string;
201
248
  /** Render prop to replace the entire header (progress area). Receives the snapshot. */
@@ -233,23 +280,26 @@ export interface PathShellActions {
233
280
  */
234
281
  export function PathShell({
235
282
  path: pathDef,
283
+ engine: externalEngine,
236
284
  steps,
237
285
  initialData = {},
238
286
  autoStart = true,
239
287
  onComplete,
240
288
  onCancel,
241
289
  onEvent,
242
- backLabel = "Back",
290
+ backLabel = "Previous",
243
291
  nextLabel = "Next",
244
- finishLabel = "Finish",
292
+ completeLabel = "Complete",
245
293
  cancelLabel = "Cancel",
246
294
  hideCancel = false,
247
295
  hideProgress = false,
296
+ footerLayout = "auto",
248
297
  className,
249
298
  renderHeader,
250
299
  renderFooter,
251
300
  }: PathShellProps): ReactElement {
252
301
  const pathReturn = usePath({
302
+ engine: externalEngine,
253
303
  onEvent(event) {
254
304
  onEvent?.(event);
255
305
  if (event.type === "completed") onComplete?.(event.data);
@@ -259,10 +309,11 @@ export function PathShell({
259
309
 
260
310
  const { snapshot, start, next, previous, cancel, goToStep, goToStepChecked, setData, restart } = pathReturn;
261
311
 
262
- // Auto-start on mount
312
+ // Auto-start on mount — skipped when an external engine is provided since
313
+ // the caller is responsible for starting it (e.g. via createPersistedEngine).
263
314
  const startedRef = useRef(false);
264
315
  useEffect(() => {
265
- if (autoStart && !startedRef.current) {
316
+ if (autoStart && !startedRef.current && !externalEngine) {
266
317
  startedRef.current = true;
267
318
  start(pathDef, initialData);
268
319
  }
@@ -297,20 +348,23 @@ export function PathShell({
297
348
  // Header — progress indicator
298
349
  !hideProgress && (renderHeader
299
350
  ? renderHeader(snapshot)
300
- : defaultHeader(snapshot)),
351
+ : (snapshot.stepCount > 1 || snapshot.nestingLevel > 0) && defaultHeader(snapshot)),
301
352
  // Body — step content
302
353
  createElement("div", { className: "pw-shell__body" }, stepContent),
303
- // Validation messages
304
- snapshot.validationMessages.length > 0 && createElement("ul", { className: "pw-shell__validation" },
305
- ...snapshot.validationMessages.map((msg, i) =>
306
- createElement("li", { key: i, className: "pw-shell__validation-item" }, msg)
354
+ // Validation messages — labeled by field name
355
+ snapshot.hasAttemptedNext && Object.keys(snapshot.fieldMessages).length > 0 && createElement("ul", { className: "pw-shell__validation" },
356
+ ...Object.entries(snapshot.fieldMessages).map(([key, msg]) =>
357
+ createElement("li", { key, className: "pw-shell__validation-item" },
358
+ key !== "_" && createElement("span", { className: "pw-shell__validation-label" }, formatFieldKey(key)),
359
+ msg
360
+ )
307
361
  )
308
362
  ),
309
363
  // Footer — navigation buttons
310
364
  renderFooter
311
365
  ? renderFooter(snapshot, actions)
312
366
  : defaultFooter(snapshot, actions, {
313
- backLabel, nextLabel, finishLabel, cancelLabel, hideCancel
367
+ backLabel, nextLabel, completeLabel, cancelLabel, hideCancel, footerLayout
314
368
  })
315
369
  )
316
370
  );
@@ -353,9 +407,10 @@ function defaultHeader(snapshot: PathSnapshot): ReactElement {
353
407
  interface FooterLabels {
354
408
  backLabel: string;
355
409
  nextLabel: string;
356
- finishLabel: string;
410
+ completeLabel: string;
357
411
  cancelLabel: string;
358
412
  hideCancel: boolean;
413
+ footerLayout: "wizard" | "form" | "auto";
359
414
  }
360
415
 
361
416
  function defaultFooter(
@@ -363,9 +418,24 @@ function defaultFooter(
363
418
  actions: PathShellActions,
364
419
  labels: FooterLabels
365
420
  ): ReactElement {
421
+ // Auto-detect layout: single-step top-level paths use "form", everything else uses "wizard"
422
+ const resolvedLayout = labels.footerLayout === "auto"
423
+ ? (snapshot.stepCount === 1 && snapshot.nestingLevel === 0 ? "form" : "wizard")
424
+ : labels.footerLayout;
425
+
426
+ const isFormMode = resolvedLayout === "form";
427
+
366
428
  return createElement("div", { className: "pw-shell__footer" },
367
429
  createElement("div", { className: "pw-shell__footer-left" },
368
- !snapshot.isFirstStep && createElement("button", {
430
+ // Form mode: Cancel on the left
431
+ isFormMode && !labels.hideCancel && createElement("button", {
432
+ type: "button",
433
+ className: "pw-shell__btn pw-shell__btn--cancel",
434
+ disabled: snapshot.isNavigating,
435
+ onClick: actions.cancel
436
+ }, labels.cancelLabel),
437
+ // Wizard mode: Back on the left
438
+ !isFormMode && !snapshot.isFirstStep && createElement("button", {
369
439
  type: "button",
370
440
  className: "pw-shell__btn pw-shell__btn--back",
371
441
  disabled: snapshot.isNavigating || !snapshot.canMovePrevious,
@@ -373,18 +443,20 @@ function defaultFooter(
373
443
  }, labels.backLabel)
374
444
  ),
375
445
  createElement("div", { className: "pw-shell__footer-right" },
376
- !labels.hideCancel && createElement("button", {
446
+ // Wizard mode: Cancel on the right
447
+ !isFormMode && !labels.hideCancel && createElement("button", {
377
448
  type: "button",
378
449
  className: "pw-shell__btn pw-shell__btn--cancel",
379
450
  disabled: snapshot.isNavigating,
380
451
  onClick: actions.cancel
381
452
  }, labels.cancelLabel),
453
+ // Both modes: Submit on the right
382
454
  createElement("button", {
383
455
  type: "button",
384
456
  className: "pw-shell__btn pw-shell__btn--next",
385
- disabled: snapshot.isNavigating || !snapshot.canMoveNext,
457
+ disabled: snapshot.isNavigating,
386
458
  onClick: actions.next
387
- }, snapshot.isLastStep ? labels.finishLabel : labels.nextLabel)
459
+ }, snapshot.isLastStep ? labels.completeLabel : labels.nextLabel)
388
460
  )
389
461
  );
390
462
  }
@@ -403,6 +475,7 @@ function cls(...parts: (string | undefined | false | null)[]): string {
403
475
 
404
476
  export type {
405
477
  PathData,
478
+ FieldErrors,
406
479
  PathDefinition,
407
480
  PathEvent,
408
481
  PathSnapshot,
@@ -411,3 +484,5 @@ export type {
411
484
  SerializedPathState
412
485
  } from "@daltonr/pathwrite-core";
413
486
 
487
+ export { PathEngine } from "@daltonr/pathwrite-core";
488
+