@daltonr/pathwrite-react 0.4.0 → 0.5.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 +7 -4
- package/dist/index.d.ts +24 -6
- package/dist/index.js +25 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +49 -14
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 ? "
|
|
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
|
|
@@ -192,15 +194,16 @@ import { PathShell } from "@daltonr/pathwrite-react";
|
|
|
192
194
|
| Prop | Type | Default | Description |
|
|
193
195
|
|------|------|---------|-------------|
|
|
194
196
|
| `path` | `PathDefinition` | *required* | The path to run. |
|
|
197
|
+
| `engine` | `PathEngine` | — | An externally-managed engine. When provided, `PathShell` skips its own `start()` and drives the UI from this engine. |
|
|
195
198
|
| `steps` | `Record<string, ReactNode>` | *required* | Map of step ID → content to render. |
|
|
196
199
|
| `initialData` | `PathData` | `{}` | Initial data passed to `engine.start()`. |
|
|
197
200
|
| `autoStart` | `boolean` | `true` | Start the path automatically on mount. |
|
|
198
201
|
| `onComplete` | `(data: PathData) => void` | — | Called when the path completes. |
|
|
199
202
|
| `onCancel` | `(data: PathData) => void` | — | Called when the path is cancelled. |
|
|
200
203
|
| `onEvent` | `(event: PathEvent) => void` | — | Called for every engine event. |
|
|
201
|
-
| `backLabel` | `string` | `"
|
|
204
|
+
| `backLabel` | `string` | `"Previous"` | Previous button label. |
|
|
202
205
|
| `nextLabel` | `string` | `"Next"` | Next button label. |
|
|
203
|
-
| `
|
|
206
|
+
| `completeLabel` | `string` | `"Complete"` | Complete button label (last step). |
|
|
204
207
|
| `cancelLabel` | `string` | `"Cancel"` | Cancel button label. |
|
|
205
208
|
| `hideCancel` | `boolean` | `false` | Hide the Cancel button. |
|
|
206
209
|
| `hideProgress` | `boolean` | `false` | Hide the progress indicator. |
|
|
@@ -223,7 +226,7 @@ Use `renderHeader` and `renderFooter` to replace the built-in progress bar or na
|
|
|
223
226
|
<div>
|
|
224
227
|
<button onClick={actions.previous} disabled={snapshot.isFirstStep}>Back</button>
|
|
225
228
|
<button onClick={actions.next} disabled={!snapshot.canMoveNext}>
|
|
226
|
-
{snapshot.isLastStep ? "
|
|
229
|
+
{snapshot.isLastStep ? "Complete" : "Next"}
|
|
227
230
|
</button>
|
|
228
231
|
</div>
|
|
229
232
|
)}
|
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
|
-
/**
|
|
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,12 +80,12 @@ 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
|
|
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
|
|
71
|
-
|
|
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`. */
|
|
@@ -108,5 +125,6 @@ export interface PathShellActions {
|
|
|
108
125
|
* />
|
|
109
126
|
* ```
|
|
110
127
|
*/
|
|
111
|
-
export declare function PathShell({ path: pathDef, steps, initialData, autoStart, onComplete, onCancel, onEvent, backLabel, nextLabel,
|
|
128
|
+
export declare function PathShell({ path: pathDef, engine: externalEngine, steps, initialData, autoStart, onComplete, onCancel, onEvent, backLabel, nextLabel, completeLabel, cancelLabel, hideCancel, hideProgress, className, renderHeader, renderFooter, }: PathShellProps): ReactElement;
|
|
112
129
|
export type { PathData, PathDefinition, PathEvent, PathSnapshot, PathStep, PathStepContext, SerializedPathState } from "@daltonr/pathwrite-core";
|
|
130
|
+
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
|
-
//
|
|
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
|
-
//
|
|
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;
|
|
@@ -81,8 +95,9 @@ export function usePathContext() {
|
|
|
81
95
|
* />
|
|
82
96
|
* ```
|
|
83
97
|
*/
|
|
84
|
-
export function PathShell({ path: pathDef, steps, initialData = {}, autoStart = true, onComplete, onCancel, onEvent, backLabel = "
|
|
98
|
+
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, className, renderHeader, renderFooter, }) {
|
|
85
99
|
const pathReturn = usePath({
|
|
100
|
+
engine: externalEngine,
|
|
86
101
|
onEvent(event) {
|
|
87
102
|
onEvent?.(event);
|
|
88
103
|
if (event.type === "completed")
|
|
@@ -92,10 +107,11 @@ export function PathShell({ path: pathDef, steps, initialData = {}, autoStart =
|
|
|
92
107
|
}
|
|
93
108
|
});
|
|
94
109
|
const { snapshot, start, next, previous, cancel, goToStep, goToStepChecked, setData, restart } = pathReturn;
|
|
95
|
-
// Auto-start on mount
|
|
110
|
+
// Auto-start on mount — skipped when an external engine is provided since
|
|
111
|
+
// the caller is responsible for starting it (e.g. via createPersistedEngine).
|
|
96
112
|
const startedRef = useRef(false);
|
|
97
113
|
useEffect(() => {
|
|
98
|
-
if (autoStart && !startedRef.current) {
|
|
114
|
+
if (autoStart && !startedRef.current && !externalEngine) {
|
|
99
115
|
startedRef.current = true;
|
|
100
116
|
start(pathDef, initialData);
|
|
101
117
|
}
|
|
@@ -127,7 +143,7 @@ export function PathShell({ path: pathDef, steps, initialData = {}, autoStart =
|
|
|
127
143
|
renderFooter
|
|
128
144
|
? renderFooter(snapshot, actions)
|
|
129
145
|
: defaultFooter(snapshot, actions, {
|
|
130
|
-
backLabel, nextLabel,
|
|
146
|
+
backLabel, nextLabel, completeLabel, cancelLabel, hideCancel
|
|
131
147
|
})));
|
|
132
148
|
}
|
|
133
149
|
// ---------------------------------------------------------------------------
|
|
@@ -158,7 +174,7 @@ function defaultFooter(snapshot, actions, labels) {
|
|
|
158
174
|
className: "pw-shell__btn pw-shell__btn--next",
|
|
159
175
|
disabled: snapshot.isNavigating || !snapshot.canMoveNext,
|
|
160
176
|
onClick: actions.next
|
|
161
|
-
}, snapshot.isLastStep ? labels.
|
|
177
|
+
}, snapshot.isLastStep ? labels.completeLabel : labels.nextLabel)));
|
|
162
178
|
}
|
|
163
179
|
// ---------------------------------------------------------------------------
|
|
164
180
|
// Helpers
|
|
@@ -166,4 +182,5 @@ function defaultFooter(snapshot, actions, labels) {
|
|
|
166
182
|
function cls(...parts) {
|
|
167
183
|
return parts.filter(Boolean).join(" ");
|
|
168
184
|
}
|
|
185
|
+
export { PathEngine } from "@daltonr/pathwrite-core";
|
|
169
186
|
//# 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":"AAAA,OAAO,EACL,aAAa,EACb,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,MAAM,EACN,oBAAoB,EACrB,MAAM,OAAO,CAAC;AAEf,OAAO,EAGL,UAAU,EAGX,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,MAAM,EACN,oBAAoB,EACrB,MAAM,OAAO,CAAC;AAEf,OAAO,EAGL,UAAU,EAGX,MAAM,yBAAyB,CAAC;AAsDjC,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E,MAAM,UAAU,OAAO,CAAoC,OAAwB;IACjF,2EAA2E;IAC3E,8EAA8E;IAC9E,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAClD,IAAI,SAAS,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QAC/B,SAAS,CAAC,OAAO,GAAG,OAAO,EAAE,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;IAC1D,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;IAEjC,4EAA4E;IAC5E,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,UAAU,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;IAEtC,2EAA2E;IAC3E,2EAA2E;IAC3E,4EAA4E;IAC5E,2DAA2D;IAC3D,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,WAAW,GAAG,MAAM,CAA6B,IAAI,CAAC,CAAC;IAC7D,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QACvB,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC;YACH,WAAW,CAAC,OAAO,GAAG,MAAM,CAAC,QAAQ,EAAgC,CAAC;QACxE,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,WAAW,CAC3B,CAAC,QAAoB,EAAE,EAAE,CACvB,MAAM,CAAC,SAAS,CAAC,CAAC,KAAgB,EAAE,EAAE;QACpC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9D,WAAW,CAAC,OAAO,GAAG,KAAK,CAAC,QAA+B,CAAC;QAC9D,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACpE,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAC7B,CAAC;QACD,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QAC5B,QAAQ,EAAE,CAAC;IACb,CAAC,CAAC,EACJ,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAE/D,MAAM,QAAQ,GAAG,oBAAoB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAE9D,0BAA0B;IAC1B,MAAM,KAAK,GAAG,WAAW,CACvB,CAAC,IAAyB,EAAE,cAAwB,EAAE,EAAE,EAAE,CACxD,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,EACjC,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,IAAyB,EAAE,cAAwB,EAAE,EAAE,IAA8B,EAAE,EAAE,CACxF,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,EAC9C,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAE5D,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAC3C,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,EAClD,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,OAAO,GAAG,WAAW,CACzB,CAAiC,GAAM,EAAE,KAAe,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,KAAgB,CAAC,EAClG,CAAC,MAAM,CAAC,CAC0B,CAAC;IAErC,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,IAAyB,EAAE,cAAwB,EAAE,EAAE,EAAE,CACxD,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,EACnC,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAChH,CAAC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,MAAM,WAAW,GAAG,aAAa,CAAuB,IAAI,CAAC,CAAC;AAE9D;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAqB;IACnE,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAClC,OAAO,aAAa,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACpC,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,GAA2B,CAAC;AACrC,CAAC;AA0DD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,cAAc,EACtB,KAAK,EACL,WAAW,GAAG,EAAE,EAChB,SAAS,GAAG,IAAI,EAChB,UAAU,EACV,QAAQ,EACR,OAAO,EACP,SAAS,GAAG,UAAU,EACtB,SAAS,GAAG,MAAM,EAClB,aAAa,GAAG,UAAU,EAC1B,WAAW,GAAG,QAAQ,EACtB,UAAU,GAAG,KAAK,EAClB,YAAY,GAAG,KAAK,EACpB,SAAS,EACT,YAAY,EACZ,YAAY,GACG;IACf,MAAM,UAAU,GAAG,OAAO,CAAC;QACzB,MAAM,EAAE,cAAc;QACtB,OAAO,CAAC,KAAK;YACX,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YACjB,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gBAAE,UAAU,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzD,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gBAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzD,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;IAE5G,0EAA0E;IAC1E,8EAA8E;IAC9E,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACjC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;YACxD,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;YAC1B,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAC9B,CAAC;QACD,uDAAuD;IACzD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,0CAA0C;IAC1C,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEvE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,aAAa,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAC9D,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,EAC5D,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EACnD,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,iBAAiB,CAAC,EAC3C,CAAC,SAAS,IAAI,aAAa,CAAC,QAAQ,EAAE;YACpC,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,qBAAqB;YAChC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC;SAC3C,EAAE,OAAO,CAAC,CACZ,CACF,CACF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAqB;QAChC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,OAAO;QAC1D,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC;KAC7C,CAAC;IAEF,OAAO,aAAa,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAC9D,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE;IAC5D,8BAA8B;IAC9B,CAAC,YAAY,IAAI,CAAC,YAAY;QAC5B,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC;QACxB,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC5B,sBAAsB;IACtB,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,EAAE,WAAW,CAAC;IAClE,sBAAsB;IACtB,QAAQ,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,sBAAsB,EAAE,EACjG,GAAG,QAAQ,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAC5C,aAAa,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,2BAA2B,EAAE,EAAE,GAAG,CAAC,CAC7E,CACF;IACD,8BAA8B;IAC9B,YAAY;QACV,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC;QACjC,CAAC,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE;YAC/B,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU;SAC7D,CAAC,CACP,CACF,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,sCAAsC;AACtC,8EAA8E;AAE9E,SAAS,aAAa,CAAC,QAAsB;IAC3C,OAAO,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,EAC3D,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EACnD,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAChC,aAAa,CAAC,KAAK,EAAE;QACnB,GAAG,EAAE,IAAI,CAAC,EAAE;QACZ,SAAS,EAAE,GAAG,CAAC,gBAAgB,EAAE,mBAAmB,IAAI,CAAC,MAAM,EAAE,CAAC;KACnE,EACC,aAAa,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,oBAAoB,EAAE,EACvD,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAClD,EACD,aAAa,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,sBAAsB,EAAE,EACzD,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,EAAE,CACtB,CACF,CACF,CACF,EACD,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EACnD,aAAa,CAAC,KAAK,EAAE;QACnB,SAAS,EAAE,sBAAsB;QACjC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,QAAQ,GAAG,GAAG,GAAG,EAAE;KAChD,CAAC,CACH,CACF,CAAC;AACJ,CAAC;AAcD,SAAS,aAAa,CACpB,QAAsB,EACtB,OAAyB,EACzB,MAAoB;IAEpB,OAAO,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,EAC3D,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,uBAAuB,EAAE,EACzD,CAAC,QAAQ,CAAC,WAAW,IAAI,aAAa,CAAC,QAAQ,EAAE;QAC/C,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,mCAAmC;QAC9C,QAAQ,EAAE,QAAQ,CAAC,YAAY,IAAI,CAAC,QAAQ,CAAC,eAAe;QAC5D,OAAO,EAAE,OAAO,CAAC,QAAQ;KAC1B,EAAE,MAAM,CAAC,SAAS,CAAC,CACrB,EACD,aAAa,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,wBAAwB,EAAE,EAC1D,CAAC,MAAM,CAAC,UAAU,IAAI,aAAa,CAAC,QAAQ,EAAE;QAC5C,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,qCAAqC;QAChD,QAAQ,EAAE,QAAQ,CAAC,YAAY;QAC/B,OAAO,EAAE,OAAO,CAAC,MAAM;KACxB,EAAE,MAAM,CAAC,WAAW,CAAC,EACtB,aAAa,CAAC,QAAQ,EAAE;QACtB,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,mCAAmC;QAC9C,QAAQ,EAAE,QAAQ,CAAC,YAAY,IAAI,CAAC,QAAQ,CAAC,WAAW;QACxD,OAAO,EAAE,OAAO,CAAC,IAAI;KACtB,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAClE,CACF,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,GAAG,CAAC,GAAG,KAA4C;IAC1D,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC;AAgBD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@daltonr/pathwrite-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.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.",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"react": ">=18.0.0"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@daltonr/pathwrite-core": "^0.
|
|
48
|
+
"@daltonr/pathwrite-core": "^0.5.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"react": "^18.3.1",
|
package/src/index.ts
CHANGED
|
@@ -21,7 +21,18 @@ import {
|
|
|
21
21
|
// ---------------------------------------------------------------------------
|
|
22
22
|
|
|
23
23
|
export interface UsePathOptions {
|
|
24
|
-
/**
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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) =>
|
|
@@ -172,6 +196,12 @@ export function usePathContext<TData extends PathData = PathData>(): UsePathRetu
|
|
|
172
196
|
export interface PathShellProps {
|
|
173
197
|
/** The path definition to drive. */
|
|
174
198
|
path: PathDefinition<any>;
|
|
199
|
+
/**
|
|
200
|
+
* An externally-managed engine — for example, the engine returned by
|
|
201
|
+
* `createPersistedEngine()`. When supplied, `PathShell` will skip its own
|
|
202
|
+
* `start()` call and drive the UI from the provided engine instead.
|
|
203
|
+
*/
|
|
204
|
+
engine?: PathEngine;
|
|
175
205
|
/** Map of step ID → content. The shell renders `steps[snapshot.stepId]` for the current step. */
|
|
176
206
|
steps: Record<string, ReactNode>;
|
|
177
207
|
/** Initial data passed to `engine.start()`. */
|
|
@@ -184,12 +214,12 @@ export interface PathShellProps {
|
|
|
184
214
|
onCancel?: (data: PathData) => void;
|
|
185
215
|
/** Called for every engine event. */
|
|
186
216
|
onEvent?: (event: PathEvent) => void;
|
|
187
|
-
/** Label for the
|
|
217
|
+
/** Label for the Previous button. Defaults to `"Previous"`. */
|
|
188
218
|
backLabel?: string;
|
|
189
219
|
/** Label for the Next button. Defaults to `"Next"`. */
|
|
190
220
|
nextLabel?: string;
|
|
191
|
-
/** Label for the
|
|
192
|
-
|
|
221
|
+
/** Label for the Complete button (shown on the last step). Defaults to `"Complete"`. */
|
|
222
|
+
completeLabel?: string;
|
|
193
223
|
/** Label for the Cancel button. Defaults to `"Cancel"`. */
|
|
194
224
|
cancelLabel?: string;
|
|
195
225
|
/** If true, hide the Cancel button. Defaults to `false`. */
|
|
@@ -233,15 +263,16 @@ export interface PathShellActions {
|
|
|
233
263
|
*/
|
|
234
264
|
export function PathShell({
|
|
235
265
|
path: pathDef,
|
|
266
|
+
engine: externalEngine,
|
|
236
267
|
steps,
|
|
237
268
|
initialData = {},
|
|
238
269
|
autoStart = true,
|
|
239
270
|
onComplete,
|
|
240
271
|
onCancel,
|
|
241
272
|
onEvent,
|
|
242
|
-
backLabel = "
|
|
273
|
+
backLabel = "Previous",
|
|
243
274
|
nextLabel = "Next",
|
|
244
|
-
|
|
275
|
+
completeLabel = "Complete",
|
|
245
276
|
cancelLabel = "Cancel",
|
|
246
277
|
hideCancel = false,
|
|
247
278
|
hideProgress = false,
|
|
@@ -250,6 +281,7 @@ export function PathShell({
|
|
|
250
281
|
renderFooter,
|
|
251
282
|
}: PathShellProps): ReactElement {
|
|
252
283
|
const pathReturn = usePath({
|
|
284
|
+
engine: externalEngine,
|
|
253
285
|
onEvent(event) {
|
|
254
286
|
onEvent?.(event);
|
|
255
287
|
if (event.type === "completed") onComplete?.(event.data);
|
|
@@ -259,10 +291,11 @@ export function PathShell({
|
|
|
259
291
|
|
|
260
292
|
const { snapshot, start, next, previous, cancel, goToStep, goToStepChecked, setData, restart } = pathReturn;
|
|
261
293
|
|
|
262
|
-
// Auto-start on mount
|
|
294
|
+
// Auto-start on mount — skipped when an external engine is provided since
|
|
295
|
+
// the caller is responsible for starting it (e.g. via createPersistedEngine).
|
|
263
296
|
const startedRef = useRef(false);
|
|
264
297
|
useEffect(() => {
|
|
265
|
-
if (autoStart && !startedRef.current) {
|
|
298
|
+
if (autoStart && !startedRef.current && !externalEngine) {
|
|
266
299
|
startedRef.current = true;
|
|
267
300
|
start(pathDef, initialData);
|
|
268
301
|
}
|
|
@@ -310,7 +343,7 @@ export function PathShell({
|
|
|
310
343
|
renderFooter
|
|
311
344
|
? renderFooter(snapshot, actions)
|
|
312
345
|
: defaultFooter(snapshot, actions, {
|
|
313
|
-
backLabel, nextLabel,
|
|
346
|
+
backLabel, nextLabel, completeLabel, cancelLabel, hideCancel
|
|
314
347
|
})
|
|
315
348
|
)
|
|
316
349
|
);
|
|
@@ -353,7 +386,7 @@ function defaultHeader(snapshot: PathSnapshot): ReactElement {
|
|
|
353
386
|
interface FooterLabels {
|
|
354
387
|
backLabel: string;
|
|
355
388
|
nextLabel: string;
|
|
356
|
-
|
|
389
|
+
completeLabel: string;
|
|
357
390
|
cancelLabel: string;
|
|
358
391
|
hideCancel: boolean;
|
|
359
392
|
}
|
|
@@ -384,7 +417,7 @@ function defaultFooter(
|
|
|
384
417
|
className: "pw-shell__btn pw-shell__btn--next",
|
|
385
418
|
disabled: snapshot.isNavigating || !snapshot.canMoveNext,
|
|
386
419
|
onClick: actions.next
|
|
387
|
-
}, snapshot.isLastStep ? labels.
|
|
420
|
+
}, snapshot.isLastStep ? labels.completeLabel : labels.nextLabel)
|
|
388
421
|
)
|
|
389
422
|
);
|
|
390
423
|
}
|
|
@@ -411,3 +444,5 @@ export type {
|
|
|
411
444
|
SerializedPathState
|
|
412
445
|
} from "@daltonr/pathwrite-core";
|
|
413
446
|
|
|
447
|
+
export { PathEngine } from "@daltonr/pathwrite-core";
|
|
448
|
+
|