@koalarx/ui
Version:
Koala UI is a modern and accessible component library designed to speed up interface development in Angular projects. With simple integration and clear documentation, you can easily build robust and visually appealing applications.
194 lines (188 loc) • 9.39 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, inject, ApplicationRef, EnvironmentInjector, createComponent, inputBinding, Injector, Injectable, viewChild, input, signal, effect, Component } from '@angular/core';
import { randomString } from '@koalarx/utils/KlString';
import { interval } from 'rxjs/internal/observable/interval';
import { startWith } from 'rxjs/internal/operators/startWith';
import { map } from 'rxjs/internal/operators/map';
const SNACKBAR_CONFIG = new InjectionToken('SnackbarConfig');
const SNACKBAR_APP_REF = new InjectionToken('SnackbarAppRef');
class Snackbar {
appRef = inject(ApplicationRef);
injector = inject(EnvironmentInjector);
generateElementId() {
let elementId;
do {
elementId = randomString(50, {
numbers: false,
lowercase: true,
uppercase: true,
specialCharacters: false,
});
} while (document.getElementById(elementId));
return elementId;
}
success(message, timeout = 5000) {
this.open({
type: 'success',
message,
timeout,
});
}
warning(message, timeout = 5000) {
this.open({
type: 'warning',
message,
timeout,
});
}
error(message, timeout = 5000) {
this.open({
type: 'error',
message,
timeout,
});
}
info(message, timeout = 5000) {
this.open({
type: 'info',
message,
timeout,
});
}
open(config) {
const main = document.querySelector('kl-snackbar-container div');
if (main) {
const elementId = this.generateElementId();
const container = main.appendChild(document.createElement('div'));
container.id = elementId;
container.classList.add('flex', 'item-center', 'justify-end');
const componentRef = createComponent(SnackbarContent, {
environmentInjector: this.injector,
hostElement: container,
elementInjector: Injector.create({
providers: [
{ provide: SNACKBAR_CONFIG, useValue: config },
{ provide: SNACKBAR_APP_REF, useValue: this.appRef },
{
provide: SNACKBAR_REF_TOKEN,
useValue: () => componentRef,
},
{
provide: SnackbarRef,
deps: [SNACKBAR_CONFIG, SNACKBAR_APP_REF, SNACKBAR_REF_TOKEN],
},
],
}),
bindings: [
inputBinding('type', () => config.type),
inputBinding('message', () => config.message),
inputBinding('timeout', () => config.timeout ?? 0),
],
});
this.appRef.attachView(componentRef.hostView);
componentRef.changeDetectorRef.detectChanges();
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: Snackbar, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: Snackbar, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: Snackbar, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
const SNACKBAR_REF_TOKEN = new InjectionToken('SnackbarRefToken');
class SnackbarRef {
appRef = inject(SNACKBAR_APP_REF);
componentRef = inject(SNACKBAR_REF_TOKEN);
dismiss() {
this.componentRef().destroy();
this.appRef.detachView(this.componentRef().hostView);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SnackbarRef, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SnackbarRef });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SnackbarRef, decorators: [{
type: Injectable
}] });
class SnackbarContent {
alertContentRef = viewChild('alertContent');
alertIconRef = viewChild('alertIcon');
snackbarRef = inject(SnackbarRef);
type = input.required();
message = input.required();
timeout = input(0);
timePast = signal(0);
constructor() {
effect(() => this.addAlertClass());
effect(() => this.addIconClass());
}
addAlertClass() {
const alertContent = this.alertContentRef()?.nativeElement;
if (alertContent) {
let className = `alert-${this.type()}`;
switch (this.type()) {
case 'info':
className = 'alert-info';
break;
case 'success':
className = 'alert-success';
break;
case 'warning':
className = 'alert-warning';
break;
case 'error':
className = 'alert-error';
break;
}
alertContent.classList.add(className);
}
}
addIconClass() {
const alertIcon = this.alertIconRef()?.nativeElement;
if (alertIcon) {
let className = '';
switch (this.type()) {
case 'info':
className = 'fa-circle-info';
break;
case 'success':
className = 'fa-circle-check';
break;
case 'warning':
className = 'fa-triangle-exclamation';
break;
case 'error':
className = 'fa-circle-xmark';
break;
}
alertIcon.classList.add(className);
}
}
ngOnInit() {
const timeout = this.timeout();
if (timeout > 0) {
const timePastInterval = interval(1000)
.pipe(startWith(0), map(() => this.timePast.update((past) => past + 1000)), map(() => this.timePast()))
.subscribe((timePast) => {
if (timePast > timeout) {
timePastInterval?.unsubscribe();
this.dismiss();
}
});
}
}
dismiss() {
this.snackbarRef.dismiss();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SnackbarContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: SnackbarContent, isStandalone: true, selector: "kl-snackbar-content", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: true, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, timeout: { classPropertyName: "timeout", publicName: "timeout", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "alertContentRef", first: true, predicate: ["alertContent"], descendants: true, isSignal: true }, { propertyName: "alertIconRef", first: true, predicate: ["alertIcon"], descendants: true, isSignal: true }], ngImport: i0, template: "<div role=\"alert\" #alertContent class=\"relative alert alert-outline bg-base-100! w-full lg:max-w-1/4 rounded-sm text-sm py-3 border-neutral-600\">\n <i #alertIcon class=\"h-4 w-4 shrink-0 stroke-current text-base fa-solid\"></i>\n <span [innerHTML]=\"message()\"></span>\n <div>\n <button class=\"btn btn-xs btn-outline\" (click)=\"dismiss()\">OK</button>\n </div>\n @if (timePast() > 0) {\n <progress class=\"absolute left-0 bottom-0 progress w-full opacity-20\"\n [value]=\"timePast()\"\n [max]=\"timeout()\">\n </progress>\n }\n</div>\n" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SnackbarContent, decorators: [{
type: Component,
args: [{ selector: 'kl-snackbar-content', template: "<div role=\"alert\" #alertContent class=\"relative alert alert-outline bg-base-100! w-full lg:max-w-1/4 rounded-sm text-sm py-3 border-neutral-600\">\n <i #alertIcon class=\"h-4 w-4 shrink-0 stroke-current text-base fa-solid\"></i>\n <span [innerHTML]=\"message()\"></span>\n <div>\n <button class=\"btn btn-xs btn-outline\" (click)=\"dismiss()\">OK</button>\n </div>\n @if (timePast() > 0) {\n <progress class=\"absolute left-0 bottom-0 progress w-full opacity-20\"\n [value]=\"timePast()\"\n [max]=\"timeout()\">\n </progress>\n }\n</div>\n" }]
}], ctorParameters: () => [] });
/**
* Generated bundle index. Do not edit.
*/
export { SNACKBAR_APP_REF, SNACKBAR_CONFIG, SNACKBAR_REF_TOKEN, Snackbar, SnackbarContent, SnackbarRef };
//# sourceMappingURL=koalarx-ui-shared-components-snackbar.mjs.map