@daltonr/pathwrite-angular 0.1.1

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Richard Dalton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # @daltonr/pathwrite-angular
2
+
3
+ Angular `@Injectable` facade over `@daltonr/pathwrite-core`. Exposes path state and events as RxJS observables that work seamlessly with Angular signals, the `async` pipe, and `takeUntilDestroyed`.
4
+
5
+ ## Setup
6
+
7
+ Provide `PathFacade` at the component level so each component gets its own isolated path instance, and Angular handles cleanup automatically via `ngOnDestroy`.
8
+
9
+ ```typescript
10
+ @Component({
11
+ // ...
12
+ providers: [PathFacade]
13
+ })
14
+ export class MyComponent {
15
+ protected readonly facade = inject(PathFacade);
16
+
17
+ // Reactive snapshot — updates whenever the path state changes
18
+ public readonly snapshot = toSignal(this.facade.state$, { initialValue: null });
19
+
20
+ constructor() {
21
+ // Automatically unsubscribes when the component is destroyed
22
+ this.facade.events$.pipe(takeUntilDestroyed()).subscribe((event) => {
23
+ console.log(event);
24
+ });
25
+ }
26
+ }
27
+ ```
28
+
29
+ ## PathFacade API
30
+
31
+ ### Observables
32
+
33
+ | Member | Type | Description |
34
+ |--------|------|-------------|
35
+ | `state$` | `Observable<PathSnapshot \| null>` | Current snapshot. `null` when no path is active. Backed by a `BehaviorSubject` — late subscribers receive the current value immediately. |
36
+ | `events$` | `Observable<PathEvent>` | All engine events: `stateChanged`, `completed`, `cancelled`, `resumed`. |
37
+
38
+ ### Methods
39
+
40
+ | Method | Description |
41
+ |--------|-------------|
42
+ | `start(definition, data?)` | Start or re-start a path. |
43
+ | `startSubPath(definition, data?)` | Push a sub-path. Requires an active path. |
44
+ | `next()` | Advance one step. Completes the path on the last step. |
45
+ | `previous()` | Go back one step. Cancels the path from the first step. |
46
+ | `cancel()` | Cancel the active path (or sub-path). |
47
+ | `setData(key, value)` | Update a single data value; emits `stateChanged`. |
48
+ | `goToStep(stepId)` | Jump directly to a step by ID. |
49
+ | `snapshot()` | Synchronous read of the current `PathSnapshot \| null`. |
50
+
51
+ ### Lifecycle
52
+
53
+ `PathFacade` implements `OnDestroy`. When Angular destroys the providing component, `ngOnDestroy` is called automatically, which:
54
+ - Unsubscribes from the internal `PathEngine`
55
+ - Completes `state$` and `events$`
56
+
57
+ ## Using with signals (Angular 16+)
58
+
59
+ ```typescript
60
+ public readonly snapshot = toSignal(this.facade.state$, { initialValue: null });
61
+
62
+ // Derive computed values from the snapshot signal
63
+ public readonly isActive = computed(() => this.snapshot() !== null);
64
+ public readonly currentStep = computed(() => this.snapshot()?.stepId ?? null);
65
+ ```
66
+
67
+ ## Using with the async pipe
68
+
69
+ ```html
70
+ <ng-container *ngIf="facade.state$ | async as s">
71
+ <p>{{ s.pathId }} / {{ s.stepId }}</p>
72
+ </ng-container>
73
+ ```
74
+
75
+ ## Peer dependencies
76
+
77
+ | Package | Version |
78
+ |---------|---------|
79
+ | `@angular/core` | `>=16.0.0` |
80
+ | `rxjs` | `>=7.0.0` |
@@ -0,0 +1,21 @@
1
+ import { OnDestroy } from "@angular/core";
2
+ import { Observable } from "rxjs";
3
+ import { PathData, PathDefinition, PathEvent, PathSnapshot } from "@daltonr/pathwrite-core";
4
+ export declare class PathFacade implements OnDestroy {
5
+ private readonly engine;
6
+ private readonly _state$;
7
+ private readonly _events$;
8
+ private readonly unsubscribeFromEngine;
9
+ readonly state$: Observable<PathSnapshot | null>;
10
+ readonly events$: Observable<PathEvent>;
11
+ constructor();
12
+ ngOnDestroy(): void;
13
+ start(path: PathDefinition, initialData?: PathData): Promise<void>;
14
+ startSubPath(path: PathDefinition, initialData?: PathData): Promise<void>;
15
+ next(): Promise<void>;
16
+ previous(): Promise<void>;
17
+ cancel(): Promise<void>;
18
+ setData(key: string, value: unknown): Promise<void>;
19
+ goToStep(stepId: string): Promise<void>;
20
+ snapshot(): PathSnapshot | null;
21
+ }
package/dist/index.js ADDED
@@ -0,0 +1,102 @@
1
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
3
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
4
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
5
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6
+ var _, done = false;
7
+ for (var i = decorators.length - 1; i >= 0; i--) {
8
+ var context = {};
9
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
10
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
11
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
12
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
13
+ if (kind === "accessor") {
14
+ if (result === void 0) continue;
15
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
16
+ if (_ = accept(result.get)) descriptor.get = _;
17
+ if (_ = accept(result.set)) descriptor.set = _;
18
+ if (_ = accept(result.init)) initializers.unshift(_);
19
+ }
20
+ else if (_ = accept(result)) {
21
+ if (kind === "field") initializers.unshift(_);
22
+ else descriptor[key] = _;
23
+ }
24
+ }
25
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
26
+ done = true;
27
+ };
28
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
29
+ var useValue = arguments.length > 2;
30
+ for (var i = 0; i < initializers.length; i++) {
31
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
32
+ }
33
+ return useValue ? value : void 0;
34
+ };
35
+ import { Injectable } from "@angular/core";
36
+ import { BehaviorSubject, Subject } from "rxjs";
37
+ import { PathEngine } from "@daltonr/pathwrite-core";
38
+ let PathFacade = (() => {
39
+ let _classDecorators = [Injectable()];
40
+ let _classDescriptor;
41
+ let _classExtraInitializers = [];
42
+ let _classThis;
43
+ var PathFacade = class {
44
+ static { _classThis = this; }
45
+ static {
46
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
47
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
48
+ PathFacade = _classThis = _classDescriptor.value;
49
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
50
+ __runInitializers(_classThis, _classExtraInitializers);
51
+ }
52
+ engine = new PathEngine();
53
+ _state$ = new BehaviorSubject(null);
54
+ _events$ = new Subject();
55
+ unsubscribeFromEngine;
56
+ state$ = this._state$.asObservable();
57
+ events$ = this._events$.asObservable();
58
+ constructor() {
59
+ this.unsubscribeFromEngine = this.engine.subscribe((event) => {
60
+ this._events$.next(event);
61
+ if (event.type === "stateChanged" || event.type === "resumed") {
62
+ this._state$.next(event.snapshot);
63
+ }
64
+ else if (event.type === "completed" || event.type === "cancelled") {
65
+ this._state$.next(null);
66
+ }
67
+ });
68
+ }
69
+ ngOnDestroy() {
70
+ this.unsubscribeFromEngine();
71
+ this._events$.complete();
72
+ this._state$.complete();
73
+ }
74
+ start(path, initialData = {}) {
75
+ return this.engine.start(path, initialData);
76
+ }
77
+ startSubPath(path, initialData = {}) {
78
+ return this.engine.startSubPath(path, initialData);
79
+ }
80
+ next() {
81
+ return this.engine.next();
82
+ }
83
+ previous() {
84
+ return this.engine.previous();
85
+ }
86
+ cancel() {
87
+ return this.engine.cancel();
88
+ }
89
+ setData(key, value) {
90
+ return this.engine.setData(key, value);
91
+ }
92
+ goToStep(stepId) {
93
+ return this.engine.goToStep(stepId);
94
+ }
95
+ snapshot() {
96
+ return this._state$.getValue();
97
+ }
98
+ };
99
+ return PathFacade = _classThis;
100
+ })();
101
+ export { PathFacade };
102
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,eAAe,EAAc,OAAO,EAAE,MAAM,MAAM,CAAC;AAC5D,OAAO,EAGL,UAAU,EAGX,MAAM,yBAAyB,CAAC;IAGpB,UAAU;4BADtB,UAAU,EAAE;;;;;;;;YACb,6KAyDC;;;YAzDY,uDAAU;;QACJ,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC1B,OAAO,GAAG,IAAI,eAAe,CAAsB,IAAI,CAAC,CAAC;QACzD,QAAQ,GAAG,IAAI,OAAO,EAAa,CAAC;QACpC,qBAAqB,CAAa;QAEnC,MAAM,GAAoC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QACtE,OAAO,GAA0B,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;QAE9E;YACE,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC3D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC1B,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBAC9D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACpC,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBACpE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAEM,WAAW;YAChB,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC7B,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC1B,CAAC;QAEM,KAAK,CAAC,IAAoB,EAAE,cAAwB,EAAE;YAC3D,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC9C,CAAC;QAEM,YAAY,CAAC,IAAoB,EAAE,cAAwB,EAAE;YAClE,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACrD,CAAC;QAEM,IAAI;YACT,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5B,CAAC;QAEM,QAAQ;YACb,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,CAAC;QAEM,MAAM;YACX,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9B,CAAC;QAEM,OAAO,CAAC,GAAW,EAAE,KAAc;YACxC,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;QAEM,QAAQ,CAAC,MAAc;YAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC;QAEM,QAAQ;YACb,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACjC,CAAC;;;;SAxDU,UAAU"}
@@ -0,0 +1,51 @@
1
+ import { TemplateRef, EventEmitter, QueryList, OnInit, OnDestroy } from "@angular/core";
2
+ import { PathData, PathDefinition, PathEvent } from "@daltonr/pathwrite-core";
3
+ import { PathFacade } from "./index";
4
+ /**
5
+ * Structural directive that associates a template with a step ID.
6
+ * Used inside `<pw-shell>` to define per-step content.
7
+ *
8
+ * ```html
9
+ * <pw-shell [path]="myPath">
10
+ * <ng-template pwStep="details"><app-details-form /></ng-template>
11
+ * <ng-template pwStep="review"><app-review-panel /></ng-template>
12
+ * </pw-shell>
13
+ * ```
14
+ */
15
+ export declare class PathStepDirective {
16
+ readonly templateRef: TemplateRef<unknown>;
17
+ stepId: string;
18
+ constructor(templateRef: TemplateRef<unknown>);
19
+ }
20
+ /**
21
+ * Default UI shell component. Renders a progress indicator, step content,
22
+ * and navigation buttons.
23
+ *
24
+ * ```html
25
+ * <pw-shell [path]="myPath" [initialData]="{ name: '' }" (completed)="onDone($event)">
26
+ * <ng-template pwStep="details"><app-details-form /></ng-template>
27
+ * <ng-template pwStep="review"><app-review-panel /></ng-template>
28
+ * </pw-shell>
29
+ * ```
30
+ */
31
+ export declare class PathShellComponent implements OnInit, OnDestroy {
32
+ path: PathDefinition;
33
+ initialData: PathData;
34
+ autoStart: boolean;
35
+ backLabel: string;
36
+ nextLabel: string;
37
+ finishLabel: string;
38
+ cancelLabel: string;
39
+ hideCancel: boolean;
40
+ hideProgress: boolean;
41
+ completed: EventEmitter<PathData>;
42
+ cancelled: EventEmitter<PathData>;
43
+ pathEvent: EventEmitter<PathEvent>;
44
+ stepDirectives: QueryList<PathStepDirective>;
45
+ readonly facade: PathFacade;
46
+ started: boolean;
47
+ private readonly destroy$;
48
+ ngOnInit(): void;
49
+ ngOnDestroy(): void;
50
+ doStart(): void;
51
+ }
package/dist/shell.js ADDED
@@ -0,0 +1,288 @@
1
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
3
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
4
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
5
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6
+ var _, done = false;
7
+ for (var i = decorators.length - 1; i >= 0; i--) {
8
+ var context = {};
9
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
10
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
11
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
12
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
13
+ if (kind === "accessor") {
14
+ if (result === void 0) continue;
15
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
16
+ if (_ = accept(result.get)) descriptor.get = _;
17
+ if (_ = accept(result.set)) descriptor.set = _;
18
+ if (_ = accept(result.init)) initializers.unshift(_);
19
+ }
20
+ else if (_ = accept(result)) {
21
+ if (kind === "field") initializers.unshift(_);
22
+ else descriptor[key] = _;
23
+ }
24
+ }
25
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
26
+ done = true;
27
+ };
28
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
29
+ var useValue = arguments.length > 2;
30
+ for (var i = 0; i < initializers.length; i++) {
31
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
32
+ }
33
+ return useValue ? value : void 0;
34
+ };
35
+ import { Component, Directive, Input, Output, EventEmitter, ContentChildren, inject, ChangeDetectionStrategy } from "@angular/core";
36
+ import { CommonModule } from "@angular/common";
37
+ import { Subject } from "rxjs";
38
+ import { takeUntil } from "rxjs/operators";
39
+ import { PathFacade } from "./index";
40
+ // ---------------------------------------------------------------------------
41
+ // PathStepDirective
42
+ // ---------------------------------------------------------------------------
43
+ /**
44
+ * Structural directive that associates a template with a step ID.
45
+ * Used inside `<pw-shell>` to define per-step content.
46
+ *
47
+ * ```html
48
+ * <pw-shell [path]="myPath">
49
+ * <ng-template pwStep="details"><app-details-form /></ng-template>
50
+ * <ng-template pwStep="review"><app-review-panel /></ng-template>
51
+ * </pw-shell>
52
+ * ```
53
+ */
54
+ let PathStepDirective = (() => {
55
+ let _classDecorators = [Directive({ selector: "[pwStep]", standalone: true })];
56
+ let _classDescriptor;
57
+ let _classExtraInitializers = [];
58
+ let _classThis;
59
+ let _stepId_decorators;
60
+ let _stepId_initializers = [];
61
+ let _stepId_extraInitializers = [];
62
+ var PathStepDirective = class {
63
+ static { _classThis = this; }
64
+ static {
65
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
66
+ _stepId_decorators = [Input({ required: true, alias: "pwStep" })];
67
+ __esDecorate(null, null, _stepId_decorators, { kind: "field", name: "stepId", static: false, private: false, access: { has: obj => "stepId" in obj, get: obj => obj.stepId, set: (obj, value) => { obj.stepId = value; } }, metadata: _metadata }, _stepId_initializers, _stepId_extraInitializers);
68
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
69
+ PathStepDirective = _classThis = _classDescriptor.value;
70
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
71
+ __runInitializers(_classThis, _classExtraInitializers);
72
+ }
73
+ templateRef;
74
+ stepId = __runInitializers(this, _stepId_initializers, void 0);
75
+ constructor(templateRef) {
76
+ __runInitializers(this, _stepId_extraInitializers);
77
+ this.templateRef = templateRef;
78
+ }
79
+ };
80
+ return PathStepDirective = _classThis;
81
+ })();
82
+ export { PathStepDirective };
83
+ // ---------------------------------------------------------------------------
84
+ // PathShellComponent
85
+ // ---------------------------------------------------------------------------
86
+ /**
87
+ * Default UI shell component. Renders a progress indicator, step content,
88
+ * and navigation buttons.
89
+ *
90
+ * ```html
91
+ * <pw-shell [path]="myPath" [initialData]="{ name: '' }" (completed)="onDone($event)">
92
+ * <ng-template pwStep="details"><app-details-form /></ng-template>
93
+ * <ng-template pwStep="review"><app-review-panel /></ng-template>
94
+ * </pw-shell>
95
+ * ```
96
+ */
97
+ let PathShellComponent = (() => {
98
+ let _classDecorators = [Component({
99
+ selector: "pw-shell",
100
+ standalone: true,
101
+ imports: [CommonModule],
102
+ providers: [PathFacade],
103
+ changeDetection: ChangeDetectionStrategy.Default,
104
+ template: `
105
+ <!-- Empty state -->
106
+ <div class="pw-shell" *ngIf="!(facade.state$ | async)">
107
+ <div class="pw-shell__empty" *ngIf="!started">
108
+ <p>No active path.</p>
109
+ <button *ngIf="!autoStart" type="button" class="pw-shell__start-btn" (click)="doStart()">Start</button>
110
+ </div>
111
+ </div>
112
+
113
+ <!-- Active path -->
114
+ <div class="pw-shell" *ngIf="facade.state$ | async as s">
115
+ <!-- Header — progress indicator -->
116
+ <div class="pw-shell__header" *ngIf="!hideProgress">
117
+ <div class="pw-shell__steps">
118
+ <div
119
+ *ngFor="let step of s.steps; let i = index"
120
+ class="pw-shell__step"
121
+ [ngClass]="'pw-shell__step--' + step.status"
122
+ >
123
+ <span class="pw-shell__step-dot">{{ step.status === 'completed' ? '✓' : (i + 1) }}</span>
124
+ <span class="pw-shell__step-label">{{ step.title ?? step.id }}</span>
125
+ </div>
126
+ </div>
127
+ <div class="pw-shell__track">
128
+ <div class="pw-shell__track-fill" [style.width.%]="s.progress * 100"></div>
129
+ </div>
130
+ </div>
131
+
132
+ <!-- Body — step content -->
133
+ <div class="pw-shell__body">
134
+ <ng-container *ngFor="let stepDir of stepDirectives">
135
+ <ng-container *ngIf="stepDir.stepId === s.stepId">
136
+ <ng-container *ngTemplateOutlet="stepDir.templateRef"></ng-container>
137
+ </ng-container>
138
+ </ng-container>
139
+ </div>
140
+
141
+ <!-- Footer — navigation buttons -->
142
+ <div class="pw-shell__footer">
143
+ <div class="pw-shell__footer-left">
144
+ <button
145
+ *ngIf="!s.isFirstStep"
146
+ type="button"
147
+ class="pw-shell__btn pw-shell__btn--back"
148
+ [disabled]="s.isNavigating"
149
+ (click)="facade.previous()"
150
+ >{{ backLabel }}</button>
151
+ </div>
152
+ <div class="pw-shell__footer-right">
153
+ <button
154
+ *ngIf="!hideCancel"
155
+ type="button"
156
+ class="pw-shell__btn pw-shell__btn--cancel"
157
+ [disabled]="s.isNavigating"
158
+ (click)="facade.cancel()"
159
+ >{{ cancelLabel }}</button>
160
+ <button
161
+ type="button"
162
+ class="pw-shell__btn pw-shell__btn--next"
163
+ [disabled]="s.isNavigating"
164
+ (click)="facade.next()"
165
+ >{{ s.isLastStep ? finishLabel : nextLabel }}</button>
166
+ </div>
167
+ </div>
168
+ </div>
169
+ `
170
+ })];
171
+ let _classDescriptor;
172
+ let _classExtraInitializers = [];
173
+ let _classThis;
174
+ let _path_decorators;
175
+ let _path_initializers = [];
176
+ let _path_extraInitializers = [];
177
+ let _initialData_decorators;
178
+ let _initialData_initializers = [];
179
+ let _initialData_extraInitializers = [];
180
+ let _autoStart_decorators;
181
+ let _autoStart_initializers = [];
182
+ let _autoStart_extraInitializers = [];
183
+ let _backLabel_decorators;
184
+ let _backLabel_initializers = [];
185
+ let _backLabel_extraInitializers = [];
186
+ let _nextLabel_decorators;
187
+ let _nextLabel_initializers = [];
188
+ let _nextLabel_extraInitializers = [];
189
+ let _finishLabel_decorators;
190
+ let _finishLabel_initializers = [];
191
+ let _finishLabel_extraInitializers = [];
192
+ let _cancelLabel_decorators;
193
+ let _cancelLabel_initializers = [];
194
+ let _cancelLabel_extraInitializers = [];
195
+ let _hideCancel_decorators;
196
+ let _hideCancel_initializers = [];
197
+ let _hideCancel_extraInitializers = [];
198
+ let _hideProgress_decorators;
199
+ let _hideProgress_initializers = [];
200
+ let _hideProgress_extraInitializers = [];
201
+ let _completed_decorators;
202
+ let _completed_initializers = [];
203
+ let _completed_extraInitializers = [];
204
+ let _cancelled_decorators;
205
+ let _cancelled_initializers = [];
206
+ let _cancelled_extraInitializers = [];
207
+ let _pathEvent_decorators;
208
+ let _pathEvent_initializers = [];
209
+ let _pathEvent_extraInitializers = [];
210
+ let _stepDirectives_decorators;
211
+ let _stepDirectives_initializers = [];
212
+ let _stepDirectives_extraInitializers = [];
213
+ var PathShellComponent = class {
214
+ static { _classThis = this; }
215
+ static {
216
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
217
+ _path_decorators = [Input({ required: true })];
218
+ _initialData_decorators = [Input()];
219
+ _autoStart_decorators = [Input()];
220
+ _backLabel_decorators = [Input()];
221
+ _nextLabel_decorators = [Input()];
222
+ _finishLabel_decorators = [Input()];
223
+ _cancelLabel_decorators = [Input()];
224
+ _hideCancel_decorators = [Input()];
225
+ _hideProgress_decorators = [Input()];
226
+ _completed_decorators = [Output()];
227
+ _cancelled_decorators = [Output()];
228
+ _pathEvent_decorators = [Output()];
229
+ _stepDirectives_decorators = [ContentChildren(PathStepDirective)];
230
+ __esDecorate(null, null, _path_decorators, { kind: "field", name: "path", static: false, private: false, access: { has: obj => "path" in obj, get: obj => obj.path, set: (obj, value) => { obj.path = value; } }, metadata: _metadata }, _path_initializers, _path_extraInitializers);
231
+ __esDecorate(null, null, _initialData_decorators, { kind: "field", name: "initialData", static: false, private: false, access: { has: obj => "initialData" in obj, get: obj => obj.initialData, set: (obj, value) => { obj.initialData = value; } }, metadata: _metadata }, _initialData_initializers, _initialData_extraInitializers);
232
+ __esDecorate(null, null, _autoStart_decorators, { kind: "field", name: "autoStart", static: false, private: false, access: { has: obj => "autoStart" in obj, get: obj => obj.autoStart, set: (obj, value) => { obj.autoStart = value; } }, metadata: _metadata }, _autoStart_initializers, _autoStart_extraInitializers);
233
+ __esDecorate(null, null, _backLabel_decorators, { kind: "field", name: "backLabel", static: false, private: false, access: { has: obj => "backLabel" in obj, get: obj => obj.backLabel, set: (obj, value) => { obj.backLabel = value; } }, metadata: _metadata }, _backLabel_initializers, _backLabel_extraInitializers);
234
+ __esDecorate(null, null, _nextLabel_decorators, { kind: "field", name: "nextLabel", static: false, private: false, access: { has: obj => "nextLabel" in obj, get: obj => obj.nextLabel, set: (obj, value) => { obj.nextLabel = value; } }, metadata: _metadata }, _nextLabel_initializers, _nextLabel_extraInitializers);
235
+ __esDecorate(null, null, _finishLabel_decorators, { kind: "field", name: "finishLabel", static: false, private: false, access: { has: obj => "finishLabel" in obj, get: obj => obj.finishLabel, set: (obj, value) => { obj.finishLabel = value; } }, metadata: _metadata }, _finishLabel_initializers, _finishLabel_extraInitializers);
236
+ __esDecorate(null, null, _cancelLabel_decorators, { kind: "field", name: "cancelLabel", static: false, private: false, access: { has: obj => "cancelLabel" in obj, get: obj => obj.cancelLabel, set: (obj, value) => { obj.cancelLabel = value; } }, metadata: _metadata }, _cancelLabel_initializers, _cancelLabel_extraInitializers);
237
+ __esDecorate(null, null, _hideCancel_decorators, { kind: "field", name: "hideCancel", static: false, private: false, access: { has: obj => "hideCancel" in obj, get: obj => obj.hideCancel, set: (obj, value) => { obj.hideCancel = value; } }, metadata: _metadata }, _hideCancel_initializers, _hideCancel_extraInitializers);
238
+ __esDecorate(null, null, _hideProgress_decorators, { kind: "field", name: "hideProgress", static: false, private: false, access: { has: obj => "hideProgress" in obj, get: obj => obj.hideProgress, set: (obj, value) => { obj.hideProgress = value; } }, metadata: _metadata }, _hideProgress_initializers, _hideProgress_extraInitializers);
239
+ __esDecorate(null, null, _completed_decorators, { kind: "field", name: "completed", static: false, private: false, access: { has: obj => "completed" in obj, get: obj => obj.completed, set: (obj, value) => { obj.completed = value; } }, metadata: _metadata }, _completed_initializers, _completed_extraInitializers);
240
+ __esDecorate(null, null, _cancelled_decorators, { kind: "field", name: "cancelled", static: false, private: false, access: { has: obj => "cancelled" in obj, get: obj => obj.cancelled, set: (obj, value) => { obj.cancelled = value; } }, metadata: _metadata }, _cancelled_initializers, _cancelled_extraInitializers);
241
+ __esDecorate(null, null, _pathEvent_decorators, { kind: "field", name: "pathEvent", static: false, private: false, access: { has: obj => "pathEvent" in obj, get: obj => obj.pathEvent, set: (obj, value) => { obj.pathEvent = value; } }, metadata: _metadata }, _pathEvent_initializers, _pathEvent_extraInitializers);
242
+ __esDecorate(null, null, _stepDirectives_decorators, { kind: "field", name: "stepDirectives", static: false, private: false, access: { has: obj => "stepDirectives" in obj, get: obj => obj.stepDirectives, set: (obj, value) => { obj.stepDirectives = value; } }, metadata: _metadata }, _stepDirectives_initializers, _stepDirectives_extraInitializers);
243
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
244
+ PathShellComponent = _classThis = _classDescriptor.value;
245
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
246
+ __runInitializers(_classThis, _classExtraInitializers);
247
+ }
248
+ path = __runInitializers(this, _path_initializers, void 0);
249
+ initialData = (__runInitializers(this, _path_extraInitializers), __runInitializers(this, _initialData_initializers, {}));
250
+ autoStart = (__runInitializers(this, _initialData_extraInitializers), __runInitializers(this, _autoStart_initializers, true));
251
+ backLabel = (__runInitializers(this, _autoStart_extraInitializers), __runInitializers(this, _backLabel_initializers, "Back"));
252
+ nextLabel = (__runInitializers(this, _backLabel_extraInitializers), __runInitializers(this, _nextLabel_initializers, "Next"));
253
+ finishLabel = (__runInitializers(this, _nextLabel_extraInitializers), __runInitializers(this, _finishLabel_initializers, "Finish"));
254
+ cancelLabel = (__runInitializers(this, _finishLabel_extraInitializers), __runInitializers(this, _cancelLabel_initializers, "Cancel"));
255
+ hideCancel = (__runInitializers(this, _cancelLabel_extraInitializers), __runInitializers(this, _hideCancel_initializers, false));
256
+ hideProgress = (__runInitializers(this, _hideCancel_extraInitializers), __runInitializers(this, _hideProgress_initializers, false));
257
+ completed = (__runInitializers(this, _hideProgress_extraInitializers), __runInitializers(this, _completed_initializers, new EventEmitter()));
258
+ cancelled = (__runInitializers(this, _completed_extraInitializers), __runInitializers(this, _cancelled_initializers, new EventEmitter()));
259
+ pathEvent = (__runInitializers(this, _cancelled_extraInitializers), __runInitializers(this, _pathEvent_initializers, new EventEmitter()));
260
+ stepDirectives = (__runInitializers(this, _pathEvent_extraInitializers), __runInitializers(this, _stepDirectives_initializers, void 0));
261
+ facade = (__runInitializers(this, _stepDirectives_extraInitializers), inject(PathFacade));
262
+ started = false;
263
+ destroy$ = new Subject();
264
+ ngOnInit() {
265
+ this.facade.events$.pipe(takeUntil(this.destroy$)).subscribe((event) => {
266
+ this.pathEvent.emit(event);
267
+ if (event.type === "completed")
268
+ this.completed.emit(event.data);
269
+ if (event.type === "cancelled")
270
+ this.cancelled.emit(event.data);
271
+ });
272
+ if (this.autoStart) {
273
+ this.doStart();
274
+ }
275
+ }
276
+ ngOnDestroy() {
277
+ this.destroy$.next();
278
+ this.destroy$.complete();
279
+ }
280
+ doStart() {
281
+ this.started = true;
282
+ this.facade.start(this.path, this.initialData);
283
+ }
284
+ };
285
+ return PathShellComponent = _classThis;
286
+ })();
287
+ export { PathShellComponent };
288
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@daltonr/pathwrite-angular",
3
+ "version": "0.1.1",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "description": "Angular adapter for @daltonr/pathwrite-core — RxJS observables, signal-friendly, with optional <pw-shell> default UI.",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/richardadalton/pathwrite.git",
10
+ "directory": "packages/angular-adapter"
11
+ },
12
+ "keywords": [
13
+ "wizard",
14
+ "stepper",
15
+ "path",
16
+ "angular",
17
+ "multi-step",
18
+ "workflow"
19
+ ],
20
+ "sideEffects": false,
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js"
25
+ },
26
+ "./shell": {
27
+ "types": "./dist/shell.d.ts",
28
+ "import": "./dist/shell.js"
29
+ }
30
+ },
31
+ "main": "dist/index.js",
32
+ "types": "dist/index.d.ts",
33
+ "files": [
34
+ "dist",
35
+ "README.md",
36
+ "LICENSE"
37
+ ],
38
+ "scripts": {
39
+ "build": "tsc -p tsconfig.json",
40
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
41
+ "prepublishOnly": "npm run clean && npm run build"
42
+ },
43
+ "peerDependencies": {
44
+ "@angular/core": ">=16.0.0",
45
+ "@angular/common": ">=16.0.0",
46
+ "rxjs": "^7.0.0"
47
+ },
48
+ "dependencies": {
49
+ "@daltonr/pathwrite-core": "^0.1.1"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ }
54
+ }