@daltonr/pathwrite-angular 0.7.0 → 0.9.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
@@ -410,7 +410,7 @@ import {
410
410
  @Component({
411
411
  imports: [PathShellComponent, PathStepDirective],
412
412
  template: `
413
- <pw-shell [path]="myPath" [initialData]="{ name: '' }" (completed)="onDone($event)">
413
+ <pw-shell [path]="myPath" [initialData]="{ name: '' }" (complete)="onDone($event)">
414
414
  <ng-template pwStep="details"><app-details-form /></ng-template>
415
415
  <ng-template pwStep="review"><app-review-panel /></ng-template>
416
416
  </pw-shell>
@@ -484,7 +484,7 @@ The parent component hosting `<pw-shell>` does **not** need its own
484
484
  @Component({
485
485
  imports: [PathShellComponent, PathStepDirective],
486
486
  template: `
487
- <pw-shell #shell [path]="myPath" (completed)="onDone($event)">
487
+ <pw-shell #shell [path]="myPath" (complete)="onDone($event)">
488
488
  <ng-template pwStep="details"><app-details-form /></ng-template>
489
489
  </pw-shell>
490
490
  `
@@ -499,9 +499,10 @@ export class MyComponent {
499
499
 
500
500
  | Input | Type | Default | Description |
501
501
  |-------|------|---------|-------------|
502
- | `path` | `PathDefinition` | *required* | The path definition to drive. |
502
+ | `path` | `PathDefinition` | | The path definition to drive. Required unless `[engine]` is provided. |
503
+ | `engine` | `PathEngine` | — | An externally-managed engine (e.g. from `restoreOrStart()`). When provided, `autoStart` is suppressed and the shell immediately reflects the engine's current state. Use `@if (engine)` in the parent template to gate mounting until the engine is ready. |
503
504
  | `initialData` | `PathData` | `{}` | Initial data passed to `facade.start()`. |
504
- | `autoStart` | `boolean` | `true` | Start the path automatically on `ngOnInit`. |
505
+ | `autoStart` | `boolean` | `true` | Start the path automatically on `ngOnInit`. Ignored when `[engine]` is provided. |
505
506
  | `backLabel` | `string` | `"Previous"` | Previous button label. |
506
507
  | `nextLabel` | `string` | `"Next"` | Next button label. |
507
508
  | `completeLabel` | `string` | `"Complete"` | Complete button label (last step). |
@@ -514,9 +515,9 @@ export class MyComponent {
514
515
 
515
516
  | Output | Payload | Description |
516
517
  |--------|---------|-------------|
517
- | `(completed)` | `PathData` | Emitted when the path finishes naturally. |
518
- | `(cancelled)` | `PathData` | Emitted when the path is cancelled. |
519
- | `(pathEvent)` | `PathEvent` | Emitted for every engine event. |
518
+ | `(complete)` | `PathData` | Emitted when the path finishes naturally. |
519
+ | `(cancel)` | `PathData` | Emitted when the path is cancelled. |
520
+ | `(event)` | `PathEvent` | Emitted for every engine event. |
520
521
 
521
522
  ### Customising the header and footer
522
523
 
@@ -576,7 +577,7 @@ Toggle an `@if` flag to destroy and recreate the shell. Every child component re
576
577
 
577
578
  ```html
578
579
  @if (isActive) {
579
- <pw-shell [path]="myPath" (completed)="isActive = false" (cancelled)="isActive = false">
580
+ <pw-shell [path]="myPath" (complete)="isActive = false" (cancel)="isActive = false">
580
581
  <ng-template pwStep="details"><app-details-form /></ng-template>
581
582
  </pw-shell>
582
583
  } @else {
@@ -589,7 +590,7 @@ Toggle an `@if` flag to destroy and recreate the shell. Every child component re
589
590
  Use the existing `#shell` template reference — `restart()` is a public method:
590
591
 
591
592
  ```html
592
- <pw-shell #shell [path]="myPath" (completed)="onDone($event)">
593
+ <pw-shell #shell [path]="myPath" (complete)="onDone($event)">
593
594
  <ng-template pwStep="details"><app-details-form /></ng-template>
594
595
  </pw-shell>
595
596
 
@@ -872,24 +873,24 @@ Use it to distinguish initialization from re-entry:
872
873
 
873
874
  ## Persistence
874
875
 
875
- Use with [@daltonr/pathwrite-store-http](../store-http) for automatic state persistence. The engine is created externally via `restoreOrStart()`, then handed to the facade via `adoptEngine()`.
876
+ Use with [@daltonr/pathwrite-store](../store) for automatic state persistence. The engine is created externally via `restoreOrStart()` and passed directly to `<pw-shell>` via the `[engine]` input.
876
877
 
877
878
  ### Simple persistence example
878
879
 
879
880
  ```typescript
880
- import { Component, inject, OnInit } from '@angular/core';
881
- import { PathFacade, PathShellComponent, PathStepDirective } from '@daltonr/pathwrite-angular';
882
- import { HttpStore, restoreOrStart, httpPersistence } from '@daltonr/pathwrite-store-http';
881
+ import { Component, OnInit } from '@angular/core';
882
+ import { PathEngine } from '@daltonr/pathwrite-angular';
883
+ import { PathShellComponent, PathStepDirective } from '@daltonr/pathwrite-angular/shell';
884
+ import { HttpStore, restoreOrStart, persistence } from '@daltonr/pathwrite-store';
883
885
  import { signupPath } from './signup-path';
884
886
 
885
887
  @Component({
886
888
  selector: 'app-signup-wizard',
887
889
  standalone: true,
888
890
  imports: [PathShellComponent, PathStepDirective],
889
- providers: [PathFacade],
890
891
  template: `
891
- @if (ready) {
892
- <pw-shell [path]="path" [autoStart]="false" (completed)="onComplete($event)">
892
+ @if (engine) {
893
+ <pw-shell [path]="path" [engine]="engine" (complete)="onComplete($event)">
893
894
  <ng-template pwStep="details"><app-details-form /></ng-template>
894
895
  <ng-template pwStep="review"><app-review-panel /></ng-template>
895
896
  </pw-shell>
@@ -899,10 +900,8 @@ import { signupPath } from './signup-path';
899
900
  `
900
901
  })
901
902
  export class SignupWizardComponent implements OnInit {
902
- private readonly facade = inject(PathFacade);
903
-
904
903
  path = signupPath;
905
- ready = false;
904
+ engine: PathEngine | null = null;
906
905
 
907
906
  async ngOnInit() {
908
907
  const store = new HttpStore({ baseUrl: '/api/wizard' });
@@ -914,14 +913,11 @@ export class SignupWizardComponent implements OnInit {
914
913
  path: this.path,
915
914
  initialData: { name: '', email: '' },
916
915
  observers: [
917
- httpPersistence({ store, key, strategy: 'onNext' })
916
+ persistence({ store, key, strategy: 'onNext' })
918
917
  ]
919
918
  });
920
919
 
921
- // Hand the running engine to the facade — it immediately
922
- // reflects the engine's current state and forwards all events.
923
- this.facade.adoptEngine(engine);
924
- this.ready = true;
920
+ this.engine = engine;
925
921
 
926
922
  if (restored) {
927
923
  console.log('Progress restored — resuming from', engine.snapshot()?.stepId);
@@ -936,9 +932,8 @@ export class SignupWizardComponent implements OnInit {
936
932
 
937
933
  ### Key points
938
934
 
939
- - **`adoptEngine()`** connects the facade to an externally-created engine. No `@ViewChild` or shell reference needed inject `PathFacade` directly.
940
- - **`[autoStart]="false"`** prevents the shell from calling `start()` on its own the engine is already running.
941
- - **The facade is the same one the shell uses** (provided in the component's `providers`), so the shell's template bindings, progress indicator, and navigation buttons all work automatically.
935
+ - **`[engine]`** passes an externally-managed engine directly to the shell. The shell adopts it immediately and skips `autoStart`.
936
+ - **`@if (engine)`** acts as the async gate the shell only mounts once the engine is ready, so there is no timing window where `autoStart` could fire before the engine arrives.
942
937
  - **`restoreOrStart()`** handles the load-or-create logic: if saved state exists on the server, it restores the engine mid-flow; otherwise it starts fresh.
943
938
 
944
939
  ---
package/dist/index.css CHANGED
@@ -246,6 +246,9 @@
246
246
  --pw-color-error: #dc2626;
247
247
  --pw-color-error-bg: #fef2f2;
248
248
  --pw-color-error-border: #fecaca;
249
+ --pw-color-warning: #d97706;
250
+ --pw-color-warning-bg: #fffbeb;
251
+ --pw-color-warning-border: #fde68a;
249
252
  }
250
253
 
251
254
  .pw-shell__validation {
@@ -282,6 +285,43 @@
282
285
  content: ":";
283
286
  }
284
287
 
288
+ /* ------------------------------------------------------------------ */
289
+ /* Warning messages */
290
+ /* ------------------------------------------------------------------ */
291
+ .pw-shell__warnings {
292
+ list-style: none;
293
+ margin: 0;
294
+ padding: 12px 16px;
295
+ background: var(--pw-color-warning-bg);
296
+ border: 1px solid var(--pw-color-warning-border);
297
+ border-radius: var(--pw-shell-radius);
298
+ display: flex;
299
+ flex-direction: column;
300
+ gap: 4px;
301
+ }
302
+
303
+ .pw-shell__warnings-item {
304
+ font-size: 13px;
305
+ color: var(--pw-color-warning);
306
+ padding-left: 16px;
307
+ position: relative;
308
+ }
309
+
310
+ .pw-shell__warnings-item::before {
311
+ content: "•";
312
+ position: absolute;
313
+ left: 4px;
314
+ }
315
+
316
+ .pw-shell__warnings-label {
317
+ font-weight: 600;
318
+ margin-right: 3px;
319
+ }
320
+
321
+ .pw-shell__warnings-label::after {
322
+ content: ":";
323
+ }
324
+
285
325
  /* ------------------------------------------------------------------ */
286
326
  /* Footer — navigation buttons */
287
327
  /* ------------------------------------------------------------------ */
package/dist/index.d.ts CHANGED
@@ -29,7 +29,7 @@ export declare class PathFacade<TData extends PathData = PathData> implements On
29
29
  constructor();
30
30
  /**
31
31
  * Adopt an externally-managed `PathEngine` — for example, the engine returned
32
- * by `restoreOrStart()` from `@daltonr/pathwrite-store-http`.
32
+ * by `restoreOrStart()` from `@daltonr/pathwrite-store`.
33
33
  *
34
34
  * The facade immediately reflects the engine's current state and forwards all
35
35
  * subsequent events. The **caller** is responsible for the engine's lifecycle
@@ -50,12 +50,15 @@ export declare class PathFacade<TData extends PathData = PathData> implements On
50
50
  * Use for "Start over" / retry flows without destroying and re-creating the
51
51
  * component that provides this facade.
52
52
  */
53
- restart(path: PathDefinition<any>, initialData?: PathData): Promise<void>;
53
+ restart(): Promise<void>;
54
54
  startSubPath(path: PathDefinition<any>, initialData?: PathData, meta?: Record<string, unknown>): Promise<void>;
55
55
  next(): Promise<void>;
56
56
  previous(): Promise<void>;
57
57
  cancel(): Promise<void>;
58
58
  setData<K extends string & keyof TData>(key: K, value: TData[K]): Promise<void>;
59
+ /** Reset the current step's data to what it was when the step was entered.
60
+ * Useful for "Clear" or "Reset" buttons that undo changes within a step. */
61
+ resetStep(): Promise<void>;
59
62
  goToStep(stepId: string): Promise<void>;
60
63
  /** Jump to a step by ID, checking the current step's canMoveNext (forward) or
61
64
  * canMovePrevious (backward) guard first. Navigation is blocked if the guard
@@ -85,6 +88,8 @@ export interface InjectPathReturn<TData extends PathData = PathData> {
85
88
  cancel: () => Promise<void>;
86
89
  /** Update a single data field. */
87
90
  setData: <K extends string & keyof TData>(key: K, value: TData[K]) => Promise<void>;
91
+ /** Reset the current step's data to what it was when the step was entered. */
92
+ resetStep: () => Promise<void>;
88
93
  /** Jump to a step by ID without checking guards. */
89
94
  goToStep: (stepId: string) => Promise<void>;
90
95
  /** Jump to a step by ID, checking guards first. */
@@ -93,7 +98,7 @@ export interface InjectPathReturn<TData extends PathData = PathData> {
93
98
  * Tears down any active path and immediately starts the given path fresh.
94
99
  * Use for "Start over" / retry flows.
95
100
  */
96
- restart: (path: PathDefinition<any>, initialData?: PathData) => Promise<void>;
101
+ restart: () => Promise<void>;
97
102
  }
98
103
  /**
99
104
  * Inject a PathFacade and return a signal-based API for use in Angular components.
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ export class PathFacade {
31
31
  }
32
32
  /**
33
33
  * Adopt an externally-managed `PathEngine` — for example, the engine returned
34
- * by `restoreOrStart()` from `@daltonr/pathwrite-store-http`.
34
+ * by `restoreOrStart()` from `@daltonr/pathwrite-store`.
35
35
  *
36
36
  * The facade immediately reflects the engine's current state and forwards all
37
37
  * subsequent events. The **caller** is responsible for the engine's lifecycle
@@ -80,8 +80,8 @@ export class PathFacade {
80
80
  * Use for "Start over" / retry flows without destroying and re-creating the
81
81
  * component that provides this facade.
82
82
  */
83
- restart(path, initialData = {}) {
84
- return this._engine.restart(path, initialData);
83
+ restart() {
84
+ return this._engine.restart();
85
85
  }
86
86
  startSubPath(path, initialData = {}, meta) {
87
87
  return this._engine.startSubPath(path, initialData, meta);
@@ -98,6 +98,11 @@ export class PathFacade {
98
98
  setData(key, value) {
99
99
  return this._engine.setData(key, value);
100
100
  }
101
+ /** Reset the current step's data to what it was when the step was entered.
102
+ * Useful for "Clear" or "Reset" buttons that undo changes within a step. */
103
+ resetStep() {
104
+ return this._engine.resetStep();
105
+ }
101
106
  goToStep(stepId) {
102
107
  return this._engine.goToStep(stepId);
103
108
  }
@@ -166,9 +171,10 @@ export function injectPath() {
166
171
  previous: () => facade.previous(),
167
172
  cancel: () => facade.cancel(),
168
173
  setData: (key, value) => facade.setData(key, value),
174
+ resetStep: () => facade.resetStep(),
169
175
  goToStep: (stepId) => facade.goToStep(stepId),
170
176
  goToStepChecked: (stepId) => facade.goToStepChecked(stepId),
171
- restart: (path, initialData = {}) => facade.restart(path, initialData),
177
+ restart: () => facade.restart(),
172
178
  };
173
179
  }
174
180
  /**
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/dist/shell.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { TemplateRef, EventEmitter, QueryList, OnInit, OnDestroy, Injector } from "@angular/core";
2
- import { PathData, PathDefinition, PathEvent, PathSnapshot, ProgressLayout } from "@daltonr/pathwrite-core";
1
+ import { TemplateRef, EventEmitter, QueryList, OnInit, OnChanges, OnDestroy, SimpleChanges, Injector } from "@angular/core";
2
+ import { PathData, PathDefinition, PathEngine, PathEvent, PathSnapshot, ProgressLayout } from "@daltonr/pathwrite-core";
3
3
  import { PathFacade } from "./index";
4
4
  import * as i0 from "@angular/core";
5
5
  /**
@@ -90,15 +90,30 @@ export declare class PathShellFooterDirective {
90
90
  * and navigation buttons.
91
91
  *
92
92
  * ```html
93
- * <pw-shell [path]="myPath" [initialData]="{ name: '' }" (completed)="onDone($event)">
93
+ * <pw-shell [path]="myPath" [initialData]="{ name: '' }" (complete)="onDone($event)">
94
94
  * <ng-template pwStep="details"><app-details-form /></ng-template>
95
95
  * <ng-template pwStep="review"><app-review-panel /></ng-template>
96
96
  * </pw-shell>
97
97
  * ```
98
98
  */
99
- export declare class PathShellComponent implements OnInit, OnDestroy {
100
- /** The path definition to run. Required. */
101
- path: PathDefinition<any>;
99
+ export declare class PathShellComponent implements OnInit, OnChanges, OnDestroy {
100
+ /** The path definition to run. Required unless [engine] is provided. */
101
+ path?: PathDefinition<any>;
102
+ /**
103
+ * An externally-managed `PathEngine` to adopt — for example, the engine
104
+ * returned by `restoreOrStart()` from `@daltonr/pathwrite-store`.
105
+ *
106
+ * When provided the shell skips `autoStart` and immediately reflects the
107
+ * engine's current state. Gate the shell's existence on the engine being
108
+ * ready using `@if (engine)` so the input is always non-null on mount:
109
+ *
110
+ * ```html
111
+ * @if (engine) {
112
+ * <pw-shell [engine]="engine" [path]="myPath" ...></pw-shell>
113
+ * }
114
+ * ```
115
+ */
116
+ engine?: PathEngine;
102
117
  /** Initial data merged into the path engine on start. */
103
118
  initialData: PathData;
104
119
  /** Start the path automatically on ngOnInit. Set to false to call doStart() manually. */
@@ -137,9 +152,9 @@ export declare class PathShellComponent implements OnInit, OnDestroy {
137
152
  * - "activeOnly": Only the active (sub-path) bar — root bar hidden.
138
153
  */
139
154
  progressLayout: ProgressLayout;
140
- completed: EventEmitter<PathData>;
141
- cancelled: EventEmitter<PathData>;
142
- pathEvent: EventEmitter<PathEvent>;
155
+ complete: EventEmitter<PathData>;
156
+ cancel: EventEmitter<PathData>;
157
+ event: EventEmitter<PathEvent>;
143
158
  stepDirectives: QueryList<PathStepDirective>;
144
159
  customHeader?: PathShellHeaderDirective;
145
160
  customFooter?: PathShellFooterDirective;
@@ -151,6 +166,7 @@ export declare class PathShellComponent implements OnInit, OnDestroy {
151
166
  /** Navigation actions passed to custom `pwShellFooter` templates. */
152
167
  protected readonly shellActions: PathShellActions;
153
168
  private readonly destroy$;
169
+ ngOnChanges(changes: SimpleChanges): void;
154
170
  ngOnInit(): void;
155
171
  ngOnDestroy(): void;
156
172
  doStart(): void;
@@ -164,13 +180,15 @@ export declare class PathShellComponent implements OnInit, OnDestroy {
164
180
  * ```
165
181
  */
166
182
  restart(): Promise<void>;
167
- /** Returns Object.entries(s.fieldMessages) for use in *ngFor. */
183
+ /** Returns Object.entries(s.fieldErrors) for use in *ngFor. */
168
184
  protected fieldEntries(s: PathSnapshot): [string, string][];
185
+ /** Returns Object.entries(s.fieldWarnings) for use in *ngFor. */
186
+ protected warningEntries(s: PathSnapshot): [string, string][];
169
187
  /** Resolves "auto" footerLayout based on snapshot. Single-step top-level → "form", otherwise → "wizard". */
170
188
  protected getResolvedFooterLayout(s: PathSnapshot): "wizard" | "form";
171
189
  /** Converts a camelCase or lowercase field key to a display label.
172
190
  * e.g. "firstName" → "First Name", "email" → "Email" */
173
191
  protected formatFieldKey(key: string): string;
174
192
  static ɵfac: i0.ɵɵFactoryDeclaration<PathShellComponent, never>;
175
- static ɵcmp: i0.ɵɵComponentDeclaration<PathShellComponent, "pw-shell", never, { "path": { "alias": "path"; "required": true; }; "initialData": { "alias": "initialData"; "required": false; }; "autoStart": { "alias": "autoStart"; "required": false; }; "backLabel": { "alias": "backLabel"; "required": false; }; "nextLabel": { "alias": "nextLabel"; "required": false; }; "completeLabel": { "alias": "completeLabel"; "required": false; }; "cancelLabel": { "alias": "cancelLabel"; "required": false; }; "hideCancel": { "alias": "hideCancel"; "required": false; }; "hideProgress": { "alias": "hideProgress"; "required": false; }; "footerLayout": { "alias": "footerLayout"; "required": false; }; "validationDisplay": { "alias": "validationDisplay"; "required": false; }; "progressLayout": { "alias": "progressLayout"; "required": false; }; }, { "completed": "completed"; "cancelled": "cancelled"; "pathEvent": "pathEvent"; }, ["customHeader", "customFooter", "stepDirectives"], never, true, never>;
193
+ static ɵcmp: i0.ɵɵComponentDeclaration<PathShellComponent, "pw-shell", never, { "path": { "alias": "path"; "required": false; }; "engine": { "alias": "engine"; "required": false; }; "initialData": { "alias": "initialData"; "required": false; }; "autoStart": { "alias": "autoStart"; "required": false; }; "backLabel": { "alias": "backLabel"; "required": false; }; "nextLabel": { "alias": "nextLabel"; "required": false; }; "completeLabel": { "alias": "completeLabel"; "required": false; }; "cancelLabel": { "alias": "cancelLabel"; "required": false; }; "hideCancel": { "alias": "hideCancel"; "required": false; }; "hideProgress": { "alias": "hideProgress"; "required": false; }; "footerLayout": { "alias": "footerLayout"; "required": false; }; "validationDisplay": { "alias": "validationDisplay"; "required": false; }; "progressLayout": { "alias": "progressLayout"; "required": false; }; }, { "complete": "complete"; "cancel": "cancel"; "event": "event"; }, ["customHeader", "customFooter", "stepDirectives"], never, true, never>;
176
194
  }
package/dist/shell.js CHANGED
@@ -97,7 +97,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
97
97
  * and navigation buttons.
98
98
  *
99
99
  * ```html
100
- * <pw-shell [path]="myPath" [initialData]="{ name: '' }" (completed)="onDone($event)">
100
+ * <pw-shell [path]="myPath" [initialData]="{ name: '' }" (complete)="onDone($event)">
101
101
  * <ng-template pwStep="details"><app-details-form /></ng-template>
102
102
  * <ng-template pwStep="review"><app-review-panel /></ng-template>
103
103
  * </pw-shell>
@@ -134,7 +134,7 @@ export class PathShellComponent {
134
134
  * - `"inline"`: Suppress the summary — handle errors inside the step template instead.
135
135
  * - `"both"`: Render the shell summary AND whatever the step template renders.
136
136
  */
137
- this.validationDisplay = "inline";
137
+ this.validationDisplay = "summary";
138
138
  /**
139
139
  * Controls how progress bars are arranged when a sub-path is active.
140
140
  * - "merged" (default): Root and sub-path bars in one card.
@@ -143,9 +143,9 @@ export class PathShellComponent {
143
143
  * - "activeOnly": Only the active (sub-path) bar — root bar hidden.
144
144
  */
145
145
  this.progressLayout = "merged";
146
- this.completed = new EventEmitter();
147
- this.cancelled = new EventEmitter();
148
- this.pathEvent = new EventEmitter();
146
+ this.complete = new EventEmitter();
147
+ this.cancel = new EventEmitter();
148
+ this.event = new EventEmitter();
149
149
  this.facade = inject(PathFacade);
150
150
  /** The shell's own component-level injector. Passed to ngTemplateOutlet so that
151
151
  * step components can resolve PathFacade (provided by this shell) via inject(). */
@@ -159,19 +159,24 @@ export class PathShellComponent {
159
159
  goToStep: (id) => this.facade.goToStep(id),
160
160
  goToStepChecked: (id) => this.facade.goToStepChecked(id),
161
161
  setData: (key, value) => this.facade.setData(key, value),
162
- restart: () => this.facade.restart(this.path, this.initialData),
162
+ restart: () => this.facade.restart(),
163
163
  };
164
164
  this.destroy$ = new Subject();
165
165
  }
166
+ ngOnChanges(changes) {
167
+ if (changes['engine'] && this.engine) {
168
+ this.facade.adoptEngine(this.engine);
169
+ }
170
+ }
166
171
  ngOnInit() {
167
172
  this.facade.events$.pipe(takeUntil(this.destroy$)).subscribe((event) => {
168
- this.pathEvent.emit(event);
173
+ this.event.emit(event);
169
174
  if (event.type === "completed")
170
- this.completed.emit(event.data);
175
+ this.complete.emit(event.data);
171
176
  if (event.type === "cancelled")
172
- this.cancelled.emit(event.data);
177
+ this.cancel.emit(event.data);
173
178
  });
174
- if (this.autoStart) {
179
+ if (this.autoStart && !this.engine) {
175
180
  this.doStart();
176
181
  }
177
182
  }
@@ -180,6 +185,8 @@ export class PathShellComponent {
180
185
  this.destroy$.complete();
181
186
  }
182
187
  doStart() {
188
+ if (!this.path)
189
+ throw new Error('[pw-shell] [path] is required when no [engine] is provided');
183
190
  this.started = true;
184
191
  this.facade.start(this.path, this.initialData);
185
192
  }
@@ -193,11 +200,15 @@ export class PathShellComponent {
193
200
  * ```
194
201
  */
195
202
  restart() {
196
- return this.facade.restart(this.path, this.initialData);
203
+ return this.facade.restart();
197
204
  }
198
- /** Returns Object.entries(s.fieldMessages) for use in *ngFor. */
205
+ /** Returns Object.entries(s.fieldErrors) for use in *ngFor. */
199
206
  fieldEntries(s) {
200
- return Object.entries(s.fieldMessages);
207
+ return Object.entries(s.fieldErrors);
208
+ }
209
+ /** Returns Object.entries(s.fieldWarnings) for use in *ngFor. */
210
+ warningEntries(s) {
211
+ return Object.entries(s.fieldWarnings);
201
212
  }
202
213
  /** Resolves "auto" footerLayout based on snapshot. Single-step top-level → "form", otherwise → "wizard". */
203
214
  getResolvedFooterLayout(s) {
@@ -211,7 +222,7 @@ export class PathShellComponent {
211
222
  return key.replace(/([A-Z])/g, " $1").replace(/^./, c => c.toUpperCase()).trim();
212
223
  }
213
224
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PathShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
214
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PathShellComponent, isStandalone: true, selector: "pw-shell", inputs: { path: "path", initialData: "initialData", autoStart: "autoStart", backLabel: "backLabel", nextLabel: "nextLabel", completeLabel: "completeLabel", cancelLabel: "cancelLabel", hideCancel: "hideCancel", hideProgress: "hideProgress", footerLayout: "footerLayout", validationDisplay: "validationDisplay", progressLayout: "progressLayout" }, outputs: { completed: "completed", cancelled: "cancelled", pathEvent: "pathEvent" }, providers: [PathFacade], queries: [{ propertyName: "customHeader", first: true, predicate: PathShellHeaderDirective, descendants: true }, { propertyName: "customFooter", first: true, predicate: PathShellFooterDirective, descendants: true }, { propertyName: "stepDirectives", predicate: PathStepDirective }], ngImport: i0, template: `
225
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PathShellComponent, isStandalone: true, selector: "pw-shell", inputs: { path: "path", engine: "engine", initialData: "initialData", autoStart: "autoStart", backLabel: "backLabel", nextLabel: "nextLabel", completeLabel: "completeLabel", cancelLabel: "cancelLabel", hideCancel: "hideCancel", hideProgress: "hideProgress", footerLayout: "footerLayout", validationDisplay: "validationDisplay", progressLayout: "progressLayout" }, outputs: { complete: "complete", cancel: "cancel", event: "event" }, providers: [PathFacade], queries: [{ propertyName: "customHeader", first: true, predicate: PathShellHeaderDirective, descendants: true }, { propertyName: "customFooter", first: true, predicate: PathShellFooterDirective, descendants: true }, { propertyName: "stepDirectives", predicate: PathStepDirective }], usesOnChanges: true, ngImport: i0, template: `
215
226
  <!-- Empty state -->
216
227
  <div class="pw-shell" *ngIf="!(facade.state$ | async)">
217
228
  <div class="pw-shell__empty" *ngIf="!started">
@@ -264,7 +275,8 @@ export class PathShellComponent {
264
275
  <!-- Body — step content -->
265
276
  <div class="pw-shell__body">
266
277
  <ng-container *ngFor="let stepDir of stepDirectives">
267
- <ng-container *ngIf="stepDir.stepId === s.stepId">
278
+ <!-- Match by formId first (inner step of a StepChoice), then stepId -->
279
+ <ng-container *ngIf="stepDir.stepId === (s.formId ?? s.stepId)">
268
280
  <ng-container *ngTemplateOutlet="stepDir.templateRef; injector: shellInjector"></ng-container>
269
281
  </ng-container>
270
282
  </ng-container>
@@ -277,6 +289,13 @@ export class PathShellComponent {
277
289
  </li>
278
290
  </ul>
279
291
 
292
+ <!-- Warning messages — non-blocking, shown immediately (no hasAttemptedNext gate) -->
293
+ <ul class="pw-shell__warnings" *ngIf="validationDisplay !== 'inline' && warningEntries(s).length > 0">
294
+ <li *ngFor="let entry of warningEntries(s)" class="pw-shell__warnings-item">
295
+ <span *ngIf="entry[0] !== '_'" class="pw-shell__warnings-label">{{ formatFieldKey(entry[0]) }}</span>{{ entry[1] }}
296
+ </li>
297
+ </ul>
298
+
280
299
  <!-- Footer — custom or default navigation buttons -->
281
300
  <ng-container *ngIf="customFooter; else defaultFooter">
282
301
  <ng-container *ngTemplateOutlet="customFooter.templateRef; context: { $implicit: s, actions: shellActions }"></ng-container>
@@ -384,7 +403,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
384
403
  <!-- Body — step content -->
385
404
  <div class="pw-shell__body">
386
405
  <ng-container *ngFor="let stepDir of stepDirectives">
387
- <ng-container *ngIf="stepDir.stepId === s.stepId">
406
+ <!-- Match by formId first (inner step of a StepChoice), then stepId -->
407
+ <ng-container *ngIf="stepDir.stepId === (s.formId ?? s.stepId)">
388
408
  <ng-container *ngTemplateOutlet="stepDir.templateRef; injector: shellInjector"></ng-container>
389
409
  </ng-container>
390
410
  </ng-container>
@@ -397,6 +417,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
397
417
  </li>
398
418
  </ul>
399
419
 
420
+ <!-- Warning messages — non-blocking, shown immediately (no hasAttemptedNext gate) -->
421
+ <ul class="pw-shell__warnings" *ngIf="validationDisplay !== 'inline' && warningEntries(s).length > 0">
422
+ <li *ngFor="let entry of warningEntries(s)" class="pw-shell__warnings-item">
423
+ <span *ngIf="entry[0] !== '_'" class="pw-shell__warnings-label">{{ formatFieldKey(entry[0]) }}</span>{{ entry[1] }}
424
+ </li>
425
+ </ul>
426
+
400
427
  <!-- Footer — custom or default navigation buttons -->
401
428
  <ng-container *ngIf="customFooter; else defaultFooter">
402
429
  <ng-container *ngTemplateOutlet="customFooter.templateRef; context: { $implicit: s, actions: shellActions }"></ng-container>
@@ -444,8 +471,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
444
471
  `
445
472
  }]
446
473
  }], propDecorators: { path: [{
447
- type: Input,
448
- args: [{ required: true }]
474
+ type: Input
475
+ }], engine: [{
476
+ type: Input
449
477
  }], initialData: [{
450
478
  type: Input
451
479
  }], autoStart: [{
@@ -468,11 +496,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
468
496
  type: Input
469
497
  }], progressLayout: [{
470
498
  type: Input
471
- }], completed: [{
499
+ }], complete: [{
472
500
  type: Output
473
- }], cancelled: [{
501
+ }], cancel: [{
474
502
  type: Output
475
- }], pathEvent: [{
503
+ }], event: [{
476
504
  type: Output
477
505
  }], stepDirectives: [{
478
506
  type: ContentChildren,
package/dist/shell.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,SAAS,EAET,KAAK,EACL,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,eAAe,EAMf,MAAM,EACN,QAAQ,EACR,uBAAuB,EACxB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAU3C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;;;AAsBrC,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;;;;;;GAUG;AAEH,MAAM,OAAO,iBAAiB;IAE5B,YAAmC,WAAiC;QAAjC,gBAAW,GAAX,WAAW,CAAsB;IAAG,CAAC;+GAF7D,iBAAiB;mGAAjB,iBAAiB;;4FAAjB,iBAAiB;kBAD7B,SAAS;mBAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE;gFAEP,MAAM;sBAAjD,KAAK;uBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE;;AAI5C,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E;;;;;;;;;;;;GAYG;AAEH,MAAM,OAAO,wBAAwB;IACnC,YACkB,WAAqD;QAArD,gBAAW,GAAX,WAAW,CAA0C;IACpE,CAAC;+GAHO,wBAAwB;mGAAxB,wBAAwB;;4FAAxB,wBAAwB;kBADpC,SAAS;mBAAC,EAAE,QAAQ,EAAE,iBAAiB,EAAE,UAAU,EAAE,IAAI,EAAE;;AAO5D,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E;;;;;;;;;;;;;;GAcG;AAEH,MAAM,OAAO,wBAAwB;IACnC,YACkB,WAAgF;QAAhF,gBAAW,GAAX,WAAW,CAAqE;IAC/F,CAAC;+GAHO,wBAAwB;mGAAxB,wBAAwB;;4FAAxB,wBAAwB;kBADpC,SAAS;mBAAC,EAAE,QAAQ,EAAE,iBAAiB,EAAE,UAAU,EAAE,IAAI,EAAE;;AAO5D,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;;;;;GAUG;AA+HH,MAAM,OAAO,kBAAkB;IA9H/B;QAgJE,yDAAyD;QAChD,gBAAW,GAAa,EAAE,CAAC;QACpC,yFAAyF;QAChF,cAAS,GAAG,IAAI,CAAC;QAC1B,4CAA4C;QACnC,cAAS,GAAG,UAAU,CAAC;QAChC,4CAA4C;QACnC,cAAS,GAAG,MAAM,CAAC;QAC5B,uDAAuD;QAC9C,kBAAa,GAAG,UAAU,CAAC;QACpC,mCAAmC;QAC1B,gBAAW,GAAG,QAAQ,CAAC;QAChC,uCAAuC;QAC9B,eAAU,GAAG,KAAK,CAAC;QAC5B,iHAAiH;QACxG,iBAAY,GAAG,KAAK,CAAC;QAC9B;;;;;WAKG;QACM,iBAAY,GAA+B,MAAM,CAAC;QAC3D;;;;;WAKG;QACM,sBAAiB,GAAkC,SAAS,CAAC;QACtE;;;;;;WAMG;QACM,mBAAc,GAAmB,QAAQ,CAAC;QAEzC,aAAQ,GAAG,IAAI,YAAY,EAAY,CAAC;QACxC,WAAM,GAAG,IAAI,YAAY,EAAY,CAAC;QACtC,UAAK,GAAG,IAAI,YAAY,EAAa,CAAC;QAMhC,WAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5C;4FACoF;QACjE,kBAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7C,YAAO,GAAG,KAAK,CAAC;QAEvB,qEAAqE;QAClD,iBAAY,GAAqB;YAClD,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;YAC9B,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;YACtC,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YAClC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1C,eAAe,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC;YACxD,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,KAAc,CAAC;YACjE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;SACrC,CAAC;QAEe,aAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;KAkEjD;IAhEQ,WAAW,CAAC,OAAsB;QACvC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAEM,QAAQ;QACb,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;YACrE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvB,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gBAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC/D,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gBAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAEM,WAAW;QAChB,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IAEM,OAAO;QACZ,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC9F,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACjD,CAAC;IAED;;;;;;;;OAQG;IACI,OAAO;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IAC/B,CAAC;IAED,+DAA+D;IACrD,YAAY,CAAC,CAAe;QACpC,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAuB,CAAC;IAC7D,CAAC;IAED,iEAAiE;IACvD,cAAc,CAAC,CAAe;QACtC,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAuB,CAAC;IAC/D,CAAC;IAED,4GAA4G;IAClG,uBAAuB,CAAC,CAAe;QAC/C,OAAO,IAAI,CAAC,YAAY,KAAK,MAAM;YACjC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;YACjE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;IACxB,CAAC;IAED;6DACyD;IAC/C,cAAc,CAAC,GAAW;QAClC,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACnF,CAAC;+GAnJU,kBAAkB;mGAAlB,kBAAkB,weA1HlB,CAAC,UAAU,CAAC,oEAwLT,wBAAwB,+EACxB,wBAAwB,oEAFrB,iBAAiB,kDArLxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsHT,2DAzHS,YAAY;;4FA2HX,kBAAkB;kBA9H9B,SAAS;mBAAC;oBACT,QAAQ,EAAE,UAAU;oBACpB,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,YAAY,CAAC;oBACvB,SAAS,EAAE,CAAC,UAAU,CAAC;oBACvB,eAAe,EAAE,uBAAuB,CAAC,OAAO;oBAChD,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsHT;iBACF;8BAGU,IAAI;sBAAZ,KAAK;gBAeG,MAAM;sBAAd,KAAK;gBAEG,WAAW;sBAAnB,KAAK;gBAEG,SAAS;sBAAjB,KAAK;gBAEG,SAAS;sBAAjB,KAAK;gBAEG,SAAS;sBAAjB,KAAK;gBAEG,aAAa;sBAArB,KAAK;gBAEG,WAAW;sBAAnB,KAAK;gBAEG,UAAU;sBAAlB,KAAK;gBAEG,YAAY;sBAApB,KAAK;gBAOG,YAAY;sBAApB,KAAK;gBAOG,iBAAiB;sBAAzB,KAAK;gBAQG,cAAc;sBAAtB,KAAK;gBAEI,QAAQ;sBAAjB,MAAM;gBACG,MAAM;sBAAf,MAAM;gBACG,KAAK;sBAAd,MAAM;gBAE6B,cAAc;sBAAjD,eAAe;uBAAC,iBAAiB;gBACM,YAAY;sBAAnD,YAAY;uBAAC,wBAAwB;gBACE,YAAY;sBAAnD,YAAY;uBAAC,wBAAwB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daltonr/pathwrite-angular",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Angular adapter for @daltonr/pathwrite-core — RxJS observables, signal-friendly, with optional <pw-shell> default UI.",
@@ -61,7 +61,7 @@
61
61
  "@angular/compiler-cli": "^17.3.12"
62
62
  },
63
63
  "dependencies": {
64
- "@daltonr/pathwrite-core": "^0.7.0"
64
+ "@daltonr/pathwrite-core": "^0.9.0"
65
65
  },
66
66
  "publishConfig": {
67
67
  "access": "public"
package/src/index.ts CHANGED
@@ -41,7 +41,7 @@ export class PathFacade<TData extends PathData = PathData> implements OnDestroy
41
41
 
42
42
  /**
43
43
  * Adopt an externally-managed `PathEngine` — for example, the engine returned
44
- * by `restoreOrStart()` from `@daltonr/pathwrite-store-http`.
44
+ * by `restoreOrStart()` from `@daltonr/pathwrite-store`.
45
45
  *
46
46
  * The facade immediately reflects the engine's current state and forwards all
47
47
  * subsequent events. The **caller** is responsible for the engine's lifecycle
@@ -94,8 +94,8 @@ export class PathFacade<TData extends PathData = PathData> implements OnDestroy
94
94
  * Use for "Start over" / retry flows without destroying and re-creating the
95
95
  * component that provides this facade.
96
96
  */
97
- public restart(path: PathDefinition<any>, initialData: PathData = {}): Promise<void> {
98
- return this._engine.restart(path, initialData);
97
+ public restart(): Promise<void> {
98
+ return this._engine.restart();
99
99
  }
100
100
 
101
101
  public startSubPath(path: PathDefinition<any>, initialData: PathData = {}, meta?: Record<string, unknown>): Promise<void> {
@@ -118,6 +118,12 @@ export class PathFacade<TData extends PathData = PathData> implements OnDestroy
118
118
  return this._engine.setData(key, value as unknown);
119
119
  }
120
120
 
121
+ /** Reset the current step's data to what it was when the step was entered.
122
+ * Useful for "Clear" or "Reset" buttons that undo changes within a step. */
123
+ public resetStep(): Promise<void> {
124
+ return this._engine.resetStep();
125
+ }
126
+
121
127
  public goToStep(stepId: string): Promise<void> {
122
128
  return this._engine.goToStep(stepId);
123
129
  }
@@ -158,6 +164,8 @@ export interface InjectPathReturn<TData extends PathData = PathData> {
158
164
  cancel: () => Promise<void>;
159
165
  /** Update a single data field. */
160
166
  setData: <K extends string & keyof TData>(key: K, value: TData[K]) => Promise<void>;
167
+ /** Reset the current step's data to what it was when the step was entered. */
168
+ resetStep: () => Promise<void>;
161
169
  /** Jump to a step by ID without checking guards. */
162
170
  goToStep: (stepId: string) => Promise<void>;
163
171
  /** Jump to a step by ID, checking guards first. */
@@ -166,7 +174,7 @@ export interface InjectPathReturn<TData extends PathData = PathData> {
166
174
  * Tears down any active path and immediately starts the given path fresh.
167
175
  * Use for "Start over" / retry flows.
168
176
  */
169
- restart: (path: PathDefinition<any>, initialData?: PathData) => Promise<void>;
177
+ restart: () => Promise<void>;
170
178
  }
171
179
 
172
180
  /**
@@ -223,9 +231,10 @@ export function injectPath<TData extends PathData = PathData>(): InjectPathRetur
223
231
  previous: () => facade.previous(),
224
232
  cancel: () => facade.cancel(),
225
233
  setData: (key, value) => facade.setData(key, value),
234
+ resetStep: () => facade.resetStep(),
226
235
  goToStep: (stepId) => facade.goToStep(stepId),
227
236
  goToStepChecked: (stepId) => facade.goToStepChecked(stepId),
228
- restart: (path, initialData = {}) => facade.restart(path, initialData),
237
+ restart: () => facade.restart(),
229
238
  };
230
239
  }
231
240
 
package/src/shell.ts CHANGED
@@ -9,7 +9,9 @@ import {
9
9
  ContentChildren,
10
10
  QueryList,
11
11
  OnInit,
12
+ OnChanges,
12
13
  OnDestroy,
14
+ SimpleChanges,
13
15
  inject,
14
16
  Injector,
15
17
  ChangeDetectionStrategy
@@ -20,6 +22,7 @@ import { takeUntil } from "rxjs/operators";
20
22
  import {
21
23
  PathData,
22
24
  PathDefinition,
25
+ PathEngine,
23
26
  PathEvent,
24
27
  PathSnapshot,
25
28
  ProgressLayout,
@@ -127,7 +130,7 @@ export class PathShellFooterDirective {
127
130
  * and navigation buttons.
128
131
  *
129
132
  * ```html
130
- * <pw-shell [path]="myPath" [initialData]="{ name: '' }" (completed)="onDone($event)">
133
+ * <pw-shell [path]="myPath" [initialData]="{ name: '' }" (complete)="onDone($event)">
131
134
  * <ng-template pwStep="details"><app-details-form /></ng-template>
132
135
  * <ng-template pwStep="review"><app-review-panel /></ng-template>
133
136
  * </pw-shell>
@@ -192,7 +195,8 @@ export class PathShellFooterDirective {
192
195
  <!-- Body — step content -->
193
196
  <div class="pw-shell__body">
194
197
  <ng-container *ngFor="let stepDir of stepDirectives">
195
- <ng-container *ngIf="stepDir.stepId === s.stepId">
198
+ <!-- Match by formId first (inner step of a StepChoice), then stepId -->
199
+ <ng-container *ngIf="stepDir.stepId === (s.formId ?? s.stepId)">
196
200
  <ng-container *ngTemplateOutlet="stepDir.templateRef; injector: shellInjector"></ng-container>
197
201
  </ng-container>
198
202
  </ng-container>
@@ -205,6 +209,13 @@ export class PathShellFooterDirective {
205
209
  </li>
206
210
  </ul>
207
211
 
212
+ <!-- Warning messages — non-blocking, shown immediately (no hasAttemptedNext gate) -->
213
+ <ul class="pw-shell__warnings" *ngIf="validationDisplay !== 'inline' && warningEntries(s).length > 0">
214
+ <li *ngFor="let entry of warningEntries(s)" class="pw-shell__warnings-item">
215
+ <span *ngIf="entry[0] !== '_'" class="pw-shell__warnings-label">{{ formatFieldKey(entry[0]) }}</span>{{ entry[1] }}
216
+ </li>
217
+ </ul>
218
+
208
219
  <!-- Footer — custom or default navigation buttons -->
209
220
  <ng-container *ngIf="customFooter; else defaultFooter">
210
221
  <ng-container *ngTemplateOutlet="customFooter.templateRef; context: { $implicit: s, actions: shellActions }"></ng-container>
@@ -251,9 +262,24 @@ export class PathShellFooterDirective {
251
262
  </div>
252
263
  `
253
264
  })
254
- export class PathShellComponent implements OnInit, OnDestroy {
255
- /** The path definition to run. Required. */
256
- @Input({ required: true }) path!: PathDefinition<any>;
265
+ export class PathShellComponent implements OnInit, OnChanges, OnDestroy {
266
+ /** The path definition to run. Required unless [engine] is provided. */
267
+ @Input() path?: PathDefinition<any>;
268
+ /**
269
+ * An externally-managed `PathEngine` to adopt — for example, the engine
270
+ * returned by `restoreOrStart()` from `@daltonr/pathwrite-store`.
271
+ *
272
+ * When provided the shell skips `autoStart` and immediately reflects the
273
+ * engine's current state. Gate the shell's existence on the engine being
274
+ * ready using `@if (engine)` so the input is always non-null on mount:
275
+ *
276
+ * ```html
277
+ * @if (engine) {
278
+ * <pw-shell [engine]="engine" [path]="myPath" ...></pw-shell>
279
+ * }
280
+ * ```
281
+ */
282
+ @Input() engine?: PathEngine;
257
283
  /** Initial data merged into the path engine on start. */
258
284
  @Input() initialData: PathData = {};
259
285
  /** Start the path automatically on ngOnInit. Set to false to call doStart() manually. */
@@ -283,7 +309,7 @@ export class PathShellComponent implements OnInit, OnDestroy {
283
309
  * - `"inline"`: Suppress the summary — handle errors inside the step template instead.
284
310
  * - `"both"`: Render the shell summary AND whatever the step template renders.
285
311
  */
286
- @Input() validationDisplay: "summary" | "inline" | "both" = "inline";
312
+ @Input() validationDisplay: "summary" | "inline" | "both" = "summary";
287
313
  /**
288
314
  * Controls how progress bars are arranged when a sub-path is active.
289
315
  * - "merged" (default): Root and sub-path bars in one card.
@@ -293,9 +319,9 @@ export class PathShellComponent implements OnInit, OnDestroy {
293
319
  */
294
320
  @Input() progressLayout: ProgressLayout = "merged";
295
321
 
296
- @Output() completed = new EventEmitter<PathData>();
297
- @Output() cancelled = new EventEmitter<PathData>();
298
- @Output() pathEvent = new EventEmitter<PathEvent>();
322
+ @Output() complete = new EventEmitter<PathData>();
323
+ @Output() cancel = new EventEmitter<PathData>();
324
+ @Output() event = new EventEmitter<PathEvent>();
299
325
 
300
326
  @ContentChildren(PathStepDirective) stepDirectives!: QueryList<PathStepDirective>;
301
327
  @ContentChild(PathShellHeaderDirective) customHeader?: PathShellHeaderDirective;
@@ -315,19 +341,25 @@ export class PathShellComponent implements OnInit, OnDestroy {
315
341
  goToStep: (id) => this.facade.goToStep(id),
316
342
  goToStepChecked: (id) => this.facade.goToStepChecked(id),
317
343
  setData: (key, value) => this.facade.setData(key, value as never),
318
- restart: () => this.facade.restart(this.path, this.initialData),
344
+ restart: () => this.facade.restart(),
319
345
  };
320
346
 
321
347
  private readonly destroy$ = new Subject<void>();
322
348
 
349
+ public ngOnChanges(changes: SimpleChanges): void {
350
+ if (changes['engine'] && this.engine) {
351
+ this.facade.adoptEngine(this.engine);
352
+ }
353
+ }
354
+
323
355
  public ngOnInit(): void {
324
356
  this.facade.events$.pipe(takeUntil(this.destroy$)).subscribe((event) => {
325
- this.pathEvent.emit(event);
326
- if (event.type === "completed") this.completed.emit(event.data);
327
- if (event.type === "cancelled") this.cancelled.emit(event.data);
357
+ this.event.emit(event);
358
+ if (event.type === "completed") this.complete.emit(event.data);
359
+ if (event.type === "cancelled") this.cancel.emit(event.data);
328
360
  });
329
361
 
330
- if (this.autoStart) {
362
+ if (this.autoStart && !this.engine) {
331
363
  this.doStart();
332
364
  }
333
365
  }
@@ -338,6 +370,7 @@ export class PathShellComponent implements OnInit, OnDestroy {
338
370
  }
339
371
 
340
372
  public doStart(): void {
373
+ if (!this.path) throw new Error('[pw-shell] [path] is required when no [engine] is provided');
341
374
  this.started = true;
342
375
  this.facade.start(this.path, this.initialData);
343
376
  }
@@ -352,12 +385,17 @@ export class PathShellComponent implements OnInit, OnDestroy {
352
385
  * ```
353
386
  */
354
387
  public restart(): Promise<void> {
355
- return this.facade.restart(this.path, this.initialData);
388
+ return this.facade.restart();
356
389
  }
357
390
 
358
- /** Returns Object.entries(s.fieldMessages) for use in *ngFor. */
391
+ /** Returns Object.entries(s.fieldErrors) for use in *ngFor. */
359
392
  protected fieldEntries(s: PathSnapshot): [string, string][] {
360
- return Object.entries(s.fieldMessages) as [string, string][];
393
+ return Object.entries(s.fieldErrors) as [string, string][];
394
+ }
395
+
396
+ /** Returns Object.entries(s.fieldWarnings) for use in *ngFor. */
397
+ protected warningEntries(s: PathSnapshot): [string, string][] {
398
+ return Object.entries(s.fieldWarnings) as [string, string][];
361
399
  }
362
400
 
363
401
  /** Resolves "auto" footerLayout based on snapshot. Single-step top-level → "form", otherwise → "wizard". */