@daltonr/pathwrite-svelte 0.13.0 → 0.14.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 +10 -16
- package/dist/PathShell.svelte +151 -84
- package/dist/PathShell.svelte.d.ts +15 -8
- package/dist/PathShell.svelte.d.ts.map +1 -1
- package/dist/index.css +12 -4
- package/dist/index.svelte.d.ts +12 -12
- package/dist/index.svelte.d.ts.map +1 -1
- package/dist/index.svelte.js +18 -9
- package/package.json +3 -3
- package/src/PathShell.svelte +151 -84
- package/src/index.svelte.ts +60 -43
package/src/index.svelte.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { onDestroy, getContext, setContext } from "svelte";
|
|
2
|
-
import type {
|
|
3
|
-
PathData,
|
|
4
|
-
PathDefinition,
|
|
5
|
-
PathEngine,
|
|
6
|
-
PathEvent,
|
|
7
|
-
PathSnapshot
|
|
8
|
-
} from "@daltonr/pathwrite-core";
|
|
2
|
+
import type { PathData, PathDefinition, PathEngine, PathEvent, PathSnapshot } from "@daltonr/pathwrite-core";
|
|
9
3
|
import { PathEngine as PathEngineClass } from "@daltonr/pathwrite-core";
|
|
10
4
|
|
|
11
5
|
// Re-export core utilities and types for convenience
|
|
@@ -17,18 +11,19 @@ export type {
|
|
|
17
11
|
PathEngine,
|
|
18
12
|
PathEvent,
|
|
19
13
|
PathSnapshot,
|
|
14
|
+
StepStatus,
|
|
20
15
|
PathStep,
|
|
21
16
|
PathStepContext,
|
|
22
17
|
ProgressLayout,
|
|
23
18
|
RootProgress,
|
|
24
|
-
SerializedPathState
|
|
19
|
+
SerializedPathState,
|
|
25
20
|
} from "@daltonr/pathwrite-core";
|
|
26
21
|
|
|
27
22
|
// ---------------------------------------------------------------------------
|
|
28
23
|
// Types
|
|
29
24
|
// ---------------------------------------------------------------------------
|
|
30
25
|
|
|
31
|
-
export interface UsePathOptions {
|
|
26
|
+
export interface UsePathOptions<TData extends PathData = PathData> {
|
|
32
27
|
/**
|
|
33
28
|
* An externally-managed `PathEngine` to subscribe to — for example, the engine
|
|
34
29
|
* returned by `restoreOrStart()` from `@daltonr/pathwrite-store`.
|
|
@@ -45,23 +40,27 @@ export interface UsePathOptions {
|
|
|
45
40
|
* later (e.g. from an async `restoreOrStart()`) or is swapped is adopted —
|
|
46
41
|
* the hook re-subscribes and re-seeds its snapshot from the new engine.
|
|
47
42
|
*/
|
|
48
|
-
engine?: PathEngine
|
|
43
|
+
engine?: PathEngine<TData>;
|
|
49
44
|
/** Called for every engine event (stateChanged, completed, cancelled, resumed). */
|
|
50
|
-
onEvent?: (event: PathEvent) => void;
|
|
45
|
+
onEvent?: (event: PathEvent<TData>) => void;
|
|
51
46
|
}
|
|
52
47
|
|
|
53
48
|
export interface UsePathReturn<TData extends PathData = PathData> {
|
|
54
49
|
/**
|
|
55
|
-
* Current path snapshot, or `null` when no path is active. Reactive via `$state`.
|
|
50
|
+
* Current path snapshot, or `null` when no path is active. Reactive via `$state.raw`.
|
|
56
51
|
*
|
|
57
52
|
* ⚠️ **Do not destructure.** `const { snapshot } = usePath()` captures the value
|
|
58
53
|
* once and loses reactivity. Always access as `path.snapshot`.
|
|
59
54
|
*/
|
|
60
55
|
readonly snapshot: PathSnapshot<TData> | null;
|
|
61
56
|
/** Start (or restart) a path. */
|
|
62
|
-
start: (path: PathDefinition<
|
|
63
|
-
/** Push a sub-path onto the stack. Requires an active path. Pass an optional `meta` object for correlation — it is returned unchanged to the parent step's `onSubPathComplete` / `onSubPathCancel` hooks. */
|
|
64
|
-
startSubPath: (
|
|
57
|
+
start: (path: PathDefinition<TData>, initialData?: Partial<TData>) => Promise<void>;
|
|
58
|
+
/** Push a sub-path onto the stack. Requires an active path. A sub-path has its own data, so any definition is accepted. Pass an optional `meta` object for correlation — it is returned unchanged to the parent step's `onSubPathComplete` / `onSubPathCancel` hooks. */
|
|
59
|
+
startSubPath: (
|
|
60
|
+
path: PathDefinition,
|
|
61
|
+
initialData?: PathData,
|
|
62
|
+
meta?: Record<string, unknown>
|
|
63
|
+
) => Promise<void>;
|
|
65
64
|
/** Advance one step. Completes the path on the last step. */
|
|
66
65
|
next: () => Promise<void>;
|
|
67
66
|
/** Go back one step. No-op when already on the first step of a top-level path. Pops back to the parent path when on the first step of a sub-path. */
|
|
@@ -150,21 +149,24 @@ export interface UsePathReturn<TData extends PathData = PathData> {
|
|
|
150
149
|
* ```
|
|
151
150
|
*/
|
|
152
151
|
export function usePath<TData extends PathData = PathData>(
|
|
153
|
-
options?: UsePathOptions
|
|
152
|
+
options?: UsePathOptions<TData>
|
|
154
153
|
): UsePathReturn<TData> {
|
|
155
|
-
let ownEngine: PathEngine | null = null;
|
|
156
|
-
const resolveEngine = (): PathEngine =>
|
|
154
|
+
let ownEngine: PathEngine<TData> | null = null;
|
|
155
|
+
const resolveEngine = (): PathEngine<TData> =>
|
|
156
|
+
options?.engine ?? (ownEngine ??= new PathEngineClass<TData>());
|
|
157
157
|
let engine = resolveEngine();
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
)
|
|
159
|
+
// `$state.raw`, not `$state`: snapshots are immutable values the engine
|
|
160
|
+
// replaces wholesale on every change and nothing mutates them in place, so a
|
|
161
|
+
// deep proxy over each one (and its `data`) would be pure overhead. Every
|
|
162
|
+
// update below reassigns the whole value, which is what `$state.raw` tracks.
|
|
163
|
+
let _snapshot: PathSnapshot<TData> | null = $state.raw(engine.snapshot());
|
|
162
164
|
|
|
163
|
-
const onEngineEvent = (event: PathEvent): void => {
|
|
165
|
+
const onEngineEvent = (event: PathEvent<TData>): void => {
|
|
164
166
|
if (event.type === "stateChanged" || event.type === "resumed") {
|
|
165
|
-
_snapshot = event.snapshot
|
|
167
|
+
_snapshot = event.snapshot;
|
|
166
168
|
} else if (event.type === "completed" || event.type === "cancelled") {
|
|
167
|
-
_snapshot = engine.snapshot()
|
|
169
|
+
_snapshot = engine.snapshot();
|
|
168
170
|
}
|
|
169
171
|
options?.onEvent?.(event);
|
|
170
172
|
};
|
|
@@ -179,19 +181,22 @@ export function usePath<TData extends PathData = PathData>(
|
|
|
179
181
|
if (next === engine) return;
|
|
180
182
|
unsubscribe();
|
|
181
183
|
engine = next;
|
|
182
|
-
_snapshot = engine.snapshot()
|
|
184
|
+
_snapshot = engine.snapshot();
|
|
183
185
|
unsubscribe = engine.subscribe(onEngineEvent);
|
|
184
186
|
});
|
|
185
187
|
});
|
|
186
188
|
|
|
187
189
|
// Auto-cleanup when component is destroyed
|
|
188
|
-
onDestroy(() => {
|
|
190
|
+
onDestroy(() => {
|
|
191
|
+
unsubscribe();
|
|
192
|
+
stopWatching();
|
|
193
|
+
});
|
|
189
194
|
|
|
190
|
-
const start = (path: PathDefinition<
|
|
195
|
+
const start = (path: PathDefinition<TData>, initialData: Partial<TData> = {}): Promise<void> =>
|
|
191
196
|
engine.start(path, initialData);
|
|
192
197
|
|
|
193
198
|
const startSubPath = (
|
|
194
|
-
path: PathDefinition
|
|
199
|
+
path: PathDefinition,
|
|
195
200
|
initialData: PathData = {},
|
|
196
201
|
meta?: Record<string, unknown>
|
|
197
202
|
): Promise<void> => engine.startSubPath(path, initialData, meta);
|
|
@@ -200,11 +205,13 @@ export function usePath<TData extends PathData = PathData>(
|
|
|
200
205
|
const previous = (): Promise<void> => engine.previous();
|
|
201
206
|
const cancel = (): Promise<void> => engine.cancel();
|
|
202
207
|
|
|
203
|
-
const goToStep = (stepId: string, options?: { validateOnLeave?: boolean }): Promise<void> =>
|
|
204
|
-
|
|
208
|
+
const goToStep = (stepId: string, options?: { validateOnLeave?: boolean }): Promise<void> =>
|
|
209
|
+
engine.goToStep(stepId, options);
|
|
210
|
+
const goToStepChecked = (stepId: string, options?: { validateOnLeave?: boolean }): Promise<void> =>
|
|
211
|
+
engine.goToStepChecked(stepId, options);
|
|
205
212
|
|
|
206
|
-
const setData =
|
|
207
|
-
engine.setData(key, value
|
|
213
|
+
const setData = <K extends string & keyof TData>(key: K, value: TData[K]): Promise<void> =>
|
|
214
|
+
engine.setData(key, value);
|
|
208
215
|
|
|
209
216
|
const resetStep = (): Promise<void> => engine.resetStep();
|
|
210
217
|
|
|
@@ -215,7 +222,9 @@ export function usePath<TData extends PathData = PathData>(
|
|
|
215
222
|
const validate = (): void => engine.validate();
|
|
216
223
|
|
|
217
224
|
return {
|
|
218
|
-
get snapshot() {
|
|
225
|
+
get snapshot() {
|
|
226
|
+
return _snapshot;
|
|
227
|
+
},
|
|
219
228
|
start,
|
|
220
229
|
startSubPath,
|
|
221
230
|
next,
|
|
@@ -228,7 +237,7 @@ export function usePath<TData extends PathData = PathData>(
|
|
|
228
237
|
restart,
|
|
229
238
|
retry,
|
|
230
239
|
suspend,
|
|
231
|
-
validate
|
|
240
|
+
validate,
|
|
232
241
|
};
|
|
233
242
|
}
|
|
234
243
|
|
|
@@ -263,7 +272,10 @@ const PATH_CONTEXT_KEY = Symbol("pathwrite-context");
|
|
|
263
272
|
* returns (derived from `UsePathReturn`, so the two cannot drift apart) plus
|
|
264
273
|
* the `services` object given to `<PathShell>`.
|
|
265
274
|
*/
|
|
266
|
-
export interface PathContext<
|
|
275
|
+
export interface PathContext<
|
|
276
|
+
TData extends PathData = PathData,
|
|
277
|
+
TServices = unknown,
|
|
278
|
+
> extends UsePathReturn<TData> {
|
|
267
279
|
services: TServices;
|
|
268
280
|
}
|
|
269
281
|
|
|
@@ -287,7 +299,10 @@ export interface PathContext<TData extends PathData = PathData, TServices = unkn
|
|
|
287
299
|
* <button onclick={ctx.next}>Next</button>
|
|
288
300
|
* ```
|
|
289
301
|
*/
|
|
290
|
-
export function usePathContext<TData extends PathData = PathData, TServices = unknown>(): PathContext<
|
|
302
|
+
export function usePathContext<TData extends PathData = PathData, TServices = unknown>(): PathContext<
|
|
303
|
+
TData,
|
|
304
|
+
TServices
|
|
305
|
+
> {
|
|
291
306
|
const ctx = getContext<PathContext<TData, TServices>>(PATH_CONTEXT_KEY);
|
|
292
307
|
if (!ctx) {
|
|
293
308
|
throw new Error(
|
|
@@ -302,7 +317,9 @@ export function usePathContext<TData extends PathData = PathData, TServices = un
|
|
|
302
317
|
* Internal: Set the PathContext for child components.
|
|
303
318
|
* Used by PathShell component.
|
|
304
319
|
*/
|
|
305
|
-
export function setPathContext<TData extends PathData = PathData, TServices = unknown>(
|
|
320
|
+
export function setPathContext<TData extends PathData = PathData, TServices = unknown>(
|
|
321
|
+
ctx: PathContext<TData, TServices>
|
|
322
|
+
): void {
|
|
306
323
|
setContext(PATH_CONTEXT_KEY, ctx);
|
|
307
324
|
}
|
|
308
325
|
|
|
@@ -312,7 +329,8 @@ export function setPathContext<TData extends PathData = PathData, TServices = un
|
|
|
312
329
|
* the outer shell's context for `restoreKey` auto-wiring — must be called
|
|
313
330
|
* before `setPathContext()` so it reads the parent rather than self.
|
|
314
331
|
*/
|
|
315
|
-
export function getPathContextOrNull<TData extends PathData = PathData, TServices = unknown>():
|
|
332
|
+
export function getPathContextOrNull<TData extends PathData = PathData, TServices = unknown>():
|
|
333
|
+
PathContext<TData, TServices> | undefined {
|
|
316
334
|
return getContext<PathContext<TData, TServices>>(PATH_CONTEXT_KEY);
|
|
317
335
|
}
|
|
318
336
|
|
|
@@ -351,15 +369,15 @@ export function bindData<TData extends PathData, K extends string & keyof TData>
|
|
|
351
369
|
},
|
|
352
370
|
set(value: TData[K]) {
|
|
353
371
|
setData(key, value);
|
|
354
|
-
}
|
|
372
|
+
},
|
|
355
373
|
};
|
|
356
374
|
}
|
|
357
375
|
|
|
358
376
|
/**
|
|
359
377
|
* Converts a hyphenated step ID to camelCase.
|
|
360
|
-
* Used internally by PathShell
|
|
361
|
-
*
|
|
362
|
-
*
|
|
378
|
+
* Used internally by PathShell as a fallback key into its `steps` record, so a
|
|
379
|
+
* hyphenated step ID (e.g. "cover-letter") also resolves an entry registered
|
|
380
|
+
* under its camelCase form ("coverLetter").
|
|
363
381
|
*/
|
|
364
382
|
export function stepIdToCamelCase(id: string): string {
|
|
365
383
|
return id.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());
|
|
@@ -367,4 +385,3 @@ export function stepIdToCamelCase(id: string): string {
|
|
|
367
385
|
|
|
368
386
|
// Export PathShell component
|
|
369
387
|
export { default as PathShell } from "./PathShell.svelte";
|
|
370
|
-
|