UNPKG

@sixbell-telco/sdk

Version:

A collection of reusable components designed for use in Sixbell Telco Angular projects

172 lines (166 loc) 12.8 kB
import * as i0 from '@angular/core'; import { signal, computed, Injectable, input, output, Component, inject } from '@angular/core'; import { generateUniqueId } from '@sixbell-telco/sdk/utils/generators/uuid'; import { NgClass } from '@angular/common'; import { IconComponent } from '@sixbell-telco/sdk/components/icon'; import { matCheckCircleOutline, matWarningOutline, matErrorOutline, matInfoOutline } from '@sixbell-telco/sdk/components/icon/material/outline'; import { TypographyDirective } from '@sixbell-telco/sdk/directives/typography'; import { cn } from '@sixbell-telco/sdk/utils/cn'; import { cva } from 'class-variance-authority'; var ToastTypes; (function (ToastTypes) { ToastTypes["SUCCESS"] = "toast-success"; ToastTypes["ERROR"] = "toast-error"; ToastTypes["INFO"] = "toast-info"; ToastTypes["WARNING"] = "toast-warning"; })(ToastTypes || (ToastTypes = {})); class ToastService { toastsSignal = signal([]); expandedSignal = signal(false); // Create computed signals for derived state toasts = computed(() => this.toastsSignal()); expanded = computed(() => this.expandedSignal()); isEmpty = computed(() => this.toasts().length === 0); notify(type, message, title = '', duration = 10000) { const toast = { id: generateUniqueId(), type, message, title, duration, animate: 'enter', }; // Create a new array reference to ensure change detection this.toastsSignal.update((toasts) => [toast, ...toasts]); this.scheduleDismiss(toast); } scheduleDismiss(toast) { setTimeout(() => { this.remove(toast); }, toast.duration); } animateRemoval(toast) { this.toastsSignal.update((toasts) => toasts.map((t) => (t.id === toast.id ? { ...t, animate: 'leave' } : t))); } remove(toast) { this.toastsSignal.update((toasts) => toasts.filter((t) => t.id !== toast.id)); if (this.isEmpty()) { this.collapse(); } } clear() { this.toastsSignal.set([]); this.collapse(); } toggle() { this.expandedSignal.update((expanded) => !expanded); } collapse() { this.expandedSignal.set(false); } expand() { this.expandedSignal.set(true); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: ToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: ToastService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: ToastService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }] }); const toastComponent = cva([ 'toast-message relative mb-2 flex min-h-20 h-20 w-[400px] cursor-pointer items-center rounded-lg border-2 bg-base-200 p-2 transition-all duration-300 ease-ease-in-and-out-back', ], { variants: { variant: { info: ['border-primary', 'text-primary'], success: ['border-success', 'text-success'], warning: ['border-warning', 'text-warning'], error: ['border-error', 'text-error'], }, }, compoundVariants: [], defaultVariants: { variant: 'info', }, }); class ToastMessageComponent { variant = input(); classes = input(''); types = ToastTypes; toast = input.required(); toastAmount = input.required(); toastIndex = input.required(); clicked = output(); iconCheckCircle = matCheckCircleOutline; iconWarning = matWarningOutline; iconError = matErrorOutline; iconInfo = matInfoOutline; componentClass = computed(() => { const toast = this.toast(); const classes = this.classes(); switch (toast.type) { case this.types.SUCCESS: return cn(toastComponent({ variant: 'success', class: classes })); case this.types.ERROR: return cn(toastComponent({ variant: 'error', class: classes })); case this.types.WARNING: return cn(toastComponent({ variant: 'warning', class: classes })); case this.types.INFO: return cn(toastComponent({ variant: 'info', class: classes })); default: return cn(toastComponent({ variant: 'info', class: classes })); } }); handleClose() { this.clicked.emit(this.toast()); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: ToastMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.0", type: ToastMessageComponent, isStandalone: true, selector: "st-toast-message", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null }, toast: { classPropertyName: "toast", publicName: "toast", isSignal: true, isRequired: true, transformFunction: null }, toastAmount: { classPropertyName: "toastAmount", publicName: "toastAmount", isSignal: true, isRequired: true, transformFunction: null }, toastIndex: { classPropertyName: "toastIndex", publicName: "toastIndex", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: "<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->\n<li\n\t[class]=\"componentClass()\"\n\t[ngClass]=\"{\n\t\t'animate-toast-slide-out bottom-0': toast().animate === 'leave' && toastAmount() > 1,\n\t\t'animate-slide-out': toast().animate === 'leave' && toastAmount() === 1,\n\t\t'animate-fade-out': toast().animate === 'leave' && toastAmount() > 1 && toastIndex() === 0,\n\t\t'animate-slide-in': toast().animate === 'enter',\n\t}\"\n\t(click)=\"handleClose()\"\n\trole=\"button\"\n\ttabindex=\"0\"\n>\n\t<div class=\"flex flex-1 items-center justify-center\">\n\t\t@if (this.toast().type === this.types.SUCCESS) {\n\t\t\t<st-icon [icon]=\"iconCheckCircle\" color=\"inherit\" size=\"md\"></st-icon>\n\t\t} @else if (this.toast().type === this.types.WARNING) {\n\t\t\t<st-icon [icon]=\"iconWarning\" color=\"inherit\" size=\"md\"></st-icon>\n\t\t} @else if (this.toast().type === this.types.ERROR) {\n\t\t\t<st-icon [icon]=\"iconError\" color=\"inherit\" size=\"md\"></st-icon>\n\t\t} @else if (this.toast().type === this.types.INFO) {\n\t\t\t<st-icon [icon]=\"iconInfo\" color=\"inherit\" size=\"md\"></st-icon>\n\t\t}\n\t</div>\n\t<div class=\"flex-4\">\n\t\t<div class=\"grid grid-rows-[min-content_1fr]\">\n\t\t\t<div typography [tyVariant]=\"'body-sm'\" [tyColor]=\"'base'\" [tyFontWeight]=\"'semibold'\">{{ toast().title }}</div>\n\t\t\t<div typography [tyVariant]=\"'body-xs'\" [tyColor]=\"'base'\" [tyFontWeight]=\"'normal'\">\n\t\t\t\t{{ toast().message }}\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</li>\n", dependencies: [{ kind: "directive", type: TypographyDirective, selector: "[typography]", inputs: ["tyVariant", "tyColor", "tyFontWeight", "tyTextOverflow"] }, { kind: "component", type: IconComponent, selector: "st-icon", inputs: ["color", "size", "icon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: ToastMessageComponent, decorators: [{ type: Component, args: [{ selector: 'st-toast-message', imports: [TypographyDirective, IconComponent, NgClass], template: "<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->\n<li\n\t[class]=\"componentClass()\"\n\t[ngClass]=\"{\n\t\t'animate-toast-slide-out bottom-0': toast().animate === 'leave' && toastAmount() > 1,\n\t\t'animate-slide-out': toast().animate === 'leave' && toastAmount() === 1,\n\t\t'animate-fade-out': toast().animate === 'leave' && toastAmount() > 1 && toastIndex() === 0,\n\t\t'animate-slide-in': toast().animate === 'enter',\n\t}\"\n\t(click)=\"handleClose()\"\n\trole=\"button\"\n\ttabindex=\"0\"\n>\n\t<div class=\"flex flex-1 items-center justify-center\">\n\t\t@if (this.toast().type === this.types.SUCCESS) {\n\t\t\t<st-icon [icon]=\"iconCheckCircle\" color=\"inherit\" size=\"md\"></st-icon>\n\t\t} @else if (this.toast().type === this.types.WARNING) {\n\t\t\t<st-icon [icon]=\"iconWarning\" color=\"inherit\" size=\"md\"></st-icon>\n\t\t} @else if (this.toast().type === this.types.ERROR) {\n\t\t\t<st-icon [icon]=\"iconError\" color=\"inherit\" size=\"md\"></st-icon>\n\t\t} @else if (this.toast().type === this.types.INFO) {\n\t\t\t<st-icon [icon]=\"iconInfo\" color=\"inherit\" size=\"md\"></st-icon>\n\t\t}\n\t</div>\n\t<div class=\"flex-4\">\n\t\t<div class=\"grid grid-rows-[min-content_1fr]\">\n\t\t\t<div typography [tyVariant]=\"'body-sm'\" [tyColor]=\"'base'\" [tyFontWeight]=\"'semibold'\">{{ toast().title }}</div>\n\t\t\t<div typography [tyVariant]=\"'body-xs'\" [tyColor]=\"'base'\" [tyFontWeight]=\"'normal'\">\n\t\t\t\t{{ toast().message }}\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</li>\n" }] }] }); class ToastsContainerComponent { toastService = inject(ToastService); containerClasses = computed(() => { const toastCount = this.toastService.toasts().length; const isExpanded = this.toastService.expanded(); return { 'min-h-64': toastCount === 3 && isExpanded, 'min-h-48': toastCount === 2 && isExpanded, 'h-24 min-h-24': toastCount === 1 && isExpanded, 'h-28 min-h-28': toastCount > 0 && !isExpanded, 'h-0 min-h-0': toastCount === 0 && !isExpanded, }; }); handleExpand() { this.toastService.expand(); } handleCollapse() { this.toastService.collapse(); } handleRemove(toast) { this.toastService.animateRemoval(toast); setTimeout(() => { this.toastService.remove(toast); }, 500); } getToastIndex(toast) { return this.toastService.toasts().findIndex((t) => t.id === toast.id); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: ToastsContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.0", type: ToastsContainerComponent, isStandalone: true, selector: "st-toasts-container", ngImport: i0, template: "<section class=\"fixed bottom-2 right-4 z-10\">\n\t<ol\n\t\tclass=\"toast-container group flex min-w-[400px] flex-col gap-2\"\n\t\t[ngClass]=\"containerClasses()\"\n\t\t[attr.aria-expanded]=\"toastService.expanded()\"\n\t\t(mouseenter)=\"handleExpand()\"\n\t\t(mouseleave)=\"handleCollapse()\"\n\t>\n\t\t@for (toast of toastService.toasts(); track toast.id) {\n\t\t\t<st-toast-message\n\t\t\t\t[toast]=\"toast\"\n\t\t\t\t[toastIndex]=\"getToastIndex(toast)\"\n\t\t\t\t[toastAmount]=\"toastService.toasts().length\"\n\t\t\t\t(clicked)=\"handleRemove($event)\"\n\t\t\t/>\n\t\t}\n\t</ol>\n</section>\n", dependencies: [{ kind: "component", type: ToastMessageComponent, selector: "st-toast-message", inputs: ["variant", "classes", "toast", "toastAmount", "toastIndex"], outputs: ["clicked"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: ToastsContainerComponent, decorators: [{ type: Component, args: [{ selector: 'st-toasts-container', imports: [ToastMessageComponent, NgClass], template: "<section class=\"fixed bottom-2 right-4 z-10\">\n\t<ol\n\t\tclass=\"toast-container group flex min-w-[400px] flex-col gap-2\"\n\t\t[ngClass]=\"containerClasses()\"\n\t\t[attr.aria-expanded]=\"toastService.expanded()\"\n\t\t(mouseenter)=\"handleExpand()\"\n\t\t(mouseleave)=\"handleCollapse()\"\n\t>\n\t\t@for (toast of toastService.toasts(); track toast.id) {\n\t\t\t<st-toast-message\n\t\t\t\t[toast]=\"toast\"\n\t\t\t\t[toastIndex]=\"getToastIndex(toast)\"\n\t\t\t\t[toastAmount]=\"toastService.toasts().length\"\n\t\t\t\t(clicked)=\"handleRemove($event)\"\n\t\t\t/>\n\t\t}\n\t</ol>\n</section>\n" }] }] }); /** * Generated bundle index. Do not edit. */ export { ToastMessageComponent, ToastService, ToastTypes, ToastsContainerComponent, toastComponent }; //# sourceMappingURL=sixbell-telco-sdk-components-toast.mjs.map