UNPKG

@orchestrator/stepper

Version:

> A stepper component for Orchestrator library.

330 lines (319 loc) 20.4 kB
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