@daltonr/pathwrite-angular 0.2.0 → 0.3.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 +53 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/shell.d.ts +70 -3
- package/dist/shell.js +173 -82
- package/dist/shell.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +3 -3
- package/src/shell.ts +134 -44
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ export class MyComponent {
|
|
|
41
41
|
| Method | Description |
|
|
42
42
|
|--------|-------------|
|
|
43
43
|
| `start(definition, data?)` | Start or re-start a path. |
|
|
44
|
-
| `startSubPath(definition, data?)` | Push a sub-path. Requires an active path. |
|
|
44
|
+
| `startSubPath(definition, data?, meta?)` | Push a sub-path. Requires an active path. `meta` is returned unchanged to `onSubPathComplete` / `onSubPathCancel`. |
|
|
45
45
|
| `next()` | Advance one step. Completes the path on the last step. |
|
|
46
46
|
| `previous()` | Go back one step. No-op when already on the first step of a top-level path. |
|
|
47
47
|
| `cancel()` | Cancel the active path (or sub-path). |
|
|
@@ -199,7 +199,12 @@ The Angular adapter ships an optional shell component that renders a complete pr
|
|
|
199
199
|
The shell lives in a separate entry point so that headless-only usage does not pull in the Angular compiler:
|
|
200
200
|
|
|
201
201
|
```typescript
|
|
202
|
-
import {
|
|
202
|
+
import {
|
|
203
|
+
PathShellComponent,
|
|
204
|
+
PathStepDirective,
|
|
205
|
+
PathShellHeaderDirective,
|
|
206
|
+
PathShellFooterDirective,
|
|
207
|
+
} from "@daltonr/pathwrite-angular/shell";
|
|
203
208
|
```
|
|
204
209
|
|
|
205
210
|
### Usage
|
|
@@ -283,6 +288,52 @@ export class MyComponent {
|
|
|
283
288
|
| `(cancelled)` | `PathData` | Emitted when the path is cancelled. |
|
|
284
289
|
| `(pathEvent)` | `PathEvent` | Emitted for every engine event. |
|
|
285
290
|
|
|
291
|
+
### Customising the header and footer
|
|
292
|
+
|
|
293
|
+
Use `pwShellHeader` and `pwShellFooter` directives to replace the built-in progress bar or navigation buttons with your own templates. Both are declared on `<ng-template>` elements inside the shell.
|
|
294
|
+
|
|
295
|
+
**`pwShellHeader`** — receives the current `PathSnapshot` as the implicit template variable:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
@Component({
|
|
299
|
+
imports: [PathShellComponent, PathStepDirective, PathShellHeaderDirective],
|
|
300
|
+
template: `
|
|
301
|
+
<pw-shell [path]="myPath">
|
|
302
|
+
<ng-template pwShellHeader let-s>
|
|
303
|
+
<p>Step {{ s.stepIndex + 1 }} of {{ s.stepCount }} — {{ s.stepTitle }}</p>
|
|
304
|
+
</ng-template>
|
|
305
|
+
<ng-template pwStep="details"><app-details-form /></ng-template>
|
|
306
|
+
<ng-template pwStep="review"><app-review-panel /></ng-template>
|
|
307
|
+
</pw-shell>
|
|
308
|
+
`
|
|
309
|
+
})
|
|
310
|
+
export class MyComponent { ... }
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**`pwShellFooter`** — receives the snapshot as the implicit variable and an `actions` variable with all navigation callbacks:
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
@Component({
|
|
317
|
+
imports: [PathShellComponent, PathStepDirective, PathShellFooterDirective],
|
|
318
|
+
template: `
|
|
319
|
+
<pw-shell [path]="myPath">
|
|
320
|
+
<ng-template pwShellFooter let-s let-actions="actions">
|
|
321
|
+
<button (click)="actions.previous()" [disabled]="s.isFirstStep || s.isNavigating">Back</button>
|
|
322
|
+
<button (click)="actions.next()" [disabled]="!s.canMoveNext || s.isNavigating">
|
|
323
|
+
{{ s.isLastStep ? 'Finish' : 'Next' }}
|
|
324
|
+
</button>
|
|
325
|
+
</ng-template>
|
|
326
|
+
<ng-template pwStep="details"><app-details-form /></ng-template>
|
|
327
|
+
</pw-shell>
|
|
328
|
+
`
|
|
329
|
+
})
|
|
330
|
+
export class MyComponent { ... }
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
`actions` (`PathShellActions`) contains: `next`, `previous`, `cancel`, `goToStep`, `goToStepChecked`, `setData`. All return `Promise<void>`.
|
|
334
|
+
|
|
335
|
+
Both directives can be combined. Only the sections you override are replaced — a custom header still shows the default footer, and vice versa.
|
|
336
|
+
|
|
286
337
|
---
|
|
287
338
|
|
|
288
339
|
## Styling
|
package/dist/index.d.ts
CHANGED
|
@@ -28,8 +28,8 @@ export declare class PathFacade<TData extends PathData = PathData> implements On
|
|
|
28
28
|
readonly stateSignal: Signal<PathSnapshot<TData> | null>;
|
|
29
29
|
constructor();
|
|
30
30
|
ngOnDestroy(): void;
|
|
31
|
-
start(path: PathDefinition
|
|
32
|
-
startSubPath(path: PathDefinition
|
|
31
|
+
start(path: PathDefinition<any>, initialData?: PathData): Promise<void>;
|
|
32
|
+
startSubPath(path: PathDefinition<any>, initialData?: PathData, meta?: Record<string, unknown>): Promise<void>;
|
|
33
33
|
next(): Promise<void>;
|
|
34
34
|
previous(): Promise<void>;
|
|
35
35
|
cancel(): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -46,8 +46,8 @@ export class PathFacade {
|
|
|
46
46
|
start(path, initialData = {}) {
|
|
47
47
|
return this.engine.start(path, initialData);
|
|
48
48
|
}
|
|
49
|
-
startSubPath(path, initialData = {}) {
|
|
50
|
-
return this.engine.startSubPath(path, initialData);
|
|
49
|
+
startSubPath(path, initialData = {}, meta) {
|
|
50
|
+
return this.engine.startSubPath(path, initialData, meta);
|
|
51
51
|
}
|
|
52
52
|
next() {
|
|
53
53
|
return this.engine.next();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAyB,MAAM,EAAU,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,eAAe,EAAc,OAAO,EAAE,MAAM,MAAM,CAAC;AAC5D,OAAO,EAGL,UAAU,EAGX,MAAM,yBAAyB,CAAC;;AAEjC;;;;;;;;;;;;;GAaG;AAEH,MAAM,OAAO,UAAU;IAYrB;QAXiB,WAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC1B,YAAO,GAAG,IAAI,eAAe,CAA6B,IAAI,CAAC,CAAC;QAChE,aAAQ,GAAG,IAAI,OAAO,EAAa,CAAC;QAEpC,iBAAY,GAAG,MAAM,CAA6B,IAAI,CAAC,CAAC;QAEzD,WAAM,GAA2C,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QAC7E,YAAO,GAA0B,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;QAC9E,0FAA0F;QAC1E,gBAAW,GAAuC,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;QAG/F,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;YAC3D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC9D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,QAA+B,CAAC,CAAC;gBACzD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,QAA+B,CAAC,CAAC;YAC/D,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACpE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,WAAW;QAChB,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC7B,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAEM,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/shell.d.ts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import { TemplateRef, EventEmitter, QueryList, OnInit, OnDestroy, Injector } from "@angular/core";
|
|
2
|
-
import { PathData, PathDefinition, PathEvent } from "@daltonr/pathwrite-core";
|
|
2
|
+
import { PathData, PathDefinition, PathEvent, PathSnapshot } from "@daltonr/pathwrite-core";
|
|
3
3
|
import { PathFacade } from "./index";
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* Navigation actions passed as template context to custom `pwShellFooter`
|
|
7
|
+
* templates. Mirrors what React's `renderFooter` and Vue's `#footer` slot
|
|
8
|
+
* receive, using promises so it is consistent with the Angular facade.
|
|
9
|
+
*/
|
|
10
|
+
export interface PathShellActions {
|
|
11
|
+
next: () => Promise<void>;
|
|
12
|
+
previous: () => Promise<void>;
|
|
13
|
+
cancel: () => Promise<void>;
|
|
14
|
+
goToStep: (stepId: string) => Promise<void>;
|
|
15
|
+
goToStepChecked: (stepId: string) => Promise<void>;
|
|
16
|
+
setData: (key: string, value: unknown) => Promise<void>;
|
|
17
|
+
}
|
|
5
18
|
/**
|
|
6
19
|
* Structural directive that associates a template with a step ID.
|
|
7
20
|
* Used inside `<pw-shell>` to define per-step content.
|
|
@@ -20,6 +33,56 @@ export declare class PathStepDirective {
|
|
|
20
33
|
static ɵfac: i0.ɵɵFactoryDeclaration<PathStepDirective, never>;
|
|
21
34
|
static ɵdir: i0.ɵɵDirectiveDeclaration<PathStepDirective, "[pwStep]", never, { "stepId": { "alias": "pwStep"; "required": true; }; }, {}, never, never, true, never>;
|
|
22
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Replaces the default progress header inside `<pw-shell>`.
|
|
38
|
+
* The template receives the current `PathSnapshot` as the implicit context.
|
|
39
|
+
*
|
|
40
|
+
* ```html
|
|
41
|
+
* <pw-shell [path]="myPath">
|
|
42
|
+
* <ng-template pwShellHeader let-s>
|
|
43
|
+
* <my-custom-progress [snapshot]="s" />
|
|
44
|
+
* </ng-template>
|
|
45
|
+
* <ng-template pwStep="details"><app-details-form /></ng-template>
|
|
46
|
+
* </pw-shell>
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare class PathShellHeaderDirective {
|
|
50
|
+
readonly templateRef: TemplateRef<{
|
|
51
|
+
$implicit: PathSnapshot;
|
|
52
|
+
}>;
|
|
53
|
+
constructor(templateRef: TemplateRef<{
|
|
54
|
+
$implicit: PathSnapshot;
|
|
55
|
+
}>);
|
|
56
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PathShellHeaderDirective, never>;
|
|
57
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<PathShellHeaderDirective, "[pwShellHeader]", never, {}, {}, never, never, true, never>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Replaces the default navigation footer inside `<pw-shell>`.
|
|
61
|
+
* The template receives the current `PathSnapshot` as the implicit context
|
|
62
|
+
* and a `actions` variable containing all navigation actions.
|
|
63
|
+
*
|
|
64
|
+
* ```html
|
|
65
|
+
* <pw-shell [path]="myPath">
|
|
66
|
+
* <ng-template pwShellFooter let-s let-actions="actions">
|
|
67
|
+
* <button (click)="actions.previous()" [disabled]="s.isFirstStep">Back</button>
|
|
68
|
+
* <button (click)="actions.next()" [disabled]="!s.canMoveNext">Next</button>
|
|
69
|
+
* </ng-template>
|
|
70
|
+
* <ng-template pwStep="details"><app-details-form /></ng-template>
|
|
71
|
+
* </pw-shell>
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare class PathShellFooterDirective {
|
|
75
|
+
readonly templateRef: TemplateRef<{
|
|
76
|
+
$implicit: PathSnapshot;
|
|
77
|
+
actions: PathShellActions;
|
|
78
|
+
}>;
|
|
79
|
+
constructor(templateRef: TemplateRef<{
|
|
80
|
+
$implicit: PathSnapshot;
|
|
81
|
+
actions: PathShellActions;
|
|
82
|
+
}>);
|
|
83
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PathShellFooterDirective, never>;
|
|
84
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<PathShellFooterDirective, "[pwShellFooter]", never, {}, {}, never, never, true, never>;
|
|
85
|
+
}
|
|
23
86
|
/**
|
|
24
87
|
* Default UI shell component. Renders a progress indicator, step content,
|
|
25
88
|
* and navigation buttons.
|
|
@@ -33,7 +96,7 @@ export declare class PathStepDirective {
|
|
|
33
96
|
*/
|
|
34
97
|
export declare class PathShellComponent implements OnInit, OnDestroy {
|
|
35
98
|
/** The path definition to run. Required. */
|
|
36
|
-
path: PathDefinition
|
|
99
|
+
path: PathDefinition<any>;
|
|
37
100
|
/** Initial data merged into the path engine on start. */
|
|
38
101
|
initialData: PathData;
|
|
39
102
|
/** Start the path automatically on ngOnInit. Set to false to call doStart() manually. */
|
|
@@ -54,15 +117,19 @@ export declare class PathShellComponent implements OnInit, OnDestroy {
|
|
|
54
117
|
cancelled: EventEmitter<PathData>;
|
|
55
118
|
pathEvent: EventEmitter<PathEvent>;
|
|
56
119
|
stepDirectives: QueryList<PathStepDirective>;
|
|
120
|
+
customHeader?: PathShellHeaderDirective;
|
|
121
|
+
customFooter?: PathShellFooterDirective;
|
|
57
122
|
readonly facade: PathFacade<PathData>;
|
|
58
123
|
/** The shell's own component-level injector. Passed to ngTemplateOutlet so that
|
|
59
124
|
* step components can resolve PathFacade (provided by this shell) via inject(). */
|
|
60
125
|
protected readonly shellInjector: Injector;
|
|
61
126
|
started: boolean;
|
|
127
|
+
/** Navigation actions passed to custom `pwShellFooter` templates. */
|
|
128
|
+
protected readonly shellActions: PathShellActions;
|
|
62
129
|
private readonly destroy$;
|
|
63
130
|
ngOnInit(): void;
|
|
64
131
|
ngOnDestroy(): void;
|
|
65
132
|
doStart(): void;
|
|
66
133
|
static ɵfac: i0.ɵɵFactoryDeclaration<PathShellComponent, never>;
|
|
67
|
-
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; }; "finishLabel": { "alias": "finishLabel"; "required": false; }; "cancelLabel": { "alias": "cancelLabel"; "required": false; }; "hideCancel": { "alias": "hideCancel"; "required": false; }; "hideProgress": { "alias": "hideProgress"; "required": false; }; }, { "completed": "completed"; "cancelled": "cancelled"; "pathEvent": "pathEvent"; }, ["stepDirectives"], never, true, never>;
|
|
134
|
+
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; }; "finishLabel": { "alias": "finishLabel"; "required": false; }; "cancelLabel": { "alias": "cancelLabel"; "required": false; }; "hideCancel": { "alias": "hideCancel"; "required": false; }; "hideProgress": { "alias": "hideProgress"; "required": false; }; }, { "completed": "completed"; "cancelled": "cancelled"; "pathEvent": "pathEvent"; }, ["customHeader", "customFooter", "stepDirectives"], never, true, never>;
|
|
68
135
|
}
|
package/dist/shell.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, Directive, Input, Output, EventEmitter, ContentChildren, inject, Injector, ChangeDetectionStrategy } from "@angular/core";
|
|
1
|
+
import { Component, Directive, Input, Output, EventEmitter, ContentChild, ContentChildren, inject, Injector, ChangeDetectionStrategy } from "@angular/core";
|
|
2
2
|
import { CommonModule } from "@angular/common";
|
|
3
3
|
import { Subject } from "rxjs";
|
|
4
4
|
import { takeUntil } from "rxjs/operators";
|
|
@@ -34,6 +34,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
34
34
|
args: [{ required: true, alias: "pwStep" }]
|
|
35
35
|
}] } });
|
|
36
36
|
// ---------------------------------------------------------------------------
|
|
37
|
+
// PathShellHeaderDirective
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
/**
|
|
40
|
+
* Replaces the default progress header inside `<pw-shell>`.
|
|
41
|
+
* The template receives the current `PathSnapshot` as the implicit context.
|
|
42
|
+
*
|
|
43
|
+
* ```html
|
|
44
|
+
* <pw-shell [path]="myPath">
|
|
45
|
+
* <ng-template pwShellHeader let-s>
|
|
46
|
+
* <my-custom-progress [snapshot]="s" />
|
|
47
|
+
* </ng-template>
|
|
48
|
+
* <ng-template pwStep="details"><app-details-form /></ng-template>
|
|
49
|
+
* </pw-shell>
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export class PathShellHeaderDirective {
|
|
53
|
+
constructor(templateRef) {
|
|
54
|
+
this.templateRef = templateRef;
|
|
55
|
+
}
|
|
56
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PathShellHeaderDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
57
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: PathShellHeaderDirective, isStandalone: true, selector: "[pwShellHeader]", ngImport: i0 }); }
|
|
58
|
+
}
|
|
59
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PathShellHeaderDirective, decorators: [{
|
|
60
|
+
type: Directive,
|
|
61
|
+
args: [{ selector: "[pwShellHeader]", standalone: true }]
|
|
62
|
+
}], ctorParameters: () => [{ type: i0.TemplateRef }] });
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
// PathShellFooterDirective
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
/**
|
|
67
|
+
* Replaces the default navigation footer inside `<pw-shell>`.
|
|
68
|
+
* The template receives the current `PathSnapshot` as the implicit context
|
|
69
|
+
* and a `actions` variable containing all navigation actions.
|
|
70
|
+
*
|
|
71
|
+
* ```html
|
|
72
|
+
* <pw-shell [path]="myPath">
|
|
73
|
+
* <ng-template pwShellFooter let-s let-actions="actions">
|
|
74
|
+
* <button (click)="actions.previous()" [disabled]="s.isFirstStep">Back</button>
|
|
75
|
+
* <button (click)="actions.next()" [disabled]="!s.canMoveNext">Next</button>
|
|
76
|
+
* </ng-template>
|
|
77
|
+
* <ng-template pwStep="details"><app-details-form /></ng-template>
|
|
78
|
+
* </pw-shell>
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export class PathShellFooterDirective {
|
|
82
|
+
constructor(templateRef) {
|
|
83
|
+
this.templateRef = templateRef;
|
|
84
|
+
}
|
|
85
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PathShellFooterDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
86
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: PathShellFooterDirective, isStandalone: true, selector: "[pwShellFooter]", ngImport: i0 }); }
|
|
87
|
+
}
|
|
88
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PathShellFooterDirective, decorators: [{
|
|
89
|
+
type: Directive,
|
|
90
|
+
args: [{ selector: "[pwShellFooter]", standalone: true }]
|
|
91
|
+
}], ctorParameters: () => [{ type: i0.TemplateRef }] });
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
37
93
|
// PathShellComponent
|
|
38
94
|
// ---------------------------------------------------------------------------
|
|
39
95
|
/**
|
|
@@ -73,6 +129,15 @@ export class PathShellComponent {
|
|
|
73
129
|
* step components can resolve PathFacade (provided by this shell) via inject(). */
|
|
74
130
|
this.shellInjector = inject(Injector);
|
|
75
131
|
this.started = false;
|
|
132
|
+
/** Navigation actions passed to custom `pwShellFooter` templates. */
|
|
133
|
+
this.shellActions = {
|
|
134
|
+
next: () => this.facade.next(),
|
|
135
|
+
previous: () => this.facade.previous(),
|
|
136
|
+
cancel: () => this.facade.cancel(),
|
|
137
|
+
goToStep: (id) => this.facade.goToStep(id),
|
|
138
|
+
goToStepChecked: (id) => this.facade.goToStepChecked(id),
|
|
139
|
+
setData: (key, value) => this.facade.setData(key, value),
|
|
140
|
+
};
|
|
76
141
|
this.destroy$ = new Subject();
|
|
77
142
|
}
|
|
78
143
|
ngOnInit() {
|
|
@@ -96,7 +161,7 @@ export class PathShellComponent {
|
|
|
96
161
|
this.facade.start(this.path, this.initialData);
|
|
97
162
|
}
|
|
98
163
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PathShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
99
|
-
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", finishLabel: "finishLabel", cancelLabel: "cancelLabel", hideCancel: "hideCancel", hideProgress: "hideProgress" }, outputs: { completed: "completed", cancelled: "cancelled", pathEvent: "pathEvent" }, providers: [PathFacade], queries: [{ propertyName: "stepDirectives", predicate: PathStepDirective }], ngImport: i0, template: `
|
|
164
|
+
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", finishLabel: "finishLabel", cancelLabel: "cancelLabel", hideCancel: "hideCancel", hideProgress: "hideProgress" }, 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: `
|
|
100
165
|
<!-- Empty state -->
|
|
101
166
|
<div class="pw-shell" *ngIf="!(facade.state$ | async)">
|
|
102
167
|
<div class="pw-shell__empty" *ngIf="!started">
|
|
@@ -107,22 +172,27 @@ export class PathShellComponent {
|
|
|
107
172
|
|
|
108
173
|
<!-- Active path -->
|
|
109
174
|
<div class="pw-shell" *ngIf="facade.state$ | async as s">
|
|
110
|
-
<!-- Header — progress indicator -->
|
|
111
|
-
<
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
175
|
+
<!-- Header — custom or default progress indicator -->
|
|
176
|
+
<ng-container *ngIf="customHeader; else defaultHeader">
|
|
177
|
+
<ng-container *ngTemplateOutlet="customHeader.templateRef; context: { $implicit: s }"></ng-container>
|
|
178
|
+
</ng-container>
|
|
179
|
+
<ng-template #defaultHeader>
|
|
180
|
+
<div class="pw-shell__header" *ngIf="!hideProgress">
|
|
181
|
+
<div class="pw-shell__steps">
|
|
182
|
+
<div
|
|
183
|
+
*ngFor="let step of s.steps; let i = index"
|
|
184
|
+
class="pw-shell__step"
|
|
185
|
+
[ngClass]="'pw-shell__step--' + step.status"
|
|
186
|
+
>
|
|
187
|
+
<span class="pw-shell__step-dot">{{ step.status === 'completed' ? '✓' : (i + 1) }}</span>
|
|
188
|
+
<span class="pw-shell__step-label">{{ step.title ?? step.id }}</span>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
<div class="pw-shell__track">
|
|
192
|
+
<div class="pw-shell__track-fill" [style.width.%]="s.progress * 100"></div>
|
|
120
193
|
</div>
|
|
121
194
|
</div>
|
|
122
|
-
|
|
123
|
-
<div class="pw-shell__track-fill" [style.width.%]="s.progress * 100"></div>
|
|
124
|
-
</div>
|
|
125
|
-
</div>
|
|
195
|
+
</ng-template>
|
|
126
196
|
|
|
127
197
|
<!-- Body — step content -->
|
|
128
198
|
<div class="pw-shell__body">
|
|
@@ -138,33 +208,38 @@ export class PathShellComponent {
|
|
|
138
208
|
<li *ngFor="let msg of s.validationMessages" class="pw-shell__validation-item">{{ msg }}</li>
|
|
139
209
|
</ul>
|
|
140
210
|
|
|
141
|
-
<!-- Footer — navigation buttons -->
|
|
142
|
-
<
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
211
|
+
<!-- Footer — custom or default navigation buttons -->
|
|
212
|
+
<ng-container *ngIf="customFooter; else defaultFooter">
|
|
213
|
+
<ng-container *ngTemplateOutlet="customFooter.templateRef; context: { $implicit: s, actions: shellActions }"></ng-container>
|
|
214
|
+
</ng-container>
|
|
215
|
+
<ng-template #defaultFooter>
|
|
216
|
+
<div class="pw-shell__footer">
|
|
217
|
+
<div class="pw-shell__footer-left">
|
|
218
|
+
<button
|
|
219
|
+
*ngIf="!s.isFirstStep"
|
|
220
|
+
type="button"
|
|
221
|
+
class="pw-shell__btn pw-shell__btn--back"
|
|
222
|
+
[disabled]="s.isNavigating || !s.canMovePrevious"
|
|
223
|
+
(click)="facade.previous()"
|
|
224
|
+
>{{ backLabel }}</button>
|
|
225
|
+
</div>
|
|
226
|
+
<div class="pw-shell__footer-right">
|
|
227
|
+
<button
|
|
228
|
+
*ngIf="!hideCancel"
|
|
229
|
+
type="button"
|
|
230
|
+
class="pw-shell__btn pw-shell__btn--cancel"
|
|
231
|
+
[disabled]="s.isNavigating"
|
|
232
|
+
(click)="facade.cancel()"
|
|
233
|
+
>{{ cancelLabel }}</button>
|
|
234
|
+
<button
|
|
235
|
+
type="button"
|
|
236
|
+
class="pw-shell__btn pw-shell__btn--next"
|
|
237
|
+
[disabled]="s.isNavigating || !s.canMoveNext"
|
|
238
|
+
(click)="facade.next()"
|
|
239
|
+
>{{ s.isLastStep ? finishLabel : nextLabel }}</button>
|
|
240
|
+
</div>
|
|
166
241
|
</div>
|
|
167
|
-
</
|
|
242
|
+
</ng-template>
|
|
168
243
|
</div>
|
|
169
244
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.Default }); }
|
|
170
245
|
}
|
|
@@ -187,22 +262,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
187
262
|
|
|
188
263
|
<!-- Active path -->
|
|
189
264
|
<div class="pw-shell" *ngIf="facade.state$ | async as s">
|
|
190
|
-
<!-- Header — progress indicator -->
|
|
191
|
-
<
|
|
192
|
-
<
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
265
|
+
<!-- Header — custom or default progress indicator -->
|
|
266
|
+
<ng-container *ngIf="customHeader; else defaultHeader">
|
|
267
|
+
<ng-container *ngTemplateOutlet="customHeader.templateRef; context: { $implicit: s }"></ng-container>
|
|
268
|
+
</ng-container>
|
|
269
|
+
<ng-template #defaultHeader>
|
|
270
|
+
<div class="pw-shell__header" *ngIf="!hideProgress">
|
|
271
|
+
<div class="pw-shell__steps">
|
|
272
|
+
<div
|
|
273
|
+
*ngFor="let step of s.steps; let i = index"
|
|
274
|
+
class="pw-shell__step"
|
|
275
|
+
[ngClass]="'pw-shell__step--' + step.status"
|
|
276
|
+
>
|
|
277
|
+
<span class="pw-shell__step-dot">{{ step.status === 'completed' ? '✓' : (i + 1) }}</span>
|
|
278
|
+
<span class="pw-shell__step-label">{{ step.title ?? step.id }}</span>
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
<div class="pw-shell__track">
|
|
282
|
+
<div class="pw-shell__track-fill" [style.width.%]="s.progress * 100"></div>
|
|
200
283
|
</div>
|
|
201
284
|
</div>
|
|
202
|
-
|
|
203
|
-
<div class="pw-shell__track-fill" [style.width.%]="s.progress * 100"></div>
|
|
204
|
-
</div>
|
|
205
|
-
</div>
|
|
285
|
+
</ng-template>
|
|
206
286
|
|
|
207
287
|
<!-- Body — step content -->
|
|
208
288
|
<div class="pw-shell__body">
|
|
@@ -218,33 +298,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
218
298
|
<li *ngFor="let msg of s.validationMessages" class="pw-shell__validation-item">{{ msg }}</li>
|
|
219
299
|
</ul>
|
|
220
300
|
|
|
221
|
-
<!-- Footer — navigation buttons -->
|
|
222
|
-
<
|
|
223
|
-
<
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
301
|
+
<!-- Footer — custom or default navigation buttons -->
|
|
302
|
+
<ng-container *ngIf="customFooter; else defaultFooter">
|
|
303
|
+
<ng-container *ngTemplateOutlet="customFooter.templateRef; context: { $implicit: s, actions: shellActions }"></ng-container>
|
|
304
|
+
</ng-container>
|
|
305
|
+
<ng-template #defaultFooter>
|
|
306
|
+
<div class="pw-shell__footer">
|
|
307
|
+
<div class="pw-shell__footer-left">
|
|
308
|
+
<button
|
|
309
|
+
*ngIf="!s.isFirstStep"
|
|
310
|
+
type="button"
|
|
311
|
+
class="pw-shell__btn pw-shell__btn--back"
|
|
312
|
+
[disabled]="s.isNavigating || !s.canMovePrevious"
|
|
313
|
+
(click)="facade.previous()"
|
|
314
|
+
>{{ backLabel }}</button>
|
|
315
|
+
</div>
|
|
316
|
+
<div class="pw-shell__footer-right">
|
|
317
|
+
<button
|
|
318
|
+
*ngIf="!hideCancel"
|
|
319
|
+
type="button"
|
|
320
|
+
class="pw-shell__btn pw-shell__btn--cancel"
|
|
321
|
+
[disabled]="s.isNavigating"
|
|
322
|
+
(click)="facade.cancel()"
|
|
323
|
+
>{{ cancelLabel }}</button>
|
|
324
|
+
<button
|
|
325
|
+
type="button"
|
|
326
|
+
class="pw-shell__btn pw-shell__btn--next"
|
|
327
|
+
[disabled]="s.isNavigating || !s.canMoveNext"
|
|
328
|
+
(click)="facade.next()"
|
|
329
|
+
>{{ s.isLastStep ? finishLabel : nextLabel }}</button>
|
|
330
|
+
</div>
|
|
246
331
|
</div>
|
|
247
|
-
</
|
|
332
|
+
</ng-template>
|
|
248
333
|
</div>
|
|
249
334
|
`
|
|
250
335
|
}]
|
|
@@ -276,5 +361,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
276
361
|
}], stepDirectives: [{
|
|
277
362
|
type: ContentChildren,
|
|
278
363
|
args: [PathStepDirective]
|
|
364
|
+
}], customHeader: [{
|
|
365
|
+
type: ContentChild,
|
|
366
|
+
args: [PathShellHeaderDirective]
|
|
367
|
+
}], customFooter: [{
|
|
368
|
+
type: ContentChild,
|
|
369
|
+
args: [PathShellFooterDirective]
|
|
279
370
|
}] } });
|
|
280
371
|
//# sourceMappingURL=shell.js.map
|
package/dist/shell.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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,eAAe,EAIf,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;
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@daltonr/pathwrite-angular",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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.",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"scripts": {
|
|
43
43
|
"build": "ngc -p tsconfig.json && cp ../shell.css dist/index.css",
|
|
44
44
|
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
45
|
-
"prepublishOnly": "npm run clean && npm run build"
|
|
45
|
+
"prepublishOnly": "test -d dist && echo 'dist already built, skipping' || (npm run clean && npm run build)"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"@angular/core": ">=16.0.0",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"@angular/compiler-cli": "^17.0.0"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@daltonr/pathwrite-core": "^0.
|
|
63
|
+
"@daltonr/pathwrite-core": "^0.3.0"
|
|
64
64
|
},
|
|
65
65
|
"publishConfig": {
|
|
66
66
|
"access": "public"
|
package/src/index.ts
CHANGED
|
@@ -54,12 +54,12 @@ export class PathFacade<TData extends PathData = PathData> implements OnDestroy
|
|
|
54
54
|
this._state$.complete();
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
public start(path: PathDefinition
|
|
57
|
+
public start(path: PathDefinition<any>, initialData: PathData = {}): Promise<void> {
|
|
58
58
|
return this.engine.start(path, initialData);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
public startSubPath(path: PathDefinition
|
|
62
|
-
return this.engine.startSubPath(path, initialData);
|
|
61
|
+
public startSubPath(path: PathDefinition<any>, initialData: PathData = {}, meta?: Record<string, unknown>): Promise<void> {
|
|
62
|
+
return this.engine.startSubPath(path, initialData, meta);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
public next(): Promise<void> {
|
package/src/shell.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
Input,
|
|
6
6
|
Output,
|
|
7
7
|
EventEmitter,
|
|
8
|
+
ContentChild,
|
|
8
9
|
ContentChildren,
|
|
9
10
|
QueryList,
|
|
10
11
|
OnInit,
|
|
@@ -19,10 +20,29 @@ import { takeUntil } from "rxjs/operators";
|
|
|
19
20
|
import {
|
|
20
21
|
PathData,
|
|
21
22
|
PathDefinition,
|
|
22
|
-
PathEvent
|
|
23
|
+
PathEvent,
|
|
24
|
+
PathSnapshot
|
|
23
25
|
} from "@daltonr/pathwrite-core";
|
|
24
26
|
import { PathFacade } from "./index";
|
|
25
27
|
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// PathShellActions
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Navigation actions passed as template context to custom `pwShellFooter`
|
|
34
|
+
* templates. Mirrors what React's `renderFooter` and Vue's `#footer` slot
|
|
35
|
+
* receive, using promises so it is consistent with the Angular facade.
|
|
36
|
+
*/
|
|
37
|
+
export interface PathShellActions {
|
|
38
|
+
next: () => Promise<void>;
|
|
39
|
+
previous: () => Promise<void>;
|
|
40
|
+
cancel: () => Promise<void>;
|
|
41
|
+
goToStep: (stepId: string) => Promise<void>;
|
|
42
|
+
goToStepChecked: (stepId: string) => Promise<void>;
|
|
43
|
+
setData: (key: string, value: unknown) => Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
|
|
26
46
|
// ---------------------------------------------------------------------------
|
|
27
47
|
// PathStepDirective
|
|
28
48
|
// ---------------------------------------------------------------------------
|
|
@@ -44,6 +64,56 @@ export class PathStepDirective {
|
|
|
44
64
|
public constructor(public readonly templateRef: TemplateRef<unknown>) {}
|
|
45
65
|
}
|
|
46
66
|
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// PathShellHeaderDirective
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Replaces the default progress header inside `<pw-shell>`.
|
|
73
|
+
* The template receives the current `PathSnapshot` as the implicit context.
|
|
74
|
+
*
|
|
75
|
+
* ```html
|
|
76
|
+
* <pw-shell [path]="myPath">
|
|
77
|
+
* <ng-template pwShellHeader let-s>
|
|
78
|
+
* <my-custom-progress [snapshot]="s" />
|
|
79
|
+
* </ng-template>
|
|
80
|
+
* <ng-template pwStep="details"><app-details-form /></ng-template>
|
|
81
|
+
* </pw-shell>
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
@Directive({ selector: "[pwShellHeader]", standalone: true })
|
|
85
|
+
export class PathShellHeaderDirective {
|
|
86
|
+
public constructor(
|
|
87
|
+
public readonly templateRef: TemplateRef<{ $implicit: PathSnapshot }>
|
|
88
|
+
) {}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// PathShellFooterDirective
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Replaces the default navigation footer inside `<pw-shell>`.
|
|
97
|
+
* The template receives the current `PathSnapshot` as the implicit context
|
|
98
|
+
* and a `actions` variable containing all navigation actions.
|
|
99
|
+
*
|
|
100
|
+
* ```html
|
|
101
|
+
* <pw-shell [path]="myPath">
|
|
102
|
+
* <ng-template pwShellFooter let-s let-actions="actions">
|
|
103
|
+
* <button (click)="actions.previous()" [disabled]="s.isFirstStep">Back</button>
|
|
104
|
+
* <button (click)="actions.next()" [disabled]="!s.canMoveNext">Next</button>
|
|
105
|
+
* </ng-template>
|
|
106
|
+
* <ng-template pwStep="details"><app-details-form /></ng-template>
|
|
107
|
+
* </pw-shell>
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
@Directive({ selector: "[pwShellFooter]", standalone: true })
|
|
111
|
+
export class PathShellFooterDirective {
|
|
112
|
+
public constructor(
|
|
113
|
+
public readonly templateRef: TemplateRef<{ $implicit: PathSnapshot; actions: PathShellActions }>
|
|
114
|
+
) {}
|
|
115
|
+
}
|
|
116
|
+
|
|
47
117
|
// ---------------------------------------------------------------------------
|
|
48
118
|
// PathShellComponent
|
|
49
119
|
// ---------------------------------------------------------------------------
|
|
@@ -76,22 +146,27 @@ export class PathStepDirective {
|
|
|
76
146
|
|
|
77
147
|
<!-- Active path -->
|
|
78
148
|
<div class="pw-shell" *ngIf="facade.state$ | async as s">
|
|
79
|
-
<!-- Header — progress indicator -->
|
|
80
|
-
<
|
|
81
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
149
|
+
<!-- Header — custom or default progress indicator -->
|
|
150
|
+
<ng-container *ngIf="customHeader; else defaultHeader">
|
|
151
|
+
<ng-container *ngTemplateOutlet="customHeader.templateRef; context: { $implicit: s }"></ng-container>
|
|
152
|
+
</ng-container>
|
|
153
|
+
<ng-template #defaultHeader>
|
|
154
|
+
<div class="pw-shell__header" *ngIf="!hideProgress">
|
|
155
|
+
<div class="pw-shell__steps">
|
|
156
|
+
<div
|
|
157
|
+
*ngFor="let step of s.steps; let i = index"
|
|
158
|
+
class="pw-shell__step"
|
|
159
|
+
[ngClass]="'pw-shell__step--' + step.status"
|
|
160
|
+
>
|
|
161
|
+
<span class="pw-shell__step-dot">{{ step.status === 'completed' ? '✓' : (i + 1) }}</span>
|
|
162
|
+
<span class="pw-shell__step-label">{{ step.title ?? step.id }}</span>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
<div class="pw-shell__track">
|
|
166
|
+
<div class="pw-shell__track-fill" [style.width.%]="s.progress * 100"></div>
|
|
89
167
|
</div>
|
|
90
168
|
</div>
|
|
91
|
-
|
|
92
|
-
<div class="pw-shell__track-fill" [style.width.%]="s.progress * 100"></div>
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
169
|
+
</ng-template>
|
|
95
170
|
|
|
96
171
|
<!-- Body — step content -->
|
|
97
172
|
<div class="pw-shell__body">
|
|
@@ -107,39 +182,44 @@ export class PathStepDirective {
|
|
|
107
182
|
<li *ngFor="let msg of s.validationMessages" class="pw-shell__validation-item">{{ msg }}</li>
|
|
108
183
|
</ul>
|
|
109
184
|
|
|
110
|
-
<!-- Footer — navigation buttons -->
|
|
111
|
-
<
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
185
|
+
<!-- Footer — custom or default navigation buttons -->
|
|
186
|
+
<ng-container *ngIf="customFooter; else defaultFooter">
|
|
187
|
+
<ng-container *ngTemplateOutlet="customFooter.templateRef; context: { $implicit: s, actions: shellActions }"></ng-container>
|
|
188
|
+
</ng-container>
|
|
189
|
+
<ng-template #defaultFooter>
|
|
190
|
+
<div class="pw-shell__footer">
|
|
191
|
+
<div class="pw-shell__footer-left">
|
|
192
|
+
<button
|
|
193
|
+
*ngIf="!s.isFirstStep"
|
|
194
|
+
type="button"
|
|
195
|
+
class="pw-shell__btn pw-shell__btn--back"
|
|
196
|
+
[disabled]="s.isNavigating || !s.canMovePrevious"
|
|
197
|
+
(click)="facade.previous()"
|
|
198
|
+
>{{ backLabel }}</button>
|
|
199
|
+
</div>
|
|
200
|
+
<div class="pw-shell__footer-right">
|
|
201
|
+
<button
|
|
202
|
+
*ngIf="!hideCancel"
|
|
203
|
+
type="button"
|
|
204
|
+
class="pw-shell__btn pw-shell__btn--cancel"
|
|
205
|
+
[disabled]="s.isNavigating"
|
|
206
|
+
(click)="facade.cancel()"
|
|
207
|
+
>{{ cancelLabel }}</button>
|
|
208
|
+
<button
|
|
209
|
+
type="button"
|
|
210
|
+
class="pw-shell__btn pw-shell__btn--next"
|
|
211
|
+
[disabled]="s.isNavigating || !s.canMoveNext"
|
|
212
|
+
(click)="facade.next()"
|
|
213
|
+
>{{ s.isLastStep ? finishLabel : nextLabel }}</button>
|
|
214
|
+
</div>
|
|
135
215
|
</div>
|
|
136
|
-
</
|
|
216
|
+
</ng-template>
|
|
137
217
|
</div>
|
|
138
218
|
`
|
|
139
219
|
})
|
|
140
220
|
export class PathShellComponent implements OnInit, OnDestroy {
|
|
141
221
|
/** The path definition to run. Required. */
|
|
142
|
-
@Input({ required: true }) path!: PathDefinition
|
|
222
|
+
@Input({ required: true }) path!: PathDefinition<any>;
|
|
143
223
|
/** Initial data merged into the path engine on start. */
|
|
144
224
|
@Input() initialData: PathData = {};
|
|
145
225
|
/** Start the path automatically on ngOnInit. Set to false to call doStart() manually. */
|
|
@@ -162,6 +242,8 @@ export class PathShellComponent implements OnInit, OnDestroy {
|
|
|
162
242
|
@Output() pathEvent = new EventEmitter<PathEvent>();
|
|
163
243
|
|
|
164
244
|
@ContentChildren(PathStepDirective) stepDirectives!: QueryList<PathStepDirective>;
|
|
245
|
+
@ContentChild(PathShellHeaderDirective) customHeader?: PathShellHeaderDirective;
|
|
246
|
+
@ContentChild(PathShellFooterDirective) customFooter?: PathShellFooterDirective;
|
|
165
247
|
|
|
166
248
|
public readonly facade = inject(PathFacade);
|
|
167
249
|
/** The shell's own component-level injector. Passed to ngTemplateOutlet so that
|
|
@@ -169,6 +251,16 @@ export class PathShellComponent implements OnInit, OnDestroy {
|
|
|
169
251
|
protected readonly shellInjector = inject(Injector);
|
|
170
252
|
public started = false;
|
|
171
253
|
|
|
254
|
+
/** Navigation actions passed to custom `pwShellFooter` templates. */
|
|
255
|
+
protected readonly shellActions: PathShellActions = {
|
|
256
|
+
next: () => this.facade.next(),
|
|
257
|
+
previous: () => this.facade.previous(),
|
|
258
|
+
cancel: () => this.facade.cancel(),
|
|
259
|
+
goToStep: (id) => this.facade.goToStep(id),
|
|
260
|
+
goToStepChecked: (id) => this.facade.goToStepChecked(id),
|
|
261
|
+
setData: (key, value) => this.facade.setData(key, value as never),
|
|
262
|
+
};
|
|
263
|
+
|
|
172
264
|
private readonly destroy$ = new Subject<void>();
|
|
173
265
|
|
|
174
266
|
public ngOnInit(): void {
|
|
@@ -193,5 +285,3 @@ export class PathShellComponent implements OnInit, OnDestroy {
|
|
|
193
285
|
this.facade.start(this.path, this.initialData);
|
|
194
286
|
}
|
|
195
287
|
}
|
|
196
|
-
|
|
197
|
-
|