@daltonr/pathwrite-react 0.8.0 → 0.10.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/dist/index.css +86 -0
- package/dist/index.d.ts +94 -12
- package/dist/index.js +113 -37
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +208 -46
package/dist/index.css
CHANGED
|
@@ -285,6 +285,16 @@
|
|
|
285
285
|
content: ":";
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
/* ------------------------------------------------------------------ */
|
|
289
|
+
/* Blocking error (guard-level message, not field-attached) */
|
|
290
|
+
/* ------------------------------------------------------------------ */
|
|
291
|
+
.pw-shell__blocking-error {
|
|
292
|
+
margin: 0;
|
|
293
|
+
padding: 8px 16px;
|
|
294
|
+
font-size: 13px;
|
|
295
|
+
color: var(--pw-color-error);
|
|
296
|
+
}
|
|
297
|
+
|
|
288
298
|
/* ------------------------------------------------------------------ */
|
|
289
299
|
/* Warning messages */
|
|
290
300
|
/* ------------------------------------------------------------------ */
|
|
@@ -361,6 +371,7 @@
|
|
|
361
371
|
background: var(--pw-color-primary);
|
|
362
372
|
border-color: var(--pw-color-primary);
|
|
363
373
|
color: #fff;
|
|
374
|
+
position: relative;
|
|
364
375
|
}
|
|
365
376
|
|
|
366
377
|
.pw-shell__btn--next:hover:not(:disabled) {
|
|
@@ -368,6 +379,29 @@
|
|
|
368
379
|
border-color: #1d4ed8;
|
|
369
380
|
}
|
|
370
381
|
|
|
382
|
+
@keyframes pw-spin {
|
|
383
|
+
to { transform: rotate(360deg); }
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.pw-shell__btn--next.pw-shell__btn--loading {
|
|
387
|
+
color: transparent;
|
|
388
|
+
pointer-events: none;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.pw-shell__btn--next.pw-shell__btn--loading::after {
|
|
392
|
+
content: "";
|
|
393
|
+
position: absolute;
|
|
394
|
+
top: 50%;
|
|
395
|
+
left: 50%;
|
|
396
|
+
width: 14px;
|
|
397
|
+
height: 14px;
|
|
398
|
+
margin: -7px 0 0 -7px;
|
|
399
|
+
border: 2px solid rgba(255, 255, 255, 0.35);
|
|
400
|
+
border-top-color: #fff;
|
|
401
|
+
border-radius: 50%;
|
|
402
|
+
animation: pw-spin 0.6s linear infinite;
|
|
403
|
+
}
|
|
404
|
+
|
|
371
405
|
.pw-shell__btn--back {
|
|
372
406
|
background: transparent;
|
|
373
407
|
border-color: var(--pw-color-primary);
|
|
@@ -388,3 +422,55 @@
|
|
|
388
422
|
background: var(--pw-color-primary-light);
|
|
389
423
|
}
|
|
390
424
|
|
|
425
|
+
/* ------------------------------------------------------------------ */
|
|
426
|
+
/* Error panel — replaces footer when status === "error" */
|
|
427
|
+
/* ------------------------------------------------------------------ */
|
|
428
|
+
.pw-shell__error {
|
|
429
|
+
background: var(--pw-color-error-bg);
|
|
430
|
+
border: 1px solid var(--pw-color-error-border);
|
|
431
|
+
border-radius: var(--pw-shell-radius);
|
|
432
|
+
padding: 16px 20px;
|
|
433
|
+
display: flex;
|
|
434
|
+
flex-direction: column;
|
|
435
|
+
gap: 10px;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.pw-shell__error-title {
|
|
439
|
+
font-size: 14px;
|
|
440
|
+
font-weight: 600;
|
|
441
|
+
color: var(--pw-color-error);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.pw-shell__error-message {
|
|
445
|
+
font-size: 13px;
|
|
446
|
+
color: var(--pw-color-muted);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.pw-shell__error-actions {
|
|
450
|
+
display: flex;
|
|
451
|
+
gap: 8px;
|
|
452
|
+
align-items: center;
|
|
453
|
+
margin-top: 2px;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.pw-shell__btn--retry {
|
|
457
|
+
background: var(--pw-color-error);
|
|
458
|
+
border-color: var(--pw-color-error);
|
|
459
|
+
color: #fff;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.pw-shell__btn--retry:hover:not(:disabled) {
|
|
463
|
+
opacity: 0.9;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
.pw-shell__btn--suspend {
|
|
467
|
+
color: var(--pw-color-muted);
|
|
468
|
+
border-color: transparent;
|
|
469
|
+
background: transparent;
|
|
470
|
+
font-size: 13px;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.pw-shell__btn--suspend:hover:not(:disabled) {
|
|
474
|
+
background: var(--pw-color-primary-light);
|
|
475
|
+
}
|
|
476
|
+
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { PropsWithChildren, ReactElement, ReactNode } from "react";
|
|
1
|
+
import type { ChangeEvent, PropsWithChildren, ReactElement, ReactNode } from "react";
|
|
2
2
|
import { PathData, PathDefinition, PathEngine, PathEvent, PathSnapshot, ProgressLayout } from "@daltonr/pathwrite-core";
|
|
3
3
|
export interface UsePathOptions {
|
|
4
4
|
/**
|
|
5
5
|
* An externally-managed `PathEngine` to subscribe to — for example, the engine
|
|
6
|
-
* returned by `createPersistedEngine()` from `@daltonr/pathwrite-store
|
|
6
|
+
* returned by `createPersistedEngine()` from `@daltonr/pathwrite-store`.
|
|
7
7
|
*
|
|
8
8
|
* When provided:
|
|
9
9
|
* - `usePath` will **not** create its own engine.
|
|
@@ -37,30 +37,86 @@ export interface UsePathReturn<TData extends PathData = PathData> {
|
|
|
37
37
|
/** Reset the current step's data to what it was when the step was entered. Useful for "Clear" or "Reset" buttons. */
|
|
38
38
|
resetStep: () => void;
|
|
39
39
|
/**
|
|
40
|
-
* Tear down any active path (without firing hooks) and immediately
|
|
41
|
-
*
|
|
40
|
+
* Tear down any active path (without firing hooks) and immediately restart
|
|
41
|
+
* the same path with the same initial data. Safe to call at any time.
|
|
42
42
|
* Use for "Start over" / retry flows without remounting the component.
|
|
43
43
|
*/
|
|
44
|
-
restart: (
|
|
44
|
+
restart: () => void;
|
|
45
|
+
/**
|
|
46
|
+
* Re-runs the operation that set `snapshot.error`. Increments `snapshot.error.retryCount`
|
|
47
|
+
* on repeated failure so shells can escalate from "Try again" to "Come back later".
|
|
48
|
+
* No-op when there is no pending error.
|
|
49
|
+
*/
|
|
50
|
+
retry: () => void;
|
|
51
|
+
/**
|
|
52
|
+
* Pauses the path with intent to return. Emits a `suspended` event that the application
|
|
53
|
+
* listens for to dismiss the wizard UI. All state and data are preserved.
|
|
54
|
+
*/
|
|
55
|
+
suspend: () => void;
|
|
45
56
|
}
|
|
46
57
|
export type PathProviderProps = PropsWithChildren<{
|
|
47
58
|
/** Forwarded to the internal usePath hook. */
|
|
48
59
|
onEvent?: (event: PathEvent) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Services object passed through context to all step components.
|
|
62
|
+
* Step components access it via `usePathContext<TData, TServices>()`.
|
|
63
|
+
* Typed as `unknown` here so `PathProvider` stays non-generic — provide a
|
|
64
|
+
* typed services interface via the `TServices` type parameter on `usePathContext`.
|
|
65
|
+
*/
|
|
66
|
+
services?: unknown;
|
|
49
67
|
}>;
|
|
50
68
|
export declare function usePath<TData extends PathData = PathData>(options?: UsePathOptions): UsePathReturn<TData>;
|
|
51
69
|
/**
|
|
52
70
|
* Provides a single `usePath` instance to all descendants.
|
|
53
71
|
* Consume with `usePathContext()`.
|
|
54
72
|
*/
|
|
55
|
-
export declare function PathProvider({ children, onEvent }: PathProviderProps): ReactElement;
|
|
73
|
+
export declare function PathProvider({ children, onEvent, services }: PathProviderProps): ReactElement;
|
|
56
74
|
/**
|
|
57
|
-
* Access the nearest `PathProvider`'s path instance.
|
|
58
|
-
* Throws if used outside of a `<PathProvider>`.
|
|
75
|
+
* Access the nearest `PathProvider`'s path instance and optional services object.
|
|
76
|
+
* Throws if used outside of a `<PathProvider>` or `<PathShell>`.
|
|
59
77
|
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
78
|
+
* Both generics are type-level assertions, not runtime guarantees:
|
|
79
|
+
* - `TData` narrows `snapshot.data`
|
|
80
|
+
* - `TServices` types the `services` value — must match what was passed to `PathShell` or `PathProvider`
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```tsx
|
|
84
|
+
* function OfficeStep() {
|
|
85
|
+
* const { snapshot, services } = usePathContext<HiringData, HiringServices>();
|
|
86
|
+
* // services is typed as HiringServices
|
|
87
|
+
* }
|
|
88
|
+
* ```
|
|
62
89
|
*/
|
|
63
|
-
export declare function usePathContext<TData extends PathData = PathData>(): UsePathReturn<TData
|
|
90
|
+
export declare function usePathContext<TData extends PathData = PathData, TServices = unknown>(): Omit<UsePathReturn<TData>, "snapshot"> & {
|
|
91
|
+
snapshot: PathSnapshot<TData>;
|
|
92
|
+
services: TServices;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Binding helper for a single `<input>`, `<select>`, or `<textarea>` field.
|
|
96
|
+
*
|
|
97
|
+
* Returns `{ value, onChange }` tied to `snapshot.data[field]`, so you can
|
|
98
|
+
* spread it directly onto an element and eliminate the repetitive
|
|
99
|
+
* `onChange={e => setData("field", e.target.value)}` pattern:
|
|
100
|
+
*
|
|
101
|
+
* ```tsx
|
|
102
|
+
* function NameStep() {
|
|
103
|
+
* const name = useField<MyData, "name">("name");
|
|
104
|
+
* return <input type="text" {...name} />;
|
|
105
|
+
* }
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* - `value` is always a `string` (falls back to `""` when the data key is unset).
|
|
109
|
+
* - `onChange` calls `setData(field, e.target.value)`.
|
|
110
|
+
*
|
|
111
|
+
* For inputs that need a value transform (e.g. `.trim()`, `Number()`) keep
|
|
112
|
+
* an explicit `onChange` handler — this helper is for the no-transform case.
|
|
113
|
+
*
|
|
114
|
+
* Must be called inside a `<PathShell>` or `<PathProvider>`.
|
|
115
|
+
*/
|
|
116
|
+
export declare function useField<TData extends PathData, K extends string & keyof TData>(field: K): {
|
|
117
|
+
value: string;
|
|
118
|
+
onChange: (e: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => void;
|
|
119
|
+
};
|
|
64
120
|
export interface PathShellProps {
|
|
65
121
|
/** The path definition to drive. */
|
|
66
122
|
path: PathDefinition<any>;
|
|
@@ -88,6 +144,8 @@ export interface PathShellProps {
|
|
|
88
144
|
nextLabel?: string;
|
|
89
145
|
/** Label for the Complete button (shown on the last step). Defaults to `"Complete"`. */
|
|
90
146
|
completeLabel?: string;
|
|
147
|
+
/** Label shown on the Next/Complete button while an async operation is in progress. Defaults to `undefined` (button shows a CSS spinner but keeps its label). */
|
|
148
|
+
loadingLabel?: string;
|
|
91
149
|
/** Label for the Cancel button. Defaults to `"Cancel"`. */
|
|
92
150
|
cancelLabel?: string;
|
|
93
151
|
/** If true, hide the Cancel button. Defaults to `false`. */
|
|
@@ -122,6 +180,26 @@ export interface PathShellProps {
|
|
|
122
180
|
* - `"activeOnly"`: Only the active (sub-path) bar — root bar hidden.
|
|
123
181
|
*/
|
|
124
182
|
progressLayout?: ProgressLayout;
|
|
183
|
+
/**
|
|
184
|
+
* Services object passed through context to all step components.
|
|
185
|
+
* Step components access it via `usePathContext<TData, TServices>()`.
|
|
186
|
+
*
|
|
187
|
+
* The same services object that was passed to your path factory function
|
|
188
|
+
* should be passed here so step components can call service methods directly
|
|
189
|
+
* (e.g. parameterised queries that depend on mid-step user input).
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```tsx
|
|
193
|
+
* const svc = new LiveHiringServices();
|
|
194
|
+
* const path = createHiringPath(svc);
|
|
195
|
+
* <PathShell path={path} services={svc} steps={{ ... }} />
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
services?: unknown;
|
|
199
|
+
}
|
|
200
|
+
export interface PathShellHandle {
|
|
201
|
+
/** Restart the shell's current path with its original `initialData`, without unmounting. */
|
|
202
|
+
restart: () => void;
|
|
125
203
|
}
|
|
126
204
|
export interface PathShellActions {
|
|
127
205
|
next: () => void;
|
|
@@ -132,6 +210,10 @@ export interface PathShellActions {
|
|
|
132
210
|
setData: (key: string, value: unknown) => void;
|
|
133
211
|
/** Restart the shell's current path with its current `initialData`. */
|
|
134
212
|
restart: () => void;
|
|
213
|
+
/** Re-run the operation that set `snapshot.error`. See `PathEngine.retry()`. */
|
|
214
|
+
retry: () => void;
|
|
215
|
+
/** Pause with intent to return, preserving all state. Emits `suspended`. */
|
|
216
|
+
suspend: () => void;
|
|
135
217
|
}
|
|
136
218
|
/**
|
|
137
219
|
* Default UI shell that renders a progress indicator, step content, and navigation
|
|
@@ -149,6 +231,6 @@ export interface PathShellActions {
|
|
|
149
231
|
* />
|
|
150
232
|
* ```
|
|
151
233
|
*/
|
|
152
|
-
export declare
|
|
234
|
+
export declare const PathShell: import("react").ForwardRefExoticComponent<PathShellProps & import("react").RefAttributes<PathShellHandle>>;
|
|
153
235
|
export type { PathData, FieldErrors, PathDefinition, PathEvent, PathSnapshot, PathStep, PathStepContext, ProgressLayout, RootProgress, SerializedPathState, StepChoice, } from "@daltonr/pathwrite-core";
|
|
154
236
|
export { PathEngine } from "@daltonr/pathwrite-core";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createContext, createElement, useCallback, useContext, useEffect, useRef, useSyncExternalStore } from "react";
|
|
2
|
-
import { PathEngine } from "@daltonr/pathwrite-core";
|
|
1
|
+
import { createContext, createElement, forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useRef, useSyncExternalStore } from "react";
|
|
2
|
+
import { PathEngine, formatFieldKey, errorPhaseMessage, } from "@daltonr/pathwrite-core";
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
// usePath hook
|
|
5
5
|
// ---------------------------------------------------------------------------
|
|
@@ -51,42 +51,80 @@ export function usePath(options) {
|
|
|
51
51
|
const goToStepChecked = useCallback((stepId) => engine.goToStepChecked(stepId), [engine]);
|
|
52
52
|
const setData = useCallback((key, value) => engine.setData(key, value), [engine]);
|
|
53
53
|
const resetStep = useCallback(() => engine.resetStep(), [engine]);
|
|
54
|
-
const restart = useCallback((
|
|
55
|
-
|
|
54
|
+
const restart = useCallback(() => engine.restart(), [engine]);
|
|
55
|
+
const retry = useCallback(() => engine.retry(), [engine]);
|
|
56
|
+
const suspend = useCallback(() => engine.suspend(), [engine]);
|
|
57
|
+
return { snapshot, start, startSubPath, next, previous, cancel, goToStep, goToStepChecked, setData, resetStep, restart, retry, suspend };
|
|
56
58
|
}
|
|
57
|
-
// ---------------------------------------------------------------------------
|
|
58
|
-
// Context + Provider
|
|
59
|
-
// ---------------------------------------------------------------------------
|
|
60
59
|
const PathContext = createContext(null);
|
|
61
60
|
/**
|
|
62
61
|
* Provides a single `usePath` instance to all descendants.
|
|
63
62
|
* Consume with `usePathContext()`.
|
|
64
63
|
*/
|
|
65
|
-
export function PathProvider({ children, onEvent }) {
|
|
64
|
+
export function PathProvider({ children, onEvent, services }) {
|
|
66
65
|
const path = usePath({ onEvent });
|
|
67
|
-
return createElement(PathContext.Provider, { value: path }, children);
|
|
66
|
+
return createElement(PathContext.Provider, { value: { path, services: services ?? null } }, children);
|
|
68
67
|
}
|
|
69
68
|
/**
|
|
70
|
-
* Access the nearest `PathProvider`'s path instance.
|
|
71
|
-
* Throws if used outside of a `<PathProvider>`.
|
|
69
|
+
* Access the nearest `PathProvider`'s path instance and optional services object.
|
|
70
|
+
* Throws if used outside of a `<PathProvider>` or `<PathShell>`.
|
|
71
|
+
*
|
|
72
|
+
* Both generics are type-level assertions, not runtime guarantees:
|
|
73
|
+
* - `TData` narrows `snapshot.data`
|
|
74
|
+
* - `TServices` types the `services` value — must match what was passed to `PathShell` or `PathProvider`
|
|
72
75
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```tsx
|
|
78
|
+
* function OfficeStep() {
|
|
79
|
+
* const { snapshot, services } = usePathContext<HiringData, HiringServices>();
|
|
80
|
+
* // services is typed as HiringServices
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
75
83
|
*/
|
|
76
84
|
export function usePathContext() {
|
|
77
85
|
const ctx = useContext(PathContext);
|
|
78
86
|
if (ctx === null) {
|
|
79
87
|
throw new Error("usePathContext must be used within a <PathProvider>.");
|
|
80
88
|
}
|
|
81
|
-
return
|
|
89
|
+
return {
|
|
90
|
+
...ctx.path,
|
|
91
|
+
services: ctx.services
|
|
92
|
+
};
|
|
82
93
|
}
|
|
83
94
|
// ---------------------------------------------------------------------------
|
|
84
|
-
//
|
|
95
|
+
// useField — input binding helper
|
|
85
96
|
// ---------------------------------------------------------------------------
|
|
86
|
-
/**
|
|
87
|
-
*
|
|
88
|
-
|
|
89
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Binding helper for a single `<input>`, `<select>`, or `<textarea>` field.
|
|
99
|
+
*
|
|
100
|
+
* Returns `{ value, onChange }` tied to `snapshot.data[field]`, so you can
|
|
101
|
+
* spread it directly onto an element and eliminate the repetitive
|
|
102
|
+
* `onChange={e => setData("field", e.target.value)}` pattern:
|
|
103
|
+
*
|
|
104
|
+
* ```tsx
|
|
105
|
+
* function NameStep() {
|
|
106
|
+
* const name = useField<MyData, "name">("name");
|
|
107
|
+
* return <input type="text" {...name} />;
|
|
108
|
+
* }
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* - `value` is always a `string` (falls back to `""` when the data key is unset).
|
|
112
|
+
* - `onChange` calls `setData(field, e.target.value)`.
|
|
113
|
+
*
|
|
114
|
+
* For inputs that need a value transform (e.g. `.trim()`, `Number()`) keep
|
|
115
|
+
* an explicit `onChange` handler — this helper is for the no-transform case.
|
|
116
|
+
*
|
|
117
|
+
* Must be called inside a `<PathShell>` or `<PathProvider>`.
|
|
118
|
+
*/
|
|
119
|
+
export function useField(field) {
|
|
120
|
+
const { snapshot, setData } = usePathContext();
|
|
121
|
+
const onChange = useCallback((e) => {
|
|
122
|
+
setData(field, e.target.value);
|
|
123
|
+
},
|
|
124
|
+
// field is a string literal at the call site and never changes; setData is stable
|
|
125
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
126
|
+
[field, setData]);
|
|
127
|
+
return { value: String(snapshot.data[field] ?? ""), onChange };
|
|
90
128
|
}
|
|
91
129
|
/**
|
|
92
130
|
* Default UI shell that renders a progress indicator, step content, and navigation
|
|
@@ -104,7 +142,7 @@ function formatFieldKey(key) {
|
|
|
104
142
|
* />
|
|
105
143
|
* ```
|
|
106
144
|
*/
|
|
107
|
-
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, validationDisplay = "
|
|
145
|
+
export const PathShell = forwardRef(function PathShell({ path: pathDef, engine: externalEngine, steps, initialData = {}, autoStart = true, onComplete, onCancel, onEvent, backLabel = "Previous", nextLabel = "Next", completeLabel = "Complete", loadingLabel, cancelLabel = "Cancel", hideCancel = false, hideProgress = false, footerLayout = "auto", className, renderHeader, renderFooter, validationDisplay = "summary", progressLayout = "merged", services, }, ref) {
|
|
108
146
|
const pathReturn = usePath({
|
|
109
147
|
engine: externalEngine,
|
|
110
148
|
onEvent(event) {
|
|
@@ -115,7 +153,10 @@ export function PathShell({ path: pathDef, engine: externalEngine, steps, initia
|
|
|
115
153
|
onCancel?.(event.data);
|
|
116
154
|
}
|
|
117
155
|
});
|
|
118
|
-
const { snapshot, start, next, previous, cancel, goToStep, goToStepChecked, setData, restart } = pathReturn;
|
|
156
|
+
const { snapshot, start, next, previous, cancel, goToStep, goToStepChecked, setData, restart, retry, suspend } = pathReturn;
|
|
157
|
+
useImperativeHandle(ref, () => ({
|
|
158
|
+
restart: () => restart(),
|
|
159
|
+
}));
|
|
119
160
|
// Auto-start on mount — skipped when an external engine is provided since
|
|
120
161
|
// the caller is responsible for starting it (e.g. via createPersistedEngine).
|
|
121
162
|
const startedRef = useRef(false);
|
|
@@ -133,8 +174,9 @@ export function PathShell({ path: pathDef, engine: externalEngine, steps, initia
|
|
|
133
174
|
const stepContent = snapshot
|
|
134
175
|
? ((snapshot.formId ? steps[snapshot.formId] : undefined) ?? steps[snapshot.stepId] ?? null)
|
|
135
176
|
: null;
|
|
177
|
+
const contextValue = { path: pathReturn, services: services ?? null };
|
|
136
178
|
if (!snapshot) {
|
|
137
|
-
return createElement(PathContext.Provider, { value:
|
|
179
|
+
return createElement(PathContext.Provider, { value: contextValue }, createElement("div", { className: cls("pw-shell", className) }, createElement("div", { className: "pw-shell__empty" }, createElement("p", null, "No active path."), !autoStart && createElement("button", {
|
|
138
180
|
type: "button",
|
|
139
181
|
className: "pw-shell__start-btn",
|
|
140
182
|
onClick: () => start(pathDef, initialData)
|
|
@@ -142,13 +184,15 @@ export function PathShell({ path: pathDef, engine: externalEngine, steps, initia
|
|
|
142
184
|
}
|
|
143
185
|
const actions = {
|
|
144
186
|
next, previous, cancel, goToStep, goToStepChecked, setData,
|
|
145
|
-
restart: () => restart(
|
|
187
|
+
restart: () => restart(),
|
|
188
|
+
retry: () => retry(),
|
|
189
|
+
suspend: () => suspend(),
|
|
146
190
|
};
|
|
147
191
|
const showRoot = !hideProgress && !!snapshot.rootProgress && progressLayout !== "activeOnly";
|
|
148
192
|
const showActive = !hideProgress && (renderHeader
|
|
149
193
|
? true
|
|
150
194
|
: (snapshot.stepCount > 1 || snapshot.nestingLevel > 0) && progressLayout !== "rootOnly");
|
|
151
|
-
return createElement(PathContext.Provider, { value:
|
|
195
|
+
return createElement(PathContext.Provider, { value: contextValue }, createElement("div", { className: cls("pw-shell", progressLayout !== "merged" && `pw-shell--progress-${progressLayout}`, className) },
|
|
152
196
|
// Root progress — persistent top-level bar visible during sub-paths
|
|
153
197
|
showRoot && defaultRootProgress(snapshot.rootProgress),
|
|
154
198
|
// Header — progress indicator (active path)
|
|
@@ -161,13 +205,19 @@ export function PathShell({ path: pathDef, engine: externalEngine, steps, initia
|
|
|
161
205
|
validationDisplay !== "inline" && snapshot.hasAttemptedNext && Object.keys(snapshot.fieldErrors).length > 0 && createElement("ul", { className: "pw-shell__validation" }, ...Object.entries(snapshot.fieldErrors).map(([key, msg]) => createElement("li", { key, className: "pw-shell__validation-item" }, key !== "_" && createElement("span", { className: "pw-shell__validation-label" }, formatFieldKey(key)), msg))),
|
|
162
206
|
// Warning messages — non-blocking, shown immediately (no hasAttemptedNext gate)
|
|
163
207
|
validationDisplay !== "inline" && Object.keys(snapshot.fieldWarnings).length > 0 && createElement("ul", { className: "pw-shell__warnings" }, ...Object.entries(snapshot.fieldWarnings).map(([key, msg]) => createElement("li", { key, className: "pw-shell__warnings-item" }, key !== "_" && createElement("span", { className: "pw-shell__warnings-label" }, formatFieldKey(key)), msg))),
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
208
|
+
// Blocking error — guard returned { allowed: false, reason }
|
|
209
|
+
validationDisplay !== "inline" && snapshot.hasAttemptedNext && snapshot.blockingError &&
|
|
210
|
+
createElement("p", { className: "pw-shell__blocking-error" }, snapshot.blockingError),
|
|
211
|
+
// Error panel — replaces footer when an async operation has failed
|
|
212
|
+
snapshot.status === "error" && snapshot.error
|
|
213
|
+
? defaultErrorPanel(snapshot, actions)
|
|
214
|
+
// Footer — navigation buttons
|
|
215
|
+
: renderFooter
|
|
216
|
+
? renderFooter(snapshot, actions)
|
|
217
|
+
: defaultFooter(snapshot, actions, {
|
|
218
|
+
backLabel, nextLabel, completeLabel, loadingLabel, cancelLabel, hideCancel, footerLayout
|
|
219
|
+
})));
|
|
220
|
+
});
|
|
171
221
|
// ---------------------------------------------------------------------------
|
|
172
222
|
// Root progress (compact top-level bar visible during sub-paths)
|
|
173
223
|
// ---------------------------------------------------------------------------
|
|
@@ -192,6 +242,30 @@ function defaultHeader(snapshot) {
|
|
|
192
242
|
style: { width: `${snapshot.progress * 100}%` }
|
|
193
243
|
})));
|
|
194
244
|
}
|
|
245
|
+
// ---------------------------------------------------------------------------
|
|
246
|
+
// Default error panel
|
|
247
|
+
// ---------------------------------------------------------------------------
|
|
248
|
+
function defaultErrorPanel(snapshot, actions) {
|
|
249
|
+
const { error, hasPersistence } = snapshot;
|
|
250
|
+
if (!error)
|
|
251
|
+
return createElement("div", null);
|
|
252
|
+
const escalated = error.retryCount >= 2;
|
|
253
|
+
const title = escalated ? "Still having trouble." : "Something went wrong.";
|
|
254
|
+
const phaseMsg = errorPhaseMessage(error.phase);
|
|
255
|
+
return createElement("div", { className: "pw-shell__error" }, createElement("div", { className: "pw-shell__error-title" }, title), createElement("div", { className: "pw-shell__error-message" }, phaseMsg, error.message && ` ${error.message}`), createElement("div", { className: "pw-shell__error-actions" }, !escalated && createElement("button", {
|
|
256
|
+
type: "button",
|
|
257
|
+
className: "pw-shell__btn pw-shell__btn--retry",
|
|
258
|
+
onClick: actions.retry
|
|
259
|
+
}, "Try again"), hasPersistence && createElement("button", {
|
|
260
|
+
type: "button",
|
|
261
|
+
className: cls("pw-shell__btn", escalated ? "pw-shell__btn--retry" : "pw-shell__btn--suspend"),
|
|
262
|
+
onClick: actions.suspend
|
|
263
|
+
}, "Save and come back later"), escalated && !hasPersistence && createElement("button", {
|
|
264
|
+
type: "button",
|
|
265
|
+
className: "pw-shell__btn pw-shell__btn--retry",
|
|
266
|
+
onClick: actions.retry
|
|
267
|
+
}, "Try again")));
|
|
268
|
+
}
|
|
195
269
|
function defaultFooter(snapshot, actions, labels) {
|
|
196
270
|
// Auto-detect layout: single-step top-level paths use "form", everything else uses "wizard"
|
|
197
271
|
const resolvedLayout = labels.footerLayout === "auto"
|
|
@@ -203,30 +277,32 @@ function defaultFooter(snapshot, actions, labels) {
|
|
|
203
277
|
isFormMode && !labels.hideCancel && createElement("button", {
|
|
204
278
|
type: "button",
|
|
205
279
|
className: "pw-shell__btn pw-shell__btn--cancel",
|
|
206
|
-
disabled: snapshot.
|
|
280
|
+
disabled: snapshot.status !== "idle",
|
|
207
281
|
onClick: actions.cancel
|
|
208
282
|
}, labels.cancelLabel),
|
|
209
283
|
// Wizard mode: Back on the left
|
|
210
284
|
!isFormMode && !snapshot.isFirstStep && createElement("button", {
|
|
211
285
|
type: "button",
|
|
212
286
|
className: "pw-shell__btn pw-shell__btn--back",
|
|
213
|
-
disabled: snapshot.
|
|
287
|
+
disabled: snapshot.status !== "idle" || !snapshot.canMovePrevious,
|
|
214
288
|
onClick: actions.previous
|
|
215
289
|
}, labels.backLabel)), createElement("div", { className: "pw-shell__footer-right" },
|
|
216
290
|
// Wizard mode: Cancel on the right
|
|
217
291
|
!isFormMode && !labels.hideCancel && createElement("button", {
|
|
218
292
|
type: "button",
|
|
219
293
|
className: "pw-shell__btn pw-shell__btn--cancel",
|
|
220
|
-
disabled: snapshot.
|
|
294
|
+
disabled: snapshot.status !== "idle",
|
|
221
295
|
onClick: actions.cancel
|
|
222
296
|
}, labels.cancelLabel),
|
|
223
297
|
// Both modes: Submit on the right
|
|
224
298
|
createElement("button", {
|
|
225
299
|
type: "button",
|
|
226
|
-
className: "pw-shell__btn pw-shell__btn--next",
|
|
227
|
-
disabled: snapshot.
|
|
300
|
+
className: cls("pw-shell__btn pw-shell__btn--next", snapshot.status !== "idle" && "pw-shell__btn--loading"),
|
|
301
|
+
disabled: snapshot.status !== "idle",
|
|
228
302
|
onClick: actions.next
|
|
229
|
-
}, snapshot.
|
|
303
|
+
}, snapshot.status !== "idle" && labels.loadingLabel
|
|
304
|
+
? labels.loadingLabel
|
|
305
|
+
: snapshot.isLastStep ? labels.completeLabel : labels.nextLabel)));
|
|
230
306
|
}
|
|
231
307
|
// ---------------------------------------------------------------------------
|
|
232
308
|
// Helpers
|
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.
|
|
3
|
+
"version": "0.10.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.",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"react": ">=18.0.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@daltonr/pathwrite-core": "^0.
|
|
49
|
+
"@daltonr/pathwrite-core": "^0.10.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"react": "^18.3.1",
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createContext,
|
|
3
3
|
createElement,
|
|
4
|
+
forwardRef,
|
|
4
5
|
useCallback,
|
|
5
6
|
useContext,
|
|
6
7
|
useEffect,
|
|
8
|
+
useImperativeHandle,
|
|
7
9
|
useRef,
|
|
8
10
|
useSyncExternalStore
|
|
9
11
|
} from "react";
|
|
10
|
-
import type { PropsWithChildren, ReactElement, ReactNode } from "react";
|
|
12
|
+
import type { ChangeEvent, PropsWithChildren, ReactElement, ReactNode } from "react";
|
|
11
13
|
import {
|
|
12
14
|
PathData,
|
|
13
15
|
PathDefinition,
|
|
@@ -15,7 +17,9 @@ import {
|
|
|
15
17
|
PathEvent,
|
|
16
18
|
PathSnapshot,
|
|
17
19
|
ProgressLayout,
|
|
18
|
-
RootProgress
|
|
20
|
+
RootProgress,
|
|
21
|
+
formatFieldKey,
|
|
22
|
+
errorPhaseMessage,
|
|
19
23
|
} from "@daltonr/pathwrite-core";
|
|
20
24
|
|
|
21
25
|
// ---------------------------------------------------------------------------
|
|
@@ -25,7 +29,7 @@ import {
|
|
|
25
29
|
export interface UsePathOptions {
|
|
26
30
|
/**
|
|
27
31
|
* An externally-managed `PathEngine` to subscribe to — for example, the engine
|
|
28
|
-
* returned by `createPersistedEngine()` from `@daltonr/pathwrite-store
|
|
32
|
+
* returned by `createPersistedEngine()` from `@daltonr/pathwrite-store`.
|
|
29
33
|
*
|
|
30
34
|
* When provided:
|
|
31
35
|
* - `usePath` will **not** create its own engine.
|
|
@@ -60,16 +64,34 @@ export interface UsePathReturn<TData extends PathData = PathData> {
|
|
|
60
64
|
/** Reset the current step's data to what it was when the step was entered. Useful for "Clear" or "Reset" buttons. */
|
|
61
65
|
resetStep: () => void;
|
|
62
66
|
/**
|
|
63
|
-
* Tear down any active path (without firing hooks) and immediately
|
|
64
|
-
*
|
|
67
|
+
* Tear down any active path (without firing hooks) and immediately restart
|
|
68
|
+
* the same path with the same initial data. Safe to call at any time.
|
|
65
69
|
* Use for "Start over" / retry flows without remounting the component.
|
|
66
70
|
*/
|
|
67
|
-
restart: (
|
|
71
|
+
restart: () => void;
|
|
72
|
+
/**
|
|
73
|
+
* Re-runs the operation that set `snapshot.error`. Increments `snapshot.error.retryCount`
|
|
74
|
+
* on repeated failure so shells can escalate from "Try again" to "Come back later".
|
|
75
|
+
* No-op when there is no pending error.
|
|
76
|
+
*/
|
|
77
|
+
retry: () => void;
|
|
78
|
+
/**
|
|
79
|
+
* Pauses the path with intent to return. Emits a `suspended` event that the application
|
|
80
|
+
* listens for to dismiss the wizard UI. All state and data are preserved.
|
|
81
|
+
*/
|
|
82
|
+
suspend: () => void;
|
|
68
83
|
}
|
|
69
84
|
|
|
70
85
|
export type PathProviderProps = PropsWithChildren<{
|
|
71
86
|
/** Forwarded to the internal usePath hook. */
|
|
72
87
|
onEvent?: (event: PathEvent) => void;
|
|
88
|
+
/**
|
|
89
|
+
* Services object passed through context to all step components.
|
|
90
|
+
* Step components access it via `usePathContext<TData, TServices>()`.
|
|
91
|
+
* Typed as `unknown` here so `PathProvider` stays non-generic — provide a
|
|
92
|
+
* typed services interface via the `TServices` type parameter on `usePathContext`.
|
|
93
|
+
*/
|
|
94
|
+
services?: unknown;
|
|
73
95
|
}>;
|
|
74
96
|
|
|
75
97
|
// ---------------------------------------------------------------------------
|
|
@@ -156,55 +178,108 @@ export function usePath<TData extends PathData = PathData>(options?: UsePathOpti
|
|
|
156
178
|
|
|
157
179
|
const resetStep = useCallback(() => engine.resetStep(), [engine]);
|
|
158
180
|
|
|
159
|
-
const restart = useCallback(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
[engine]
|
|
163
|
-
);
|
|
181
|
+
const restart = useCallback(() => engine.restart(), [engine]);
|
|
182
|
+
|
|
183
|
+
const retry = useCallback(() => engine.retry(), [engine]);
|
|
164
184
|
|
|
165
|
-
|
|
185
|
+
const suspend = useCallback(() => engine.suspend(), [engine]);
|
|
186
|
+
|
|
187
|
+
return { snapshot, start, startSubPath, next, previous, cancel, goToStep, goToStepChecked, setData, resetStep, restart, retry, suspend };
|
|
166
188
|
}
|
|
167
189
|
|
|
168
190
|
// ---------------------------------------------------------------------------
|
|
169
191
|
// Context + Provider
|
|
170
192
|
// ---------------------------------------------------------------------------
|
|
171
193
|
|
|
172
|
-
|
|
194
|
+
interface PathContextValue {
|
|
195
|
+
path: UsePathReturn;
|
|
196
|
+
services: unknown;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const PathContext = createContext<PathContextValue | null>(null);
|
|
173
200
|
|
|
174
201
|
/**
|
|
175
202
|
* Provides a single `usePath` instance to all descendants.
|
|
176
203
|
* Consume with `usePathContext()`.
|
|
177
204
|
*/
|
|
178
|
-
export function PathProvider({ children, onEvent }: PathProviderProps): ReactElement {
|
|
205
|
+
export function PathProvider({ children, onEvent, services }: PathProviderProps): ReactElement {
|
|
179
206
|
const path = usePath({ onEvent });
|
|
180
|
-
return createElement(PathContext.Provider, { value: path }, children);
|
|
207
|
+
return createElement(PathContext.Provider, { value: { path, services: services ?? null } }, children);
|
|
181
208
|
}
|
|
182
209
|
|
|
183
210
|
/**
|
|
184
|
-
* Access the nearest `PathProvider`'s path instance.
|
|
185
|
-
* Throws if used outside of a `<PathProvider>`.
|
|
211
|
+
* Access the nearest `PathProvider`'s path instance and optional services object.
|
|
212
|
+
* Throws if used outside of a `<PathProvider>` or `<PathShell>`.
|
|
186
213
|
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
214
|
+
* Both generics are type-level assertions, not runtime guarantees:
|
|
215
|
+
* - `TData` narrows `snapshot.data`
|
|
216
|
+
* - `TServices` types the `services` value — must match what was passed to `PathShell` or `PathProvider`
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```tsx
|
|
220
|
+
* function OfficeStep() {
|
|
221
|
+
* const { snapshot, services } = usePathContext<HiringData, HiringServices>();
|
|
222
|
+
* // services is typed as HiringServices
|
|
223
|
+
* }
|
|
224
|
+
* ```
|
|
189
225
|
*/
|
|
190
|
-
export function usePathContext<TData extends PathData = PathData>(): UsePathReturn<TData> {
|
|
226
|
+
export function usePathContext<TData extends PathData = PathData, TServices = unknown>(): Omit<UsePathReturn<TData>, "snapshot"> & { snapshot: PathSnapshot<TData>; services: TServices } {
|
|
191
227
|
const ctx = useContext(PathContext);
|
|
192
228
|
if (ctx === null) {
|
|
193
229
|
throw new Error("usePathContext must be used within a <PathProvider>.");
|
|
194
230
|
}
|
|
195
|
-
return
|
|
231
|
+
return {
|
|
232
|
+
...(ctx.path as unknown as Omit<UsePathReturn<TData>, "snapshot"> & { snapshot: PathSnapshot<TData> }),
|
|
233
|
+
services: ctx.services as TServices
|
|
234
|
+
};
|
|
196
235
|
}
|
|
197
236
|
|
|
198
237
|
// ---------------------------------------------------------------------------
|
|
199
|
-
//
|
|
238
|
+
// useField — input binding helper
|
|
200
239
|
// ---------------------------------------------------------------------------
|
|
201
240
|
|
|
202
|
-
/**
|
|
203
|
-
*
|
|
204
|
-
|
|
205
|
-
|
|
241
|
+
/**
|
|
242
|
+
* Binding helper for a single `<input>`, `<select>`, or `<textarea>` field.
|
|
243
|
+
*
|
|
244
|
+
* Returns `{ value, onChange }` tied to `snapshot.data[field]`, so you can
|
|
245
|
+
* spread it directly onto an element and eliminate the repetitive
|
|
246
|
+
* `onChange={e => setData("field", e.target.value)}` pattern:
|
|
247
|
+
*
|
|
248
|
+
* ```tsx
|
|
249
|
+
* function NameStep() {
|
|
250
|
+
* const name = useField<MyData, "name">("name");
|
|
251
|
+
* return <input type="text" {...name} />;
|
|
252
|
+
* }
|
|
253
|
+
* ```
|
|
254
|
+
*
|
|
255
|
+
* - `value` is always a `string` (falls back to `""` when the data key is unset).
|
|
256
|
+
* - `onChange` calls `setData(field, e.target.value)`.
|
|
257
|
+
*
|
|
258
|
+
* For inputs that need a value transform (e.g. `.trim()`, `Number()`) keep
|
|
259
|
+
* an explicit `onChange` handler — this helper is for the no-transform case.
|
|
260
|
+
*
|
|
261
|
+
* Must be called inside a `<PathShell>` or `<PathProvider>`.
|
|
262
|
+
*/
|
|
263
|
+
export function useField<TData extends PathData, K extends string & keyof TData>(
|
|
264
|
+
field: K
|
|
265
|
+
): { value: string; onChange: (e: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => void } {
|
|
266
|
+
const { snapshot, setData } = usePathContext<TData>();
|
|
267
|
+
const onChange = useCallback(
|
|
268
|
+
(e: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
|
|
269
|
+
setData(field, e.target.value as TData[K]);
|
|
270
|
+
},
|
|
271
|
+
// field is a string literal at the call site and never changes; setData is stable
|
|
272
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
273
|
+
[field, setData]
|
|
274
|
+
);
|
|
275
|
+
return { value: String(snapshot.data[field] ?? ""), onChange };
|
|
206
276
|
}
|
|
207
277
|
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
// Helpers
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
|
|
282
|
+
|
|
208
283
|
// ---------------------------------------------------------------------------
|
|
209
284
|
// Default UI — PathShell
|
|
210
285
|
// ---------------------------------------------------------------------------
|
|
@@ -236,6 +311,8 @@ export interface PathShellProps {
|
|
|
236
311
|
nextLabel?: string;
|
|
237
312
|
/** Label for the Complete button (shown on the last step). Defaults to `"Complete"`. */
|
|
238
313
|
completeLabel?: string;
|
|
314
|
+
/** Label shown on the Next/Complete button while an async operation is in progress. Defaults to `undefined` (button shows a CSS spinner but keeps its label). */
|
|
315
|
+
loadingLabel?: string;
|
|
239
316
|
/** Label for the Cancel button. Defaults to `"Cancel"`. */
|
|
240
317
|
cancelLabel?: string;
|
|
241
318
|
/** If true, hide the Cancel button. Defaults to `false`. */
|
|
@@ -270,6 +347,27 @@ export interface PathShellProps {
|
|
|
270
347
|
* - `"activeOnly"`: Only the active (sub-path) bar — root bar hidden.
|
|
271
348
|
*/
|
|
272
349
|
progressLayout?: ProgressLayout;
|
|
350
|
+
/**
|
|
351
|
+
* Services object passed through context to all step components.
|
|
352
|
+
* Step components access it via `usePathContext<TData, TServices>()`.
|
|
353
|
+
*
|
|
354
|
+
* The same services object that was passed to your path factory function
|
|
355
|
+
* should be passed here so step components can call service methods directly
|
|
356
|
+
* (e.g. parameterised queries that depend on mid-step user input).
|
|
357
|
+
*
|
|
358
|
+
* @example
|
|
359
|
+
* ```tsx
|
|
360
|
+
* const svc = new LiveHiringServices();
|
|
361
|
+
* const path = createHiringPath(svc);
|
|
362
|
+
* <PathShell path={path} services={svc} steps={{ ... }} />
|
|
363
|
+
* ```
|
|
364
|
+
*/
|
|
365
|
+
services?: unknown;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export interface PathShellHandle {
|
|
369
|
+
/** Restart the shell's current path with its original `initialData`, without unmounting. */
|
|
370
|
+
restart: () => void;
|
|
273
371
|
}
|
|
274
372
|
|
|
275
373
|
export interface PathShellActions {
|
|
@@ -281,6 +379,10 @@ export interface PathShellActions {
|
|
|
281
379
|
setData: (key: string, value: unknown) => void;
|
|
282
380
|
/** Restart the shell's current path with its current `initialData`. */
|
|
283
381
|
restart: () => void;
|
|
382
|
+
/** Re-run the operation that set `snapshot.error`. See `PathEngine.retry()`. */
|
|
383
|
+
retry: () => void;
|
|
384
|
+
/** Pause with intent to return, preserving all state. Emits `suspended`. */
|
|
385
|
+
suspend: () => void;
|
|
284
386
|
}
|
|
285
387
|
|
|
286
388
|
/**
|
|
@@ -299,7 +401,7 @@ export interface PathShellActions {
|
|
|
299
401
|
* />
|
|
300
402
|
* ```
|
|
301
403
|
*/
|
|
302
|
-
export function PathShell({
|
|
404
|
+
export const PathShell = forwardRef<PathShellHandle, PathShellProps>(function PathShell({
|
|
303
405
|
path: pathDef,
|
|
304
406
|
engine: externalEngine,
|
|
305
407
|
steps,
|
|
@@ -311,6 +413,7 @@ export function PathShell({
|
|
|
311
413
|
backLabel = "Previous",
|
|
312
414
|
nextLabel = "Next",
|
|
313
415
|
completeLabel = "Complete",
|
|
416
|
+
loadingLabel,
|
|
314
417
|
cancelLabel = "Cancel",
|
|
315
418
|
hideCancel = false,
|
|
316
419
|
hideProgress = false,
|
|
@@ -318,9 +421,10 @@ export function PathShell({
|
|
|
318
421
|
className,
|
|
319
422
|
renderHeader,
|
|
320
423
|
renderFooter,
|
|
321
|
-
validationDisplay = "
|
|
424
|
+
validationDisplay = "summary",
|
|
322
425
|
progressLayout = "merged",
|
|
323
|
-
|
|
426
|
+
services,
|
|
427
|
+
}: PathShellProps, ref): ReactElement {
|
|
324
428
|
const pathReturn = usePath({
|
|
325
429
|
engine: externalEngine,
|
|
326
430
|
onEvent(event) {
|
|
@@ -330,7 +434,11 @@ export function PathShell({
|
|
|
330
434
|
}
|
|
331
435
|
});
|
|
332
436
|
|
|
333
|
-
const { snapshot, start, next, previous, cancel, goToStep, goToStepChecked, setData, restart } = pathReturn;
|
|
437
|
+
const { snapshot, start, next, previous, cancel, goToStep, goToStepChecked, setData, restart, retry, suspend } = pathReturn;
|
|
438
|
+
|
|
439
|
+
useImperativeHandle(ref, () => ({
|
|
440
|
+
restart: () => restart(),
|
|
441
|
+
}));
|
|
334
442
|
|
|
335
443
|
// Auto-start on mount — skipped when an external engine is provided since
|
|
336
444
|
// the caller is responsible for starting it (e.g. via createPersistedEngine).
|
|
@@ -351,8 +459,10 @@ export function PathShell({
|
|
|
351
459
|
? ((snapshot.formId ? steps[snapshot.formId] : undefined) ?? steps[snapshot.stepId] ?? null)
|
|
352
460
|
: null;
|
|
353
461
|
|
|
462
|
+
const contextValue: PathContextValue = { path: pathReturn, services: services ?? null };
|
|
463
|
+
|
|
354
464
|
if (!snapshot) {
|
|
355
|
-
return createElement(PathContext.Provider, { value:
|
|
465
|
+
return createElement(PathContext.Provider, { value: contextValue },
|
|
356
466
|
createElement("div", { className: cls("pw-shell", className) },
|
|
357
467
|
createElement("div", { className: "pw-shell__empty" },
|
|
358
468
|
createElement("p", null, "No active path."),
|
|
@@ -368,7 +478,9 @@ export function PathShell({
|
|
|
368
478
|
|
|
369
479
|
const actions: PathShellActions = {
|
|
370
480
|
next, previous, cancel, goToStep, goToStepChecked, setData,
|
|
371
|
-
restart: () => restart(
|
|
481
|
+
restart: () => restart(),
|
|
482
|
+
retry: () => retry(),
|
|
483
|
+
suspend: () => suspend(),
|
|
372
484
|
};
|
|
373
485
|
|
|
374
486
|
const showRoot = !hideProgress && !!snapshot.rootProgress && progressLayout !== "activeOnly";
|
|
@@ -376,7 +488,7 @@ export function PathShell({
|
|
|
376
488
|
? true
|
|
377
489
|
: (snapshot.stepCount > 1 || snapshot.nestingLevel > 0) && progressLayout !== "rootOnly");
|
|
378
490
|
|
|
379
|
-
return createElement(PathContext.Provider, { value:
|
|
491
|
+
return createElement(PathContext.Provider, { value: contextValue },
|
|
380
492
|
createElement("div", { className: cls("pw-shell", progressLayout !== "merged" && `pw-shell--progress-${progressLayout}`, className) },
|
|
381
493
|
// Root progress — persistent top-level bar visible during sub-paths
|
|
382
494
|
showRoot && defaultRootProgress(snapshot.rootProgress!),
|
|
@@ -404,15 +516,21 @@ export function PathShell({
|
|
|
404
516
|
)
|
|
405
517
|
)
|
|
406
518
|
),
|
|
407
|
-
//
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
519
|
+
// Blocking error — guard returned { allowed: false, reason }
|
|
520
|
+
validationDisplay !== "inline" && snapshot.hasAttemptedNext && snapshot.blockingError &&
|
|
521
|
+
createElement("p", { className: "pw-shell__blocking-error" }, snapshot.blockingError),
|
|
522
|
+
// Error panel — replaces footer when an async operation has failed
|
|
523
|
+
snapshot.status === "error" && snapshot.error
|
|
524
|
+
? defaultErrorPanel(snapshot, actions)
|
|
525
|
+
// Footer — navigation buttons
|
|
526
|
+
: renderFooter
|
|
527
|
+
? renderFooter(snapshot, actions)
|
|
528
|
+
: defaultFooter(snapshot, actions, {
|
|
529
|
+
backLabel, nextLabel, completeLabel, loadingLabel, cancelLabel, hideCancel, footerLayout
|
|
530
|
+
})
|
|
413
531
|
)
|
|
414
532
|
);
|
|
415
|
-
}
|
|
533
|
+
});
|
|
416
534
|
|
|
417
535
|
// ---------------------------------------------------------------------------
|
|
418
536
|
// Root progress (compact top-level bar visible during sub-paths)
|
|
@@ -474,6 +592,47 @@ function defaultHeader(snapshot: PathSnapshot): ReactElement {
|
|
|
474
592
|
);
|
|
475
593
|
}
|
|
476
594
|
|
|
595
|
+
// ---------------------------------------------------------------------------
|
|
596
|
+
// Default error panel
|
|
597
|
+
// ---------------------------------------------------------------------------
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
function defaultErrorPanel(
|
|
601
|
+
snapshot: PathSnapshot,
|
|
602
|
+
actions: PathShellActions
|
|
603
|
+
): ReactElement {
|
|
604
|
+
const { error, hasPersistence } = snapshot;
|
|
605
|
+
if (!error) return createElement("div", null);
|
|
606
|
+
const escalated = error.retryCount >= 2;
|
|
607
|
+
const title = escalated ? "Still having trouble." : "Something went wrong.";
|
|
608
|
+
const phaseMsg = errorPhaseMessage(error.phase);
|
|
609
|
+
|
|
610
|
+
return createElement("div", { className: "pw-shell__error" },
|
|
611
|
+
createElement("div", { className: "pw-shell__error-title" }, title),
|
|
612
|
+
createElement("div", { className: "pw-shell__error-message" },
|
|
613
|
+
phaseMsg,
|
|
614
|
+
error.message && ` ${error.message}`
|
|
615
|
+
),
|
|
616
|
+
createElement("div", { className: "pw-shell__error-actions" },
|
|
617
|
+
!escalated && createElement("button", {
|
|
618
|
+
type: "button",
|
|
619
|
+
className: "pw-shell__btn pw-shell__btn--retry",
|
|
620
|
+
onClick: actions.retry
|
|
621
|
+
}, "Try again"),
|
|
622
|
+
hasPersistence && createElement("button", {
|
|
623
|
+
type: "button",
|
|
624
|
+
className: cls("pw-shell__btn", escalated ? "pw-shell__btn--retry" : "pw-shell__btn--suspend"),
|
|
625
|
+
onClick: actions.suspend
|
|
626
|
+
}, "Save and come back later"),
|
|
627
|
+
escalated && !hasPersistence && createElement("button", {
|
|
628
|
+
type: "button",
|
|
629
|
+
className: "pw-shell__btn pw-shell__btn--retry",
|
|
630
|
+
onClick: actions.retry
|
|
631
|
+
}, "Try again")
|
|
632
|
+
)
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
|
|
477
636
|
// ---------------------------------------------------------------------------
|
|
478
637
|
// Default footer (navigation buttons)
|
|
479
638
|
// ---------------------------------------------------------------------------
|
|
@@ -482,6 +641,7 @@ interface FooterLabels {
|
|
|
482
641
|
backLabel: string;
|
|
483
642
|
nextLabel: string;
|
|
484
643
|
completeLabel: string;
|
|
644
|
+
loadingLabel?: string;
|
|
485
645
|
cancelLabel: string;
|
|
486
646
|
hideCancel: boolean;
|
|
487
647
|
footerLayout: "wizard" | "form" | "auto";
|
|
@@ -505,14 +665,14 @@ function defaultFooter(
|
|
|
505
665
|
isFormMode && !labels.hideCancel && createElement("button", {
|
|
506
666
|
type: "button",
|
|
507
667
|
className: "pw-shell__btn pw-shell__btn--cancel",
|
|
508
|
-
disabled: snapshot.
|
|
668
|
+
disabled: snapshot.status !== "idle",
|
|
509
669
|
onClick: actions.cancel
|
|
510
670
|
}, labels.cancelLabel),
|
|
511
671
|
// Wizard mode: Back on the left
|
|
512
672
|
!isFormMode && !snapshot.isFirstStep && createElement("button", {
|
|
513
673
|
type: "button",
|
|
514
674
|
className: "pw-shell__btn pw-shell__btn--back",
|
|
515
|
-
disabled: snapshot.
|
|
675
|
+
disabled: snapshot.status !== "idle" || !snapshot.canMovePrevious,
|
|
516
676
|
onClick: actions.previous
|
|
517
677
|
}, labels.backLabel)
|
|
518
678
|
),
|
|
@@ -521,16 +681,18 @@ function defaultFooter(
|
|
|
521
681
|
!isFormMode && !labels.hideCancel && createElement("button", {
|
|
522
682
|
type: "button",
|
|
523
683
|
className: "pw-shell__btn pw-shell__btn--cancel",
|
|
524
|
-
disabled: snapshot.
|
|
684
|
+
disabled: snapshot.status !== "idle",
|
|
525
685
|
onClick: actions.cancel
|
|
526
686
|
}, labels.cancelLabel),
|
|
527
687
|
// Both modes: Submit on the right
|
|
528
688
|
createElement("button", {
|
|
529
689
|
type: "button",
|
|
530
|
-
className: "pw-shell__btn pw-shell__btn--next",
|
|
531
|
-
disabled: snapshot.
|
|
690
|
+
className: cls("pw-shell__btn pw-shell__btn--next", snapshot.status !== "idle" && "pw-shell__btn--loading"),
|
|
691
|
+
disabled: snapshot.status !== "idle",
|
|
532
692
|
onClick: actions.next
|
|
533
|
-
}, snapshot.
|
|
693
|
+
}, snapshot.status !== "idle" && labels.loadingLabel
|
|
694
|
+
? labels.loadingLabel
|
|
695
|
+
: snapshot.isLastStep ? labels.completeLabel : labels.nextLabel)
|
|
534
696
|
)
|
|
535
697
|
);
|
|
536
698
|
}
|