@orchestrator/stepper
Version:
> A stepper component for Orchestrator library.
330 lines (319 loc) • 20.4 kB
JavaScript
import * as i2 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { Component, ChangeDetectionStrategy, Input, Injectable, NgModule } from '@angular/core';
import * as i1 from '@orchestrator/core';
import { Option, DynamicComponent, OrchestratorCoreModule, provideInjectorMap } from '@orchestrator/core';
import { __decorate, __metadata } from 'tslib';
import { trigger, transition, style, query, animateChild, group, animate } from '@angular/animations';
class StepConfig {
constructor() {
this.header = true;
this.footer = true;
}
}
__decorate([
Option({ required: true }),
__metadata("design:type", String)
], StepConfig.prototype, "id", void 0);
__decorate([
Option(),
__metadata("design:type", String)
], StepConfig.prototype, "name", void 0);
__decorate([
Option(),
__metadata("design:type", Object)
], StepConfig.prototype, "header", void 0);
__decorate([
Option(),
__metadata("design:type", Object)
], StepConfig.prototype, "footer", void 0);
let StepHostComponent = class StepHostComponent {
};
/** @nocollapse */ /** @nocollapse */ StepHostComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ /** @nocollapse */ StepHostComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: StepHostComponent, selector: "orc-step-host", inputs: { items: "items" }, ngImport: i0, template: "<orc-render-item *ngIf=\"items\" [item]=\"items[0]\"></orc-render-item>\n", styles: [""], components: [{ type: i1.RenderItemComponent, selector: "orc-render-item", inputs: ["item", "context"], outputs: ["componentCreated", "childComponentsCreated"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
StepHostComponent = __decorate([
DynamicComponent({ config: StepConfig })
], StepHostComponent);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepHostComponent, decorators: [{
type: Component,
args: [{ selector: 'orc-step-host', changeDetection: ChangeDetectionStrategy.OnPush, template: "<orc-render-item *ngIf=\"items\" [item]=\"items[0]\"></orc-render-item>\n", styles: [""] }]
}], propDecorators: { items: [{
type: Input
}] } });
class Stepper {
}
class StepperConfig {
}
/** @nocollapse */ /** @nocollapse */ StepperConfig.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepperConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
/** @nocollapse */ /** @nocollapse */ StepperConfig.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepperConfig });
__decorate([
Option(),
__metadata("design:type", Boolean)
], StepperConfig.prototype, "loopSteps", void 0);
__decorate([
Option(),
__metadata("design:type", Object)
], StepperConfig.prototype, "header", void 0);
__decorate([
Option(),
__metadata("design:type", Object)
], StepperConfig.prototype, "footer", void 0);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepperConfig, decorators: [{
type: Injectable
}], propDecorators: { loopSteps: [], header: [], footer: [] } });
function getStepAnimation(name) {
return [
trigger(`${name}Backward`, [stepAnimationTransition(name, false)]),
trigger(`${name}Forward`, [stepAnimationTransition(name, true)]),
trigger(`${name}Prev`, []),
trigger(`${name}Next`, []),
];
}
function stepAnimationTransition(name, forwards) {
return transition('* <=> *', [
// Initial state
style({
position: 'relative',
display: 'flex',
overflow: 'hidden',
'flex-direction': 'row',
'flex-wrap': 'nowrap',
}),
query(`@${name}Prev, @${name}Next`, [
style({
width: '100%',
'flex-shrink': 0,
'will-change': 'transform',
}),
]),
query(`@${name}Prev`, [style({ position: 'absolute', top: 0 }), animateChild()], { optional: true }),
query(`@${name}Next`, style({ transform: `translateX(${forwards ? '' : '-'}100%)` })),
// Transition
group([
query(`@${name}Prev`, animate('300ms ease-out', style({ transform: `translateX(${forwards ? '-' : ''}100%)` })), { optional: true }),
query(`@${name}Next`, animate('300ms ease-out', style({ transform: 'translateX(0)' }))),
]),
query(`@${name}Next`, animateChild()),
]);
}
class StepperComponent {
constructor(cdr) {
this.cdr = cdr;
this.steps = [];
this.initialStep = 0;
this.loop = false;
this.goingBack = false;
this.animationHeader = {
curr: false,
prev: false,
animate: false,
shouldAnimate: () => this.doAnimateHeader(),
};
this.animationContent = {
curr: false,
prev: false,
animate: false,
shouldAnimate: () => this.doAnimateContent(),
};
this.animationFooter = {
curr: false,
prev: false,
animate: false,
shouldAnimate: () => this.doAnimateFooter(),
};
this.animations = [
this.animationHeader,
this.animationContent,
this.animationFooter,
];
}
get stepsCount() {
return this.steps ? this.steps.length : 0;
}
get hideHeader() {
return this.isHeaderHidden(this.currentStep);
}
get headerItem() {
if (this.hideHeader) {
return;
}
const header = this.currentStep.config.header;
return typeof header === 'object' ? header : this.header;
}
get hideFooter() {
return this.isFooterHidden(this.currentStep);
}
get footerItem() {
if (this.hideFooter) {
return;
}
const footer = this.currentStep.config.footer;
return typeof footer === 'object' ? footer : this.footer;
}
ngOnInit() {
if (this.steps) {
this.activateStep(this.initialStep);
}
}
ngOnChanges(changes) {
if ('steps' in changes) {
this.activateStep(this.currentStepIdx != null ? this.currentStepIdx : this.initialStep);
}
}
async goTo(offsetOrId, stepData) {
if (typeof offsetOrId === 'number') {
return await this.jumpSteps(offsetOrId, stepData);
}
else {
return await this.toStep(offsetOrId, stepData);
}
}
async goNext(stepData) {
return await this.goTo(1, stepData);
}
async goBack(stepData) {
return await this.goTo(-1, stepData);
}
async goToStart(stepData) {
return await this.activateStep(0, stepData);
}
async goToEnd(stepData) {
return await this.activateStep(this.steps.length - 1, stepData);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async activateStep(idx, stepData) {
// Bounds normalization
if (idx >= this.steps.length) {
idx = this.loop ? idx % this.steps.length : this.steps.length - 1;
}
else if (idx < 0) {
idx = this.loop ? idx + this.steps.length : 0;
}
if (idx === this.currentStepIdx) {
return;
}
// TODO(gund): do something with stepData...
this.goingBack = this.currentStepIdx > idx;
this.prevStep = this.currentStep;
this.currentStep = this.steps[idx];
this.currentStepIdx = idx;
this.updateAnimations();
this.cdr.markForCheck();
}
cleanupPrevStep() {
this.prevStep = undefined;
}
async toStep(id, stepData) {
const idx = this.steps.findIndex((step) => step.config.id === id);
if (idx !== -1) {
return await this.activateStep(idx, stepData);
}
}
async jumpSteps(n, stepData) {
return await this.activateStep(this.currentStepIdx + n, stepData);
}
updateAnimations() {
this.animations.forEach((animation) => {
animation.animate = animation.shouldAnimate();
if (animation.animate) {
if (this.goingBack) {
animation.prev = !animation.prev;
}
else {
animation.curr = !animation.curr;
}
}
});
}
doAnimateHeader() {
return (!!this.currentStep &&
!!this.prevStep &&
this.isHeaderHidden(this.currentStep) !==
this.isHeaderHidden(this.prevStep));
}
doAnimateContent() {
return !!this.currentStep && !!this.prevStep;
}
doAnimateFooter() {
return (!!this.currentStep &&
!!this.prevStep &&
this.isFooterHidden(this.currentStep) !==
this.isFooterHidden(this.prevStep));
}
isHeaderHidden(step) {
return 'header' in step.config && !step.config.header;
}
isFooterHidden(step) {
return 'footer' in step.config && !step.config.footer;
}
}
/** @nocollapse */ /** @nocollapse */ StepperComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepperComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ /** @nocollapse */ StepperComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: StepperComponent, selector: "orc-stepper", inputs: { steps: "steps", header: "header", footer: "footer", initialStep: "initialStep", loop: "loop" }, providers: [{ provide: Stepper, useExisting: StepperComponent }], usesOnChanges: true, ngImport: i0, template: "<div class=\"step-wrapper\">\n <div class=\"step\">\n <div class=\"step-header-wrapper\">\n <ng-container\n *ngTemplateOutlet=\"\n renderStepTpl;\n context: {\n $implicit: stepHeader,\n animation: animationHeader\n }\n \"\n ></ng-container>\n </div>\n <div class=\"step-content-wrapper\">\n <ng-container\n *ngTemplateOutlet=\"\n renderStepTpl;\n context: {\n $implicit: stepContent,\n animation: animationContent\n }\n \"\n ></ng-container>\n </div>\n <div class=\"step-footer-wrapper\">\n <ng-container\n *ngTemplateOutlet=\"\n renderStepTpl;\n context: {\n $implicit: stepFooter,\n animation: animationFooter\n }\n \"\n ></ng-container>\n </div>\n </div>\n</div>\n\n<ng-template #renderStepTpl let-tpl let-animation=\"animation\">\n <div\n [@stepAnimationForward]=\"animation.curr\"\n [@stepAnimationBackward]=\"animation.prev\"\n (@stepAnimationForward.done)=\"cleanupPrevStep()\"\n (@stepAnimationBackward.done)=\"cleanupPrevStep()\"\n >\n <div *ngIf=\"animation.animate\" @stepAnimationPrev>\n <ng-container\n *ngTemplateOutlet=\"tpl; context: { $implicit: prevStep }\"\n ></ng-container>\n </div>\n <div @stepAnimationNext>\n <ng-container\n *ngTemplateOutlet=\"tpl; context: { $implicit: currentStep }\"\n ></ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #stepHeader let-step>\n <div *ngIf=\"step && !hideHeader\" class=\"step-header\">\n <orc-render-item\n *ngIf=\"headerItem; else defaultHeader\"\n [item]=\"headerItem\"\n [context]=\"step\"\n ></orc-render-item>\n <ng-template #defaultHeader>{{ step.config.name }}</ng-template>\n </div>\n</ng-template>\n\n<ng-template #stepContent let-step>\n <div *ngIf=\"step\" class=\"step-content\">\n <orc-render-item [item]=\"step\"></orc-render-item>\n </div>\n</ng-template>\n\n<ng-template #stepFooter let-step>\n <div *ngIf=\"step && !hideFooter\" class=\"step-footer\">\n <orc-render-item\n *ngIf=\"footerItem; else defaultFooter\"\n [item]=\"footerItem\"\n [context]=\"step\"\n ></orc-render-item>\n <ng-template #defaultFooter>\n <button type=\"button\" class=\"step-footer--prev\" (click)=\"goBack()\">\n Prev\n </button>\n <button type=\"button\" class=\"step-footer--next\" (click)=\"goNext()\">\n Next\n </button>\n </ng-template>\n </div>\n</ng-template>\n", styles: [""], components: [{ type: i1.RenderItemComponent, selector: "orc-render-item", inputs: ["item", "context"], outputs: ["componentCreated", "childComponentsCreated"] }], directives: [{ type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], animations: [...getStepAnimation('stepAnimation')], changeDetection: i0.ChangeDetectionStrategy.OnPush });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepperComponent, decorators: [{
type: Component,
args: [{ selector: 'orc-stepper', changeDetection: ChangeDetectionStrategy.OnPush, animations: [...getStepAnimation('stepAnimation')], providers: [{ provide: Stepper, useExisting: StepperComponent }], template: "<div class=\"step-wrapper\">\n <div class=\"step\">\n <div class=\"step-header-wrapper\">\n <ng-container\n *ngTemplateOutlet=\"\n renderStepTpl;\n context: {\n $implicit: stepHeader,\n animation: animationHeader\n }\n \"\n ></ng-container>\n </div>\n <div class=\"step-content-wrapper\">\n <ng-container\n *ngTemplateOutlet=\"\n renderStepTpl;\n context: {\n $implicit: stepContent,\n animation: animationContent\n }\n \"\n ></ng-container>\n </div>\n <div class=\"step-footer-wrapper\">\n <ng-container\n *ngTemplateOutlet=\"\n renderStepTpl;\n context: {\n $implicit: stepFooter,\n animation: animationFooter\n }\n \"\n ></ng-container>\n </div>\n </div>\n</div>\n\n<ng-template #renderStepTpl let-tpl let-animation=\"animation\">\n <div\n [@stepAnimationForward]=\"animation.curr\"\n [@stepAnimationBackward]=\"animation.prev\"\n (@stepAnimationForward.done)=\"cleanupPrevStep()\"\n (@stepAnimationBackward.done)=\"cleanupPrevStep()\"\n >\n <div *ngIf=\"animation.animate\" @stepAnimationPrev>\n <ng-container\n *ngTemplateOutlet=\"tpl; context: { $implicit: prevStep }\"\n ></ng-container>\n </div>\n <div @stepAnimationNext>\n <ng-container\n *ngTemplateOutlet=\"tpl; context: { $implicit: currentStep }\"\n ></ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #stepHeader let-step>\n <div *ngIf=\"step && !hideHeader\" class=\"step-header\">\n <orc-render-item\n *ngIf=\"headerItem; else defaultHeader\"\n [item]=\"headerItem\"\n [context]=\"step\"\n ></orc-render-item>\n <ng-template #defaultHeader>{{ step.config.name }}</ng-template>\n </div>\n</ng-template>\n\n<ng-template #stepContent let-step>\n <div *ngIf=\"step\" class=\"step-content\">\n <orc-render-item [item]=\"step\"></orc-render-item>\n </div>\n</ng-template>\n\n<ng-template #stepFooter let-step>\n <div *ngIf=\"step && !hideFooter\" class=\"step-footer\">\n <orc-render-item\n *ngIf=\"footerItem; else defaultFooter\"\n [item]=\"footerItem\"\n [context]=\"step\"\n ></orc-render-item>\n <ng-template #defaultFooter>\n <button type=\"button\" class=\"step-footer--prev\" (click)=\"goBack()\">\n Prev\n </button>\n <button type=\"button\" class=\"step-footer--next\" (click)=\"goNext()\">\n Next\n </button>\n </ng-template>\n </div>\n</ng-template>\n", styles: [""] }]
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { steps: [{
type: Input
}], header: [{
type: Input
}], footer: [{
type: Input
}], initialStep: [{
type: Input
}], loop: [{
type: Input
}] } });
let StepperHostComponent = class StepperHostComponent {
};
/** @nocollapse */ /** @nocollapse */ StepperHostComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepperHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ /** @nocollapse */ StepperHostComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: StepperHostComponent, selector: "orc-stepper-host", inputs: { items: "items", config: "config" }, ngImport: i0, template: "<orc-stepper\n [steps]=\"items\"\n [header]=\"config?.header\"\n [footer]=\"config?.footer\"\n [loop]=\"config?.loopSteps\"\n></orc-stepper>\n", styles: [""], components: [{ type: StepperComponent, selector: "orc-stepper", inputs: ["steps", "header", "footer", "initialStep", "loop"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
StepperHostComponent = __decorate([
DynamicComponent({ config: StepperConfig })
], StepperHostComponent);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepperHostComponent, decorators: [{
type: Component,
args: [{ selector: 'orc-stepper-host', changeDetection: ChangeDetectionStrategy.OnPush, template: "<orc-stepper\n [steps]=\"items\"\n [header]=\"config?.header\"\n [footer]=\"config?.footer\"\n [loop]=\"config?.loopSteps\"\n></orc-stepper>\n", styles: [""] }]
}], propDecorators: { items: [{
type: Input
}], config: [{
type: Input
}] } });
class StepperModule {
static forRoot() {
return {
ngModule: StepperModule,
providers: [
...OrchestratorCoreModule.registerComponents([
StepperHostComponent,
StepHostComponent,
]),
provideInjectorMap({ Stepper: Stepper }),
],
};
}
}
/** @nocollapse */ /** @nocollapse */ StepperModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepperModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
/** @nocollapse */ /** @nocollapse */ StepperModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepperModule, declarations: [StepperHostComponent, StepperComponent, StepHostComponent], imports: [CommonModule, OrchestratorCoreModule], exports: [OrchestratorCoreModule,
StepperComponent,
StepperHostComponent,
StepHostComponent] });
/** @nocollapse */ /** @nocollapse */ StepperModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepperModule, imports: [[CommonModule, OrchestratorCoreModule], OrchestratorCoreModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: StepperModule, decorators: [{
type: NgModule,
args: [{
imports: [CommonModule, OrchestratorCoreModule],
declarations: [StepperHostComponent, StepperComponent, StepHostComponent],
exports: [
OrchestratorCoreModule,
StepperComponent,
StepperHostComponent,
StepHostComponent,
],
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { StepConfig, StepHostComponent, Stepper, StepperComponent, StepperConfig, StepperHostComponent, StepperModule };
//# sourceMappingURL=orchestrator-stepper.mjs.map