@ipi-soft/ng-components
Version:
Custom Angular Components
183 lines (178 loc) • 15.5 kB
JavaScript
import { NgClass } from '@angular/common';
import * as i0 from '@angular/core';
import { EventEmitter, Component, Input, Output, createComponent, Injectable } from '@angular/core';
import { IpiImageComponent } from '@ipi-soft/ng-components/image';
import * as i1 from '@ipi-soft/ng-components/services';
var verticalPosition;
(function (verticalPosition) {
verticalPosition[verticalPosition["Bottom"] = 0] = "Bottom";
verticalPosition[verticalPosition["Top"] = 1] = "Top";
})(verticalPosition || (verticalPosition = {}));
var horizontalPosition;
(function (horizontalPosition) {
horizontalPosition[horizontalPosition["Left"] = 0] = "Left";
horizontalPosition[horizontalPosition["Center"] = 1] = "Center";
horizontalPosition[horizontalPosition["Right"] = 2] = "Right";
})(horizontalPosition || (horizontalPosition = {}));
class IpiSnackbarComponent {
constructor() {
this.closed = new EventEmitter();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: IpiSnackbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.4", type: IpiSnackbarComponent, isStandalone: true, selector: "ipi-snackbar", inputs: { message: "message", options: "options", positionOptions: "positionOptions" }, outputs: { closed: "closed" }, ngImport: i0, template: "<div\n class=\"custom-snackbar\"\n [class.error]=\"options.error\"\n [ngClass]=\"[ 'horizontal-' + positionOptions.horizontalPosition, 'vertical-' + positionOptions.verticalPosition]\"\n [style.ipi-snackbar-animation-duration]=\"options.animationDuration + 's'\">\n\n <div class=\"placeholder-wrapper\">\n @if (options.icon) {\n <ipi-img [src]=\"'assets/img/' + options.icon\" [ariaLabel]=\"'Snackbar prefix icon'\"></ipi-img>\n }\n\n <div class=\"placeholder\">{{ options.title ?? (options.error ? 'Error' : 'Success') }}</div>\n\n <div class=\"x-icon\" (click)=\"closed.emit()\"></div>\n </div>\n\n <div class=\"message-wrapper\" [ngClass]=\"{ 'no-padding' : !options.icon }\">\n <div class=\"message\">{{ message }}</div>\n </div>\n\n <div class=\"progress\" [style.animation-duration]=\"options.animationDuration + 's'\"></div>\n</div>\n", styles: [":host{--ipi-snackbar-animation-duration: 10s;--ipi-snackbar-background-color: #14BD6C;--ipi-snackbar-placeholder-text-color: #FFFFFF;--ipi-snackbar-message-text-color: #FFFFFF;--ipi-snackbar-error-background-color: #F96138;--ipi-snackbar-progress-color: #FFFFFF;--ipi-snackbar-x-icon-color: #FFFFFF;pointer-events:all;touch-action:manipulation;margin:.2em}.placeholder-wrapper{height:24px;display:flex;align-items:center;align-self:stretch;gap:4px}.custom-snackbar{width:360px;height:100%;display:flex;position:relative;flex-direction:column;justify-content:center;align-items:flex-start;border-radius:4px;opacity:0;background:var(--ipi-snackbar-background-color);padding:12px 16px 16px}ipi-img{width:20px;height:20px}.placeholder{flex:1 0 0;color:var(--ipi-snackbar-placeholder-text-color);font-size:18px;font-style:normal;font-weight:600;line-height:22px}.message-wrapper{display:flex;align-items:flex-start;align-self:stretch;gap:10px;padding-left:24px}.message-wrapper.no-padding{padding:0}.message{flex:1 0 0;color:var(--ipi-snackbar-message-text-color);font-size:16px;font-style:normal;font-weight:400;line-height:20px}.error{background-color:var(--ipi-snackbar-error-background-color)}.vertical-1{top:.5em}.vertical-0{bottom:.5em}.horizontal-0{animation:LeftPopUpAnimation var(--ipi-snackbar-animation-duration) ease-in-out}.horizontal-1{animation:CenterPopUpAnimation var(--ipi-snackbar-animation-duration) ease-in-out}.horizontal-2{animation:RightPopUpAnimation var(--ipi-snackbar-animation-duration) ease-in-out}.progress{max-width:392px;height:4px;position:absolute;bottom:0;opacity:.5;background:var(--ipi-snackbar-progress-color);transform:translate(-16px);animation:shrinkProgress var(--ipi-snackbar-animation-duration) ease-in-out}.x-icon{width:20px;cursor:pointer;transition:transform .3s ease;opacity:.7;padding-top:8px}.x-icon:after{font-size:36px;color:var(--ipi-snackbar-x-icon-color);content:\"\\d7\"}.x-icon:hover{animation:rotate .3s linear}@media (max-width: 460px){.custom-snackbar{width:300px}}@keyframes rotate{0%{transform:rotate(0)}25%{transform:rotate(-10deg)}75%{transform:rotate(10deg)}to{transform:rotate(0)}}@keyframes CenterPopUpAnimation{1%{bottom:-2em;opacity:0}10%{bottom:.5em;opacity:1}95%{bottom:.5em;opacity:1}99%{bottom:2em;opacity:0}}@keyframes LeftPopUpAnimation{1%{left:-2em;opacity:0}10%{left:.5em;opacity:1}95%{left:.5em;opacity:1}99%{left:-2em;opacity:0}}@keyframes RightPopUpAnimation{1%{right:-2em;opacity:0}10%{right:.5em;opacity:1}95%{right:.5em;opacity:1}99%{right:2em;opacity:0}}@keyframes shrinkProgress{0%{width:100%}to{width:0%}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: IpiImageComponent, selector: "ipi-img", inputs: ["src", "ariaLabel"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: IpiSnackbarComponent, decorators: [{
type: Component,
args: [{ selector: 'ipi-snackbar', imports: [
NgClass,
IpiImageComponent,
], template: "<div\n class=\"custom-snackbar\"\n [class.error]=\"options.error\"\n [ngClass]=\"[ 'horizontal-' + positionOptions.horizontalPosition, 'vertical-' + positionOptions.verticalPosition]\"\n [style.ipi-snackbar-animation-duration]=\"options.animationDuration + 's'\">\n\n <div class=\"placeholder-wrapper\">\n @if (options.icon) {\n <ipi-img [src]=\"'assets/img/' + options.icon\" [ariaLabel]=\"'Snackbar prefix icon'\"></ipi-img>\n }\n\n <div class=\"placeholder\">{{ options.title ?? (options.error ? 'Error' : 'Success') }}</div>\n\n <div class=\"x-icon\" (click)=\"closed.emit()\"></div>\n </div>\n\n <div class=\"message-wrapper\" [ngClass]=\"{ 'no-padding' : !options.icon }\">\n <div class=\"message\">{{ message }}</div>\n </div>\n\n <div class=\"progress\" [style.animation-duration]=\"options.animationDuration + 's'\"></div>\n</div>\n", styles: [":host{--ipi-snackbar-animation-duration: 10s;--ipi-snackbar-background-color: #14BD6C;--ipi-snackbar-placeholder-text-color: #FFFFFF;--ipi-snackbar-message-text-color: #FFFFFF;--ipi-snackbar-error-background-color: #F96138;--ipi-snackbar-progress-color: #FFFFFF;--ipi-snackbar-x-icon-color: #FFFFFF;pointer-events:all;touch-action:manipulation;margin:.2em}.placeholder-wrapper{height:24px;display:flex;align-items:center;align-self:stretch;gap:4px}.custom-snackbar{width:360px;height:100%;display:flex;position:relative;flex-direction:column;justify-content:center;align-items:flex-start;border-radius:4px;opacity:0;background:var(--ipi-snackbar-background-color);padding:12px 16px 16px}ipi-img{width:20px;height:20px}.placeholder{flex:1 0 0;color:var(--ipi-snackbar-placeholder-text-color);font-size:18px;font-style:normal;font-weight:600;line-height:22px}.message-wrapper{display:flex;align-items:flex-start;align-self:stretch;gap:10px;padding-left:24px}.message-wrapper.no-padding{padding:0}.message{flex:1 0 0;color:var(--ipi-snackbar-message-text-color);font-size:16px;font-style:normal;font-weight:400;line-height:20px}.error{background-color:var(--ipi-snackbar-error-background-color)}.vertical-1{top:.5em}.vertical-0{bottom:.5em}.horizontal-0{animation:LeftPopUpAnimation var(--ipi-snackbar-animation-duration) ease-in-out}.horizontal-1{animation:CenterPopUpAnimation var(--ipi-snackbar-animation-duration) ease-in-out}.horizontal-2{animation:RightPopUpAnimation var(--ipi-snackbar-animation-duration) ease-in-out}.progress{max-width:392px;height:4px;position:absolute;bottom:0;opacity:.5;background:var(--ipi-snackbar-progress-color);transform:translate(-16px);animation:shrinkProgress var(--ipi-snackbar-animation-duration) ease-in-out}.x-icon{width:20px;cursor:pointer;transition:transform .3s ease;opacity:.7;padding-top:8px}.x-icon:after{font-size:36px;color:var(--ipi-snackbar-x-icon-color);content:\"\\d7\"}.x-icon:hover{animation:rotate .3s linear}@media (max-width: 460px){.custom-snackbar{width:300px}}@keyframes rotate{0%{transform:rotate(0)}25%{transform:rotate(-10deg)}75%{transform:rotate(10deg)}to{transform:rotate(0)}}@keyframes CenterPopUpAnimation{1%{bottom:-2em;opacity:0}10%{bottom:.5em;opacity:1}95%{bottom:.5em;opacity:1}99%{bottom:2em;opacity:0}}@keyframes LeftPopUpAnimation{1%{left:-2em;opacity:0}10%{left:.5em;opacity:1}95%{left:.5em;opacity:1}99%{left:-2em;opacity:0}}@keyframes RightPopUpAnimation{1%{right:-2em;opacity:0}10%{right:.5em;opacity:1}95%{right:.5em;opacity:1}99%{right:2em;opacity:0}}@keyframes shrinkProgress{0%{width:100%}to{width:0%}}\n"] }]
}], propDecorators: { message: [{
type: Input
}], options: [{
type: Input
}], positionOptions: [{
type: Input
}], closed: [{
type: Output
}] } });
class IpiSnackbarService {
constructor(appRef, overlayService) {
this.appRef = appRef;
this.overlayService = overlayService;
this.maxSnackbars = 5;
this.defaultSnackbarOptions = {
error: false,
animationDuration: 10,
backgroundColor: '#14BD6C',
placeholderTextColor: '#FFFFFF',
messageTextColor: '#FFFFFF',
progressColor: '#FFFFFF',
xIconColor: '#FFFFFF',
errorBackgroundColor: '#F96138'
};
this.positionOptions = {
verticalPosition: verticalPosition.Bottom,
horizontalPosition: horizontalPosition.Center
};
this.snackbarsArray = [];
}
open(message, options) {
this.createFixedComponent();
const snackbarOptions = {
...this.defaultSnackbarOptions,
...options
};
const snackbarRef = this.createAndAppendSnackbar(snackbarOptions);
snackbarRef.instance.message = message;
this.closeIfMaxSnackbar();
this.snackbarsArray.push(snackbarRef);
this.subscribeToClosingEvents(snackbarRef);
}
setPosition(options) {
this.positionOptions = options;
}
setMaxSnackbars(length) {
this.maxSnackbars = length;
}
updateDefaultOptions(options) {
this.defaultSnackbarOptions = { ...this.defaultSnackbarOptions, ...options };
}
createFixedComponent() {
if (!this.fixedContainer || this.fixedContainer.children.length === 0) {
this.fixedContainer = document.createElement('div');
this.setFixedComponentStyling();
this.overlayService.appendToOverlay(this.fixedContainer, false);
}
}
createAndAppendSnackbar(options) {
const componentRef = createComponent(IpiSnackbarComponent, { environmentInjector: this.appRef.injector });
componentRef.instance.options = options;
componentRef.instance.positionOptions = this.positionOptions;
this.appRef.attachView(componentRef.hostView);
const snackbarElement = componentRef.hostView.rootNodes[0];
this.applyCustomStyles(snackbarElement, options);
this.fixedContainer.appendChild(snackbarElement);
setTimeout(() => {
componentRef.destroy();
this.close(this.snackbarsArray.indexOf(componentRef));
if (this.snackbarsArray.length === 0) {
this.overlayService.removeFromOverlay(this.fixedContainer);
}
}, options.animationDuration * 1000);
return componentRef;
}
applyCustomStyles(snackbarElement, options) {
const styles = {
'--ipi-snackbar-background-color': options.backgroundColor,
'--ipi-snackbar-placeholder-text-color': options.placeholderTextColor,
'--ipi-snackbar-message-text-color': options.messageTextColor,
'--ipi-snackbar-progress-color': options.progressColor,
'--ipi-snackbar-x-icon-color': options.xIconColor,
'--ipi-snackbar-animation-duration': options.animationDuration ? `${options.animationDuration}s` : undefined
};
for (const [cssVar, value] of Object.entries(styles)) {
if (value) {
snackbarElement.style.setProperty(cssVar, value);
}
}
}
closeIfMaxSnackbar() {
if (this.snackbarsArray.length === this.maxSnackbars) {
this.close(0);
}
}
subscribeToClosingEvents(snackbarRef) {
snackbarRef.instance.closed.subscribe(() => {
this.close(this.snackbarsArray.indexOf(snackbarRef));
if (this.snackbarsArray.length === 0) {
this.overlayService.removeFromOverlay(this.fixedContainer);
}
});
snackbarRef.onDestroy(() => {
snackbarRef.instance.closed.unsubscribe();
});
}
setFixedComponentStyling() {
this.fixedContainer.style.display = 'flex';
this.fixedContainer.style.flexDirection = 'column';
this.fixedContainer.style.alignItems = 'flex-end';
this.fixedContainer.style.bottom = '0px';
this.fixedContainer.style.left = '50%';
this.fixedContainer.style.transform = 'translateX(-50%)';
if (this.positionOptions.horizontalPosition === horizontalPosition.Left) {
this.fixedContainer.style.left = '0px';
this.fixedContainer.style.transform = 'translateX(0%)';
}
else if (this.positionOptions.horizontalPosition === horizontalPosition.Right) {
this.fixedContainer.style.left = '';
this.fixedContainer.style.right = '0px';
this.fixedContainer.style.transform = 'translateX(0%)';
}
if (this.positionOptions.verticalPosition === verticalPosition.Top) {
this.fixedContainer.style.bottom = '';
this.fixedContainer.style.top = '0px';
}
this.fixedContainer.style.position = 'fixed';
this.fixedContainer.style.zIndex = '1000';
}
close(index) {
if (this.snackbarsArray[index]) {
this.snackbarsArray[index].destroy();
this.snackbarsArray.splice(index, 1);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: IpiSnackbarService, deps: [{ token: i0.ApplicationRef }, { token: i1.OverlayService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: IpiSnackbarService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: IpiSnackbarService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i0.ApplicationRef }, { type: i1.OverlayService }] });
/**
* Generated bundle index. Do not edit.
*/
export { IpiSnackbarComponent, IpiSnackbarService, horizontalPosition, verticalPosition };
//# sourceMappingURL=ipi-soft-ng-components-snackbar.mjs.map