@y3krulez/angular-archwizard
Version:
The port of angular-archwizard, supporting IVY and thus being compatible with Angular16+
1,132 lines (1,116 loc) • 89.9 kB
JavaScript
import * as i0 from '@angular/core';
import { Directive, EventEmitter, ContentChild, Input, Output, HostBinding, forwardRef, Component, InjectionToken, Inject, Optional, HostListener, ContentChildren, Host, NgModule } from '@angular/core';
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
/**
* The `awWizardStepSymbol` directive can be used as an alternative to the `navigationSymbol` input of a [[WizardStep]]
* to define the step symbol inside the navigation bar. This way step symbol may contain arbitrary content.
*
* ### Syntax
*
* ```html
* <ng-template awWizardStepSymbol>
* ...
* </ng-template>
* ```
*/
class WizardStepSymbolDirective {
/**
* Constructor
*
* @param templateRef A reference to the content of the `ng-template` that contains this [[WizardStepSymbolDirective]]
*/
constructor(templateRef) {
this.templateRef = templateRef;
}
}
WizardStepSymbolDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardStepSymbolDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
WizardStepSymbolDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: WizardStepSymbolDirective, selector: "ng-template[awStepSymbol], ng-template[awWizardStepSymbol]", ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardStepSymbolDirective, decorators: [{
type: Directive,
args: [{
selector: 'ng-template[awStepSymbol], ng-template[awWizardStepSymbol]'
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
/**
* The `awWizardStepTitle` directive can be used as an alternative to the `stepTitle` input of a [[WizardStep]]
* to define the content of a step title inside the navigation bar.
* This step title can be freely created and can contain more than only plain text
*
* ### Syntax
*
* ```html
* <ng-template awWizardStepTitle>
* ...
* </ng-template>
* ```
*
* @author Marc Arndt
*/
class WizardStepTitleDirective {
/**
* Constructor
*
* @param templateRef A reference to the content of the `ng-template` that contains this [[WizardStepTitleDirective]]
*/
constructor(templateRef) {
this.templateRef = templateRef;
}
}
WizardStepTitleDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardStepTitleDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
WizardStepTitleDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: WizardStepTitleDirective, selector: "ng-template[awStepTitle], ng-template[awWizardStepTitle]", ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardStepTitleDirective, decorators: [{
type: Directive,
args: [{
selector: 'ng-template[awStepTitle], ng-template[awWizardStepTitle]'
}]
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
/**
* Basic functionality every type of wizard step needs to provide
*
* @author Marc Arndt
*/
/* tslint:disable-next-line directive-class-suffix */
class WizardStep {
constructor() {
/**
* A symbol property, which contains an optional symbol for the step inside the navigation bar.
* Takes effect when `stepSymbolTemplate` is not defined or null.
*/
this.navigationSymbol = { symbol: '' };
/**
* A boolean describing if the wizard step is currently selected
*/
this.selected = false;
/**
* A boolean describing if the wizard step has been completed
*/
this.completed = false;
/**
* A boolean describing if the wizard step is shown as completed when the wizard is presented to the user
*
* Users will typically use `CompletedStepDirective` to set this flag
*/
this.initiallyCompleted = false;
/**
* A boolean describing if the wizard step is being edited after being competed
*
* This flag can only be true when `selected` is true.
*/
this.editing = false;
/**
* A boolean describing, if the wizard step should be selected by default, i.e. after the wizard has been initialized as the initial step
*/
this.defaultSelected = false;
/**
* A boolean describing if the wizard step is an optional step
*/
this.optional = false;
/**
* A function or boolean deciding, if this step can be entered
*/
this.canEnter = true;
/**
* A function or boolean deciding, if this step can be exited
*/
this.canExit = true;
/**
* This [[EventEmitter]] is called when the step is entered.
* The bound method should be used to do initialization work.
*/
this.stepEnter = new EventEmitter();
/**
* This [[EventEmitter]] is called when the step is exited.
* The bound method can be used to do cleanup work.
*/
this.stepExit = new EventEmitter();
}
/**
* Returns true if this wizard step should be visible to the user.
* If the step should be visible to the user false is returned, otherwise true
*/
get hidden() {
return !this.selected;
}
/**
* This method returns true, if this wizard step can be transitioned with a given direction.
* Transitioned in this case means either entered or exited, depending on the given `condition` parameter.
*
* @param condition A condition variable, deciding if the step can be transitioned
* @param direction The direction in which this step should be transitioned
* @returns A [[Promise]] containing `true`, if this step can transitioned in the given direction
* @throws An `Error` is thrown if `condition` is neither a function nor a boolean
*/
static canTransitionStep(condition, direction) {
if (typeof (condition) === typeof (true)) {
return Promise.resolve(condition);
}
else if (condition instanceof Function) {
return Promise.resolve(condition(direction));
}
else {
return Promise.reject(new Error(`Input value '${condition}' is neither a boolean nor a function`));
}
}
/**
* A function called when the step is entered
*
* @param direction The direction in which the step is entered
*/
enter(direction) {
this.stepEnter.emit(direction);
}
/**
* A function called when the step is exited
*
* @param direction The direction in which the step is exited
*/
exit(direction) {
this.stepExit.emit(direction);
}
/**
* This method returns true, if this wizard step can be entered from the given direction.
* Because this method depends on the value `canEnter`, it will throw an error, if `canEnter` is neither a boolean
* nor a function.
*
* @param direction The direction in which this step should be entered
* @returns A [[Promise]] containing `true`, if the step can be entered in the given direction, false otherwise
* @throws An `Error` is thrown if `anEnter` is neither a function nor a boolean
*/
canEnterStep(direction) {
return WizardStep.canTransitionStep(this.canEnter, direction);
}
/**
* This method returns true, if this wizard step can be exited into given direction.
* Because this method depends on the value `canExit`, it will throw an error, if `canExit` is neither a boolean
* nor a function.
*
* @param direction The direction in which this step should be left
* @returns A [[Promise]] containing `true`, if the step can be exited in the given direction, false otherwise
* @throws An `Error` is thrown if `canExit` is neither a function nor a boolean
*/
canExitStep(direction) {
return WizardStep.canTransitionStep(this.canExit, direction);
}
}
WizardStep.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardStep, deps: [], target: i0.ɵɵFactoryTarget.Directive });
WizardStep.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: WizardStep, inputs: { stepId: "stepId", stepTitle: "stepTitle", navigationSymbol: "navigationSymbol", canEnter: "canEnter", canExit: "canExit" }, outputs: { stepEnter: "stepEnter", stepExit: "stepExit" }, host: { properties: { "hidden": "this.hidden" } }, queries: [{ propertyName: "stepTitleTemplate", first: true, predicate: WizardStepTitleDirective, descendants: true }, { propertyName: "stepSymbolTemplate", first: true, predicate: WizardStepSymbolDirective, descendants: true }], ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardStep, decorators: [{
type: Directive
}], propDecorators: { stepTitleTemplate: [{
type: ContentChild,
args: [WizardStepTitleDirective]
}], stepSymbolTemplate: [{
type: ContentChild,
args: [WizardStepSymbolDirective]
}], stepId: [{
type: Input
}], stepTitle: [{
type: Input
}], navigationSymbol: [{
type: Input
}], canEnter: [{
type: Input
}], canExit: [{
type: Input
}], stepEnter: [{
type: Output
}], stepExit: [{
type: Output
}], hidden: [{
type: HostBinding,
args: ['hidden']
}] } });
/**
* Basic functionality every wizard completion step needs to provide
*
* @author Marc Arndt
*/
/* tslint:disable-next-line directive-class-suffix */
class WizardCompletionStep extends WizardStep {
constructor() {
super(...arguments);
/**
* @inheritDoc
*/
this.stepExit = new EventEmitter();
/**
* @inheritDoc
*/
this.canExit = false;
}
/**
* @inheritDoc
*/
enter(direction) {
this.completed = true;
this.stepEnter.emit(direction);
}
/**
* @inheritDoc
*/
exit(direction) {
// set this completion step as incomplete (unless it happens to be initiallyCompleted)
this.completed = this.initiallyCompleted;
this.stepExit.emit(direction);
}
}
WizardCompletionStep.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardCompletionStep, deps: null, target: i0.ɵɵFactoryTarget.Directive });
WizardCompletionStep.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: WizardCompletionStep, usesInheritance: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardCompletionStep, decorators: [{
type: Directive
}] });
/**
* The `aw-wizard-completion-step` component can be used to define a completion/success step at the end of your wizard
* After a `aw-wizard-completion-step` has been entered, it has the characteristic that the user is blocked from
* leaving it again to a previous step.
* In addition entering a `aw-wizard-completion-step` automatically sets the `aw-wizard` and all steps inside the `aw-wizard`
* as completed.
*
* ### Syntax
*
* ```html
* <aw-wizard-completion-step [stepTitle]="title of the wizard step"
* [navigationSymbol]="{ symbol: 'navigation symbol', fontFamily: 'navigation symbol font family' }"
* (stepEnter)="event emitter to be called when the wizard step is entered"
* (stepExit)="event emitter to be called when the wizard step is exited">
* ...
* </aw-wizard-completion-step>
* ```
*
* ### Example
*
* ```html
* <aw-wizard-completion-step stepTitle="Step 1" [navigationSymbol]="{ symbol: '1' }">
* ...
* </aw-wizard-completion-step>
* ```
*
* With a navigation symbol from the `font-awesome` font:
*
* ```html
* <aw-wizard-completion-step stepTitle="Step 1" [navigationSymbol]="{ symbol: '', fontFamily: 'FontAwesome' }">
* ...
* </aw-wizard-completion-step>
* ```
*
* @author Marc Arndt
*/
class WizardCompletionStepComponent extends WizardCompletionStep {
}
WizardCompletionStepComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardCompletionStepComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
WizardCompletionStepComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WizardCompletionStepComponent, selector: "aw-wizard-completion-step", providers: [
{ provide: WizardStep, useExisting: forwardRef(() => WizardCompletionStepComponent) },
{ provide: WizardCompletionStep, useExisting: forwardRef(() => WizardCompletionStepComponent) }
], usesInheritance: true, ngImport: i0, template: "<ng-content></ng-content>\r\n" });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardCompletionStepComponent, decorators: [{
type: Component,
args: [{ selector: 'aw-wizard-completion-step', providers: [
{ provide: WizardStep, useExisting: forwardRef(() => WizardCompletionStepComponent) },
{ provide: WizardCompletionStep, useExisting: forwardRef(() => WizardCompletionStepComponent) }
], template: "<ng-content></ng-content>\r\n" }]
}] });
const WIZARD_TOKEN = new InjectionToken('WIZARD_TOKEN');
/**
* Checks whether the given `value` implements the interface [[StepId]].
*
* @param value The value to be checked
* @returns True if the given value implements [[StepId]] and false otherwise
*/
function isStepId(value) {
return value.hasOwnProperty('stepId') && !(value instanceof WizardStep);
}
/**
* Checks whether the given `value` implements the interface [[StepIndex]].
*
* @param value The value to be checked
* @returns True if the given value implements [[StepIndex]] and false otherwise
*/
function isStepIndex(value) {
return value.hasOwnProperty('stepIndex');
}
/**
* Checks whether the given `value` implements the interface [[StepOffset]].
*
* @param value The value to be checked
* @returns True if the given value implements [[StepOffset]] and false otherwise
*/
function isStepOffset(value) {
return value.hasOwnProperty('stepOffset');
}
/**
* The `awGoToStep` directive can be used to navigate to a given step.
* This step can be defined in one of multiple formats
*
* ### Syntax
*
* With absolute step index:
*
* ```html
* <button [awGoToStep]="{ stepIndex: absolute step index }" (finalize)="finalize method">...</button>
* ```
*
* With unique step id:
*
* ```html
* <button [awGoToStep]="{ stepId: 'step id of destination step' }" (finalize)="finalize method">...</button>
* ```
*
* With a wizard step object:
*
* ```html
* <button [awGoToStep]="wizard step object" (finalize)="finalize method">...</button>
* ```
*
* With an offset to the defining step:
*
* ```html
* <button [awGoToStep]="{ stepOffset: offset }" (finalize)="finalize method">...</button>
* ```
*
* @author Marc Arndt
*/
class GoToStepDirective {
/**
* Constructor
*
* @param wizard The wizard component
* @param wizardStep The wizard step, which contains this [[GoToStepDirective]]
*/
constructor(wizard, wizardStep) {
this.wizard = wizard;
this.wizardStep = wizardStep;
/**
* This [[EventEmitter]] is called directly before the current step is exited during a transition through a component with this directive.
*/
this.preFinalize = new EventEmitter();
/**
* This [[EventEmitter]] is called directly after the current step is exited during a transition through a component with this directive.
*/
this.postFinalize = new EventEmitter();
}
/**
* A convenience field for `preFinalize`
*/
get finalize() {
return this.preFinalize;
}
/**
* A convenience name for `preFinalize`
*
* @param emitter The [[EventEmitter]] to be set
*/
set finalize(emitter) {
/* istanbul ignore next */
this.preFinalize = emitter;
}
/**
* Returns the destination step of this directive as an absolute step index inside the wizard
*
* @returns The index of the destination step
* @throws If `targetStep` is of an unknown type an `Error` is thrown
*/
get destinationStep() {
let destinationStep;
if (isStepIndex(this.targetStep)) {
destinationStep = this.targetStep.stepIndex;
}
else if (isStepId(this.targetStep)) {
destinationStep = this.wizard.getIndexOfStepWithId(this.targetStep.stepId);
}
else if (isStepOffset(this.targetStep) && this.wizardStep !== null) {
destinationStep = this.wizard.getIndexOfStep(this.wizardStep) + this.targetStep.stepOffset;
}
else if (this.targetStep instanceof WizardStep) {
destinationStep = this.wizard.getIndexOfStep(this.targetStep);
}
else {
throw new Error(`Input 'targetStep' is neither a WizardStep, StepOffset, StepIndex or StepId`);
}
return destinationStep;
}
/**
* Listener method for `click` events on the component with this directive.
* After this method is called the wizard will try to transition to the `destinationStep`
*/
onClick() {
this.wizard.goToStep(this.destinationStep, this.preFinalize, this.postFinalize);
}
}
GoToStepDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GoToStepDirective, deps: [{ token: WIZARD_TOKEN }, { token: WizardStep, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
GoToStepDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: GoToStepDirective, selector: "[awGoToStep]", inputs: { targetStep: ["awGoToStep", "targetStep"] }, outputs: { preFinalize: "preFinalize", postFinalize: "postFinalize", finalize: "finalize" }, host: { listeners: { "click": "onClick()" } }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GoToStepDirective, decorators: [{
type: Directive,
args: [{
selector: '[awGoToStep]'
}]
}], ctorParameters: function () {
return [{ type: undefined, decorators: [{
type: Inject,
args: [WIZARD_TOKEN]
}] }, { type: WizardStep, decorators: [{
type: Optional
}] }];
}, propDecorators: { preFinalize: [{
type: Output
}], postFinalize: [{
type: Output
}], targetStep: [{
type: Input,
args: ['awGoToStep']
}], finalize: [{
type: Output
}], onClick: [{
type: HostListener,
args: ['click']
}] } });
/**
* The `aw-wizard-navigation-bar` component contains the navigation bar inside a [[WizardComponent]].
* To correctly display the navigation bar, it's required to set the right css classes for the navigation bar,
* otherwise it will look like a normal `ul` component.
*
* ### Syntax
*
* ```html
* <aw-wizard-navigation-bar></aw-wizard-navigation-bar>
* ```
*
* @author Marc Arndt
*/
class WizardNavigationBarComponent {
/**
* Constructor
*
* @param wizard The state the wizard currently resides in
*/
constructor(wizard) {
this.wizard = wizard;
}
/**
* Returns all [[WizardStep]]s contained in the wizard
*
* @returns An array containing all [[WizardStep]]s
*/
get wizardSteps() {
switch (this.wizard.navBarDirection) {
case 'right-to-left':
return this.wizard.wizardSteps.slice().reverse();
case 'left-to-right':
default:
return this.wizard.wizardSteps;
}
}
/**
* Returns the number of wizard steps, that need to be displaced in the navigation bar
*
* @returns The number of wizard steps to be displayed
*/
get numberOfWizardSteps() {
return this.wizard.wizardSteps.length;
}
/**
* Checks, whether a [[WizardStep]] can be marked as `current` in the navigation bar
*
* @param wizardStep The wizard step to be checked
* @returns True if the step can be marked as `current`
*/
isCurrent(wizardStep) {
return wizardStep.selected;
}
/**
* Checks, whether a [[WizardStep]] can be marked as `editing` in the navigation bar
*
* @param wizardStep The wizard step to be checked
* @returns True if the step can be marked as `editing`
*/
isEditing(wizardStep) {
return wizardStep.editing;
}
/**
* Checks, whether a [[WizardStep]] can be marked as `done` in the navigation bar
*
* @param wizardStep The wizard step to be checked
* @returns True if the step can be marked as `done`
*/
isDone(wizardStep) {
return wizardStep.completed;
}
/**
* Checks, whether a [[WizardStep]] can be marked as `optional` in the navigation bar
*
* @param wizardStep The wizard step to be checked
* @returns True if the step can be marked as `optional`
*/
isOptional(wizardStep) {
return wizardStep.optional;
}
/**
* Checks, whether a [[WizardStep]] can be marked as `completed` in the navigation bar.
*
* The `completed` class is only applied to completion steps.
*
* @param wizardStep The wizard step to be checked
* @returns True if the step can be marked as `completed`
*/
isCompleted(wizardStep) {
return wizardStep instanceof WizardCompletionStep && this.wizard.completed;
}
/**
* Checks, whether a [[WizardStep]] can be marked as `navigable` in the navigation bar.
* A wizard step can be navigated to if:
* - the step is currently not selected
* - the navigation bar isn't disabled
* - the navigation mode allows navigation to the step
*
* @param wizardStep The wizard step to be checked
* @returns True if the step can be marked as navigable
*/
isNavigable(wizardStep) {
return !wizardStep.selected && !this.wizard.disableNavigationBar &&
this.wizard.isNavigable(this.wizard.getIndexOfStep(wizardStep));
}
}
WizardNavigationBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardNavigationBarComponent, deps: [{ token: WIZARD_TOKEN }], target: i0.ɵɵFactoryTarget.Component });
WizardNavigationBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WizardNavigationBarComponent, selector: "aw-wizard-navigation-bar", ngImport: i0, template: "<ul class=\"steps-indicator steps-{{numberOfWizardSteps}}\">\r\n <li [attr.id]=\"step.stepId\" *ngFor=\"let step of wizardSteps\" [ngClass]=\"{\r\n 'current': isCurrent(step),\r\n 'editing': isEditing(step),\r\n 'done': isDone(step),\r\n 'optional': isOptional(step),\r\n 'completed': isCompleted(step),\r\n 'navigable': isNavigable(step)\r\n }\">\r\n <a [awGoToStep]=\"step\">\r\n <div class=\"label\">\r\n <ng-container *ngIf=\"step.stepTitleTemplate\" [ngTemplateOutlet]=\"step.stepTitleTemplate.templateRef\"\r\n [ngTemplateOutletContext]=\"{wizardStep: step}\"></ng-container>\r\n <ng-container *ngIf=\"!step.stepTitleTemplate\">{{step.stepTitle}}</ng-container>\r\n </div>\r\n <div class=\"step-indicator\"\r\n [ngStyle]=\"{ 'font-family': step.stepSymbolTemplate ? '' : step.navigationSymbol.fontFamily }\">\r\n <ng-container *ngIf=\"step.stepSymbolTemplate\" [ngTemplateOutlet]=\"step.stepSymbolTemplate.templateRef\"\r\n [ngTemplateOutletContext]=\"{wizardStep: step}\"></ng-container>\r\n <ng-container *ngIf=\"!step.stepSymbolTemplate\">{{step.navigationSymbol.symbol}}</ng-container>\r\n </div>\r\n </a>\r\n </li>\r\n</ul>\r\n", dependencies: [{ 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: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: GoToStepDirective, selector: "[awGoToStep]", inputs: ["awGoToStep"], outputs: ["preFinalize", "postFinalize", "finalize"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardNavigationBarComponent, decorators: [{
type: Component,
args: [{ selector: 'aw-wizard-navigation-bar', template: "<ul class=\"steps-indicator steps-{{numberOfWizardSteps}}\">\r\n <li [attr.id]=\"step.stepId\" *ngFor=\"let step of wizardSteps\" [ngClass]=\"{\r\n 'current': isCurrent(step),\r\n 'editing': isEditing(step),\r\n 'done': isDone(step),\r\n 'optional': isOptional(step),\r\n 'completed': isCompleted(step),\r\n 'navigable': isNavigable(step)\r\n }\">\r\n <a [awGoToStep]=\"step\">\r\n <div class=\"label\">\r\n <ng-container *ngIf=\"step.stepTitleTemplate\" [ngTemplateOutlet]=\"step.stepTitleTemplate.templateRef\"\r\n [ngTemplateOutletContext]=\"{wizardStep: step}\"></ng-container>\r\n <ng-container *ngIf=\"!step.stepTitleTemplate\">{{step.stepTitle}}</ng-container>\r\n </div>\r\n <div class=\"step-indicator\"\r\n [ngStyle]=\"{ 'font-family': step.stepSymbolTemplate ? '' : step.navigationSymbol.fontFamily }\">\r\n <ng-container *ngIf=\"step.stepSymbolTemplate\" [ngTemplateOutlet]=\"step.stepSymbolTemplate.templateRef\"\r\n [ngTemplateOutletContext]=\"{wizardStep: step}\"></ng-container>\r\n <ng-container *ngIf=\"!step.stepSymbolTemplate\">{{step.navigationSymbol.symbol}}</ng-container>\r\n </div>\r\n </a>\r\n </li>\r\n</ul>\r\n" }]
}], ctorParameters: function () {
return [{ type: undefined, decorators: [{
type: Inject,
args: [WIZARD_TOKEN]
}] }];
} });
/**
* The `aw-wizard-step` component is used to define a normal step inside a wizard.
*
* ### Syntax
*
* With `stepTitle` and `navigationSymbol` inputs:
*
* ```html
* <aw-wizard-step [stepTitle]="step title" [navigationSymbol]="{ symbol: 'symbol', fontFamily: 'font-family' }"
* [canExit]="deciding function" (stepEnter)="enter function" (stepExit)="exit function">
* ...
* </aw-wizard-step>
* ```
*
* With `awWizardStepTitle` and `awWizardStepSymbol` directives:
*
* ```html
* <aw-wizard-step"
* [canExit]="deciding function" (stepEnter)="enter function" (stepExit)="exit function">
* <ng-template awWizardStepTitle>
* step title
* </ng-template>
* <ng-template awWizardStepSymbol>
* symbol
* </ng-template>
* ...
* </aw-wizard-step>
* ```
*
* ### Example
*
* With `stepTitle` and `navigationSymbol` inputs:
*
* ```html
* <aw-wizard-step stepTitle="Address information" [navigationSymbol]="{ symbol: '', fontFamily: 'FontAwesome' }">
* ...
* </aw-wizard-step>
* ```
*
* With `awWizardStepTitle` and `awWizardStepSymbol` directives:
*
* ```html
* <aw-wizard-step>
* <ng-template awWizardStepTitle>
* Address information
* </ng-template>
* <ng-template awWizardStepSymbol>
* <i class="fa fa-taxi"></i>
* </ng-template>
* </aw-wizard-step>
* ```
*
* @author Marc Arndt
*/
class WizardStepComponent extends WizardStep {
}
WizardStepComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardStepComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
WizardStepComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WizardStepComponent, selector: "aw-wizard-step", providers: [
{ provide: WizardStep, useExisting: forwardRef(() => WizardStepComponent) }
], usesInheritance: true, ngImport: i0, template: "<ng-content></ng-content>\r\n" });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WizardStepComponent, decorators: [{
type: Component,
args: [{ selector: 'aw-wizard-step', providers: [
{ provide: WizardStep, useExisting: forwardRef(() => WizardStepComponent) }
], template: "<ng-content></ng-content>\r\n" }]
}] });
/**
* The direction in which a step transition was made
*
* @author Marc Arndt
*/
/**
* This enum contains the different possible moving directions in which a wizard can be traversed
*
* @author Marc Arndt
*/
var MovingDirection;
(function (MovingDirection) {
/**
* A forward step transition
*/
MovingDirection[MovingDirection["Forwards"] = 0] = "Forwards";
/**
* A backward step transition
*/
MovingDirection[MovingDirection["Backwards"] = 1] = "Backwards";
/**
* No step transition was done
*/
MovingDirection[MovingDirection["Stay"] = 2] = "Stay";
})(MovingDirection || (MovingDirection = {}));
/**
* Base implementation of [[NavigationMode]]
*
* Note: Built-in [[NavigationMode]] classes should be stateless, allowing the library user to easily create
* an instance of a particular [[NavigationMode]] class and pass it to `<aw-wizard [navigationMode]="...">`.
*
* @author Marc Arndt
*/
class BaseNavigationMode {
/**
* Checks, whether a wizard step, as defined by the given destination index, can be transitioned to.
*
* This method controls navigation by [[goToStep]], [[goToPreviousStep]], and [[goToNextStep]] directives.
* Navigation by navigation bar is governed by [[isNavigable]].
*
* In this implementation, a destination wizard step can be entered if:
* - it exists
* - the current step can be exited in the direction of the destination step
* - the destination step can be entered in the direction from the current step
*
* Subclasses can impose additional restrictions, see [[canTransitionToStep]].
*
* @param wizard The wizard component to operate on
* @param destinationIndex The index of the destination step
* @returns A [[Promise]] containing `true`, if the destination step can be transitioned to and `false` otherwise
*/
canGoToStep(wizard, destinationIndex) {
const hasStep = wizard.hasStep(destinationIndex);
const movingDirection = wizard.getMovingDirection(destinationIndex);
const canExitCurrentStep = (previous) => {
return previous && wizard.currentStep.canExitStep(movingDirection);
};
const canEnterDestinationStep = (previous) => {
return previous && wizard.getStepAtIndex(destinationIndex).canEnterStep(movingDirection);
};
const canTransitionToStep = (previous) => {
return previous && this.canTransitionToStep(wizard, destinationIndex);
};
return Promise.resolve(hasStep)
.then(canTransitionToStep)
// Apply user-defined checks at the end. They can involve user interaction
// which is better to be avoided if navigation mode does not actually allow the transition
// (`canTransitionToStep` returns `false`).
.then(canExitCurrentStep)
.then(canEnterDestinationStep);
}
/**
* Imposes additional restrictions for `canGoToStep` in current navigation mode.
*
* The base implementation allows transition iff the given step is navigable from the navigation bar (see `isNavigable`).
* However, in some navigation modes `canTransitionToStep` can be more relaxed to allow navigation to certain steps
* by previous/next buttons, but not using the navigation bar.
*
* @param wizard The wizard component to operate on
* @param destinationIndex The index of the destination step
* @returns `true`, if the destination step can be transitioned to and `false` otherwise
*/
canTransitionToStep(wizard, destinationIndex) {
return this.isNavigable(wizard, destinationIndex);
}
/**
* Tries to transition to the wizard step, as denoted by the given destination index.
*
* When entering the destination step, the following actions are done:
* - the old current step is set as completed
* - the old current step is set as unselected
* - the old current step is exited
* - the destination step is set as selected
* - the destination step is entered
*
* When the destination step couldn't be entered, the following actions are done:
* - the current step is exited and entered in the direction `MovingDirection.Stay`
*
* @param wizard The wizard component to operate on
* @param destinationIndex The index of the destination wizard step, which should be entered
* @param preFinalize An event emitter, to be called before the step has been transitioned
* @param postFinalize An event emitter, to be called after the step has been transitioned
*/
goToStep(wizard, destinationIndex, preFinalize, postFinalize) {
this.canGoToStep(wizard, destinationIndex).then(navigationAllowed => {
if (navigationAllowed) {
// the current step can be exited in the given direction
const movingDirection = wizard.getMovingDirection(destinationIndex);
/* istanbul ignore if */
if (preFinalize) {
preFinalize.emit();
}
// leave current step
wizard.currentStep.completed = true;
wizard.currentStep.exit(movingDirection);
wizard.currentStep.editing = false;
wizard.currentStep.selected = false;
this.transition(wizard, destinationIndex);
// remember if the next step is already completed before entering it to properly set `editing` flag
const wasCompleted = wizard.completed || wizard.currentStep.completed;
// go to next step
wizard.currentStep.enter(movingDirection);
wizard.currentStep.selected = true;
if (wasCompleted) {
wizard.currentStep.editing = true;
}
/* istanbul ignore if */
if (postFinalize) {
postFinalize.emit();
}
}
else {
// if the current step can't be left, reenter the current step
wizard.currentStep.exit(MovingDirection.Stay);
wizard.currentStep.enter(MovingDirection.Stay);
}
});
}
/**
* Transitions the wizard to the given step index.
*
* Can perform additional actions in particular navigation mode implementations.
*
* @param wizard The wizard component to operate on
* @param destinationIndex The index of the destination wizard step
*/
transition(wizard, destinationIndex) {
wizard.currentStepIndex = destinationIndex;
}
/**
* Resets the state of this wizard.
*
* A reset transitions the wizard automatically to the first step and sets all steps as incomplete.
* In addition the whole wizard is set as incomplete.
*
* @param wizard The wizard component to operate on
*/
reset(wizard) {
this.ensureCanReset(wizard);
// reset the step internal state
wizard.wizardSteps.forEach(step => {
step.completed = step.initiallyCompleted;
step.selected = false;
step.editing = false;
});
// set the first step as the current step
wizard.currentStepIndex = wizard.defaultStepIndex;
wizard.currentStep.selected = true;
wizard.currentStep.enter(MovingDirection.Forwards);
}
/**
* Checks if wizard configuration allows to perform reset.
*
* A check failure is indicated by throwing an `Error` with the message discribing the discovered misconfiguration issue.
*
* Can include additional checks in particular navigation mode implementations.
*
* @param wizard The wizard component to operate on
* @throws An `Error` is thrown, if a micconfiguration issue is discovered.
*/
ensureCanReset(wizard) {
// the wizard doesn't contain a step with the default step index
if (!wizard.hasStep(wizard.defaultStepIndex)) {
throw new Error(`The wizard doesn't contain a step with index ${wizard.defaultStepIndex}`);
}
}
}
/**
* The default navigation mode used by [[WizardComponent]] and [[NavigationModeDirective]].
*
* It is parameterized with two navigation policies passed to constructor:
*
* - [[navigateBackward]] policy controls whether wizard steps before the current step are navigable:
*
* - `"deny"` -- the steps are not navigable
* - `"allow"` -- the steps are navigable
* - If the corresponding constructor argument is omitted or is `null` or `undefined`,
* then the default value is applied which is `"deny"`
*
* - [[navigateForward]] policy controls whether wizard steps after the current step are navigable:
*
* - `"deny"` -- the steps are not navigable
* - `"allow"` -- the steps are navigable
* - `"visited"` -- a step is navigable iff it was already visited before
* - If the corresponding constructor argument is omitted or is `null` or `undefined`,
* then the default value is applied which is `"allow"`
*/
class ConfigurableNavigationMode extends BaseNavigationMode {
/**
* Constructor
*
* @param navigateBackward Controls whether wizard steps before the current step are navigable
* @param navigateForward Controls whether wizard steps before the current step are navigable
*/
constructor(navigateBackward = null, navigateForward = null) {
super();
this.navigateBackward = navigateBackward;
this.navigateForward = navigateForward;
this.navigateBackward = this.navigateBackward || 'allow';
this.navigateForward = this.navigateForward || 'deny';
}
/**
* @inheritDoc
*/
canTransitionToStep(wizard, destinationIndex) {
// if the destination step can be navigated to using the navigation bar,
// it should be accessible with [goToStep] as well
if (this.isNavigable(wizard, destinationIndex)) {
return true;
}
// navigation with [goToStep] is permitted if all previous steps
// to the destination step have been completed or are optional
return wizard.wizardSteps
.filter((step, index) => index < destinationIndex && index !== wizard.currentStepIndex)
.every(step => step.completed || step.optional);
}
/**
* @inheritDoc
*/
transition(wizard, destinationIndex) {
if (this.navigateForward === 'deny') {
// set all steps after the destination step to incomplete
wizard.wizardSteps
.filter((step, index) => wizard.currentStepIndex > destinationIndex && index > destinationIndex)
.forEach(step => step.completed = false);
}
super.transition(wizard, destinationIndex);
}
/**
* @inheritDoc
*/
isNavigable(wizard, destinationIndex) {
// Check if the destination step can be navigated to
const destinationStep = wizard.getStepAtIndex(destinationIndex);
if (destinationStep instanceof WizardCompletionStep) {
// A completion step can only be entered, if all previous steps have been completed, are optional, or selected
const previousStepsCompleted = wizard.wizardSteps
.filter((step, index) => index < destinationIndex)
.every(step => step.completed || step.optional || step.selected);
if (!previousStepsCompleted) {
return false;
}
}
// Apply navigation pocicies
if (destinationIndex < wizard.currentStepIndex) {
// If the destination step is before current, apply the `navigateBackward` policy
switch (this.navigateBackward) {
case 'allow': return true;
case 'deny': return false;
default:
throw new Error(`Invalid value for navigateBackward: ${this.navigateBackward}`);
}
}
else if (destinationIndex > wizard.currentStepIndex) {
// If the destination step is after current, apply the `navigateForward` policy
switch (this.navigateForward) {
case 'allow': return true;
case 'deny': return false;
case 'visited': return destinationStep.completed;
default:
throw new Error(`Invalid value for navigateForward: ${this.navigateForward}`);
}
}
else {
// Re-entering the current step is not allowed
return false;
}
}
/**
* @inheritDoc
*/
ensureCanReset(wizard) {
super.ensureCanReset(wizard);
// the default step is a completion step and the wizard contains more than one step
const defaultWizardStep = wizard.getStepAtIndex(wizard.defaultStepIndex);
const defaultCompletionStep = defaultWizardStep instanceof WizardCompletionStep;
if (defaultCompletionStep && wizard.wizardSteps.length !== 1) {
throw new Error(`The default step index ${wizard.defaultStepIndex} references a completion step`);
}
}
}
/**
* The `aw-wizard` component defines the root component of a wizard.
* Through the setting of input parameters for the `aw-wizard` component it's possible to change the location and size
* of its navigation bar.
*
* ### Syntax
* ```html
* <aw-wizard [navBarLocation]="location of navigation bar" [navBarLayout]="layout of navigation bar">
* ...
* </aw-wizard>
* ```
*
* ### Example
*
* Without completion step:
*
* ```html
* <aw-wizard navBarLocation="top" navBarLayout="small">
* <aw-wizard-step>...</aw-wizard-step>
* <aw-wizard-step>...</aw-wizard-step>
* </aw-wizard>
* ```
*
* With completion step:
*
* ```html
* <aw-wizard navBarLocation="top" navBarLayout="small">
* <aw-wizard-step>...</aw-wizard-step>
* <aw-wizard-step>...</aw-wizard-step>
* <aw-wizard-completion-step>...</aw-wizard-completion-step>
* </aw-wizard>
* ```
*
* @author Marc Arndt
*/
class WizardComponent {
/**
* The initially selected step, represented by its index
* Beware: This initial default is only used if no wizard step has been enhanced with the `selected` directive
*/
get defaultStepIndex() {
// This value can be either:
// - the index of a wizard step with a `selected` directive, or
// - the default step index, set in the [[WizardComponent]]
const foundDefaultStep = this.wizardSteps.find(step => step.defaultSelected);
if (foundDefaultStep) {
return this.getIndexOfStep(foundDefaultStep);
}
else {
return this._defaultStepIndex;
}
}
set defaultStepIndex(defaultStepIndex) {
this._defaultStepIndex = defaultStepIndex;
}
/**
* Constructor
*/
constructor() {
/**
* The location of the navigation bar inside the wizard.
* This location can be either top, bottom, left or right
*/
this.navBarLocation = 'top';
/**
* The layout of the navigation bar inside the wizard.
* The layout can be either small, large-filled, large-empty or large-symbols
*/
this.navBarLayout = 'small';
/**
* The direction in which the steps inside the navigation bar should be shown.
* The direction can be either `left-to-right` or `right-to-left`
*/
this.navBarDirection = 'left-to-right';
this._defaultStepIndex = 0;
/**
* True, if the navigation bar shouldn't be used for navigating
*/
this.disableNavigationBar = false;
/**
* The navigation mode used to navigate inside the wizard
*
* For outside access, use the [[navigation]] getter.
*/
this._navigation = new ConfigurableNavigationMode();
/**
* An array representation of all wizard steps belonging to this model
*
* For outside access, use the [[wizardSteps]] getter.
*/
this._wizardSteps = [];
/**
* The index of the currently visible and selected step inside the wizardSteps QueryList.
* If this wizard contains no steps, currentStepIndex is -1
*
* Note: Do not modify this field directly. Instead, use navigation methods:
* [[goToStep]], [[goToPreviousStep]], [[goToNextStep]].
*/
this.currentStepIndex = -1;
}
/**
* Returns true if this wizard uses a horizontal orientation.
* The wizard uses a horizontal orientation, iff the navigation bar is shown at the top or bottom of this wizard
*
* @returns True if this wizard uses a horizontal orientation
*/
get horizontalOrientation() {
return this.navBarLocation === 'top' || this.navBarLocation === 'bottom';
}
/**
* Returns true if this wizard uses a vertical orientation.
* The wizard uses a vertical orientation, iff the navigation bar is shown at the left or right of this wizard
*
* @returns True if this wizard uses a vertical orientation
*/
get verticalOrientation() {
return this.navBarLocation === 'left' || this.navBarLocation === 'right';
}
/**
* Initialization work
*/
ngAfterContentInit() {
// add a subscriber to the wizard steps QueryList to listen to changes in the DOM
this.wizardStepsQueryList.changes.subscribe(changedWizardSteps => {
this.updateWizardSteps(changedWizardSteps.toArray());
});
// initialize the model
this.updateWizardSteps(this.wizardStepsQueryList.toArray());
// finally reset the whole wizard component
setTimeout(() => this.reset());
}
/**
* The WizardStep object belonging to the currently visible and selected step.
* The currentStep is always the currently selected wizard step.
* The currentStep can be either completed, if it was visited earlier,
* or not completed, if it is visited for the first time or its state is currently out of date.
*
* If this wizard contains no steps, currentStep is null
*/
get currentStep() {
if (this.hasStep(this.currentStepIndex)) {
return this.wizardSteps[this.currentStepIndex];
}
else {
return null;
}
}
/**
* The completeness of the wizard.
* If the wizard has been completed, i.e. all steps are either completed or optional, this value is true, otherwise it is false
*/
get completed() {
return this.wizardSteps.every(step => step.completed || step.optional);
}
/**
* An array representation of all wizard steps belonging to this model
*/
get wizardSteps() {
return this._wizardSteps;
}
/**
* Updates the wizard steps to the new array
*
* @param wizardSteps The updated wizard steps
*/
updateWizardSteps(wiz