@obliczeniowo/elementary
Version:
Library made in Angular version 20
302 lines (294 loc) • 11.4 kB
JavaScript
import * as i1 from '@angular/common/http';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import * as i0 from '@angular/core';
import { SecurityContext, DOCUMENT, Inject, Injectable, input, effect, HostBinding, Component, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { of, from } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import * as i2 from '@angular/platform-browser';
/**
* Registering icons service for icon.component
*
* Registering own:
* @example
*
* constructor(private iconResource: IconResourceService) {
* iconResource.registerIcon(
* this.sanitizer.bypassSecurityTrustHtml('/assets/icons/your-icon.svg'),
* 'icon-name'
* );
* }
*
* @
* Use in html with icon component:
*
* @example
*
* <obl-icon [width]="20" name="icon-name"></obl-icon>
*
* @ To correctly work in library component you need to copy assets folder adding script to npm:
*
* @example
*
* "copy-assets": "node ./node_modules/@obliczeniowo/elementary/assets/scripts/copy.js ./src/assets/",
*
* @ and run in console:
*
* @example
* npm run copy-assets
*/
class IconResourceService {
http;
sanitizer;
document;
icons = new Map();
urls = new Map();
loading = new Map();
base = '/';
constructor(http, sanitizer, document) {
this.http = http;
this.sanitizer = sanitizer;
this.document = document;
const base = document.head.querySelector('base');
this.base = base?.href || '/';
if (!this.icons.size) {
const icons = [
'search',
'expand',
'add',
'add-box',
'subtract-box',
'subtract',
'cancel',
'ok',
'down-more',
'up-more',
'up',
'down',
'left-more',
'right-more',
'left',
'right',
'csv-file',
'json-file',
'xlsx-file',
'logout',
'edit',
'pause',
'play',
'move',
'mute',
'voice',
'loop',
'stop',
'pointing',
'asc',
'filter',
'save',
'gear',
'checked',
'unchecked',
'checklist-mixed',
'list',
'file',
'sync-up',
'sync-down',
'link'
];
icons.forEach((icon) => this.registerIcon(this.sanitizer.bypassSecurityTrustHtml(`/assets/obl-icons/${icon}.svg`), icon));
}
}
/**
* Registering own:
* @param url SafeHTML object with path to icon in your asset folder
* @param name your icon name
*
* @example
*
* constructor(private iconResource: IconResourceService) {
* iconResource.registerIcon(
* this.sanitizer.bypassSecurityTrustHtml('/assets/icons/your-icon.svg'),
* 'icon-name'
* );
* }
*
* @
* Use in html with icon component:
*
* @example
*
* <obl-icon [width]="20" name="icon-name"></obl-icon>
*/
registerIcon(url, name) {
url.changingThisBreaksApplicationSecurity =
this.base +
url.changingThisBreaksApplicationSecurity.replace(/^\//, '');
const icon = {
url,
name,
};
this.icons.set(name, icon);
}
/**
* Download once icon from server and keep it in buffer
* @param name name of icon
* @returns observable with SVGSVGElement or undefined
*/
getIcon(name) {
const icon = this.icons.get(name);
if (!icon) {
throw new Error(`Can't find icon "${name}" in registered resources. Pleas register it.`);
}
if (icon.svgString) {
return of(this.createSvgFromString(icon.svgString));
}
const loading = this.loading.get(name);
if (loading) {
return from(loading).pipe(map((svg) => (svg ? this.createSvgFromString(svg) : undefined)));
}
const url = this.sanitizer.sanitize(SecurityContext.HTML, icon.url);
if (url) {
let resolve;
let reject;
const exec = (res, rej) => {
resolve = res;
reject = rej;
};
const promise = new Promise(exec);
this.loading.set(name, promise);
return this._fromUrl(url, (svg) => {
icon.svgString = svg;
this.icons.set(name, icon);
resolve(svg);
this.loading.delete(name);
}, () => {
reject(name);
this.loading.delete(url);
return this.err(name, url);
});
}
throw new Error('Icon url was not set');
}
/**
* Register url to SVG file
* @param url url string
* @returns SVGSVGElement/undefined or throwing error
*/
fromUrl(url) {
let icon = this.urls.get(url) || {};
if (!icon) {
icon = {
url: this.sanitizer.bypassSecurityTrustHtml(url),
};
}
if (icon.svgString) {
return of(this.createSvgFromString(icon.svgString));
}
return this._fromUrl(url, (svg) => {
icon.svgString = svg;
this.urls.set(url, icon);
}, () => this.err(undefined, url));
}
_fromUrl(url, cb, cbError) {
return this.http.get(url, { responseType: 'text' }).pipe(map((svg) => {
if (cb) {
cb(svg);
}
return this.createSvgFromString(svg);
}), catchError((_) => {
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
throw (cbError && cbError()) || this.err(undefined, url);
}));
}
ngOnDestroy() {
this.icons.clear();
}
err(name, url) {
return new Error(`Can't download icon "${name}" with url "${url}". Please make sure that asset folder in node_modules
of library @obliczeniowo/elementary was copied by adding script:
"copy-assets": "node ./node_modules/@obliczeniowo/elementary/assets/scripts/copy.js ./src/assets/",
and run it with npm or registered by you icon have proper path to file in your assets folder`);
}
createSvgFromString(svgString) {
const div = this.document.createElement('DIV');
div.innerHTML = svgString;
// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
return div.querySelector('svg');
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: IconResourceService, deps: [{ token: i1.HttpClient }, { token: i2.DomSanitizer }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: IconResourceService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: IconResourceService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.DomSanitizer }, { type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
/**
* Icon component that let you display registered icon with IconResourceService
*
* @example
*
* <obl-icon name="search" [size]="20"></obl-icon>
*/
class IconComponent {
iconResource;
elementRef;
/**
* registered icon name
*/
name = input.required();
/**
* Width in px or css like things
*/
width = input('var(--obl-icon-width, 20px)');
get widthStyle() {
return typeof this.width() === 'string' && this.width() || this.width() + 'px';
}
constructor(iconResource, elementRef) {
this.iconResource = iconResource;
this.elementRef = elementRef;
effect(() => {
this.iconResource.getIcon(this.name()).subscribe((svg) => {
if (svg) {
while (this.elementRef.nativeElement.firstChild) {
this.elementRef.nativeElement.removeChild(this.elementRef.nativeElement.firstChild);
}
svg.style.fill = 'var(--obl-default-icon-color)';
this.elementRef.nativeElement.appendChild(svg);
}
});
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: IconComponent, deps: [{ token: IconResourceService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.0.4", type: IconComponent, isStandalone: false, selector: "obl-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.width": "this.widthStyle" } }, ngImport: i0, template: "\n", styles: [":host{display:flex;align-items:center}\n"] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: IconComponent, decorators: [{
type: Component,
args: [{ selector: 'obl-icon', standalone: false, template: "\n", styles: [":host{display:flex;align-items:center}\n"] }]
}], ctorParameters: () => [{ type: IconResourceService }, { type: i0.ElementRef }], propDecorators: { widthStyle: [{
type: HostBinding,
args: ['style.width']
}] } });
class IconsModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: IconsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.4", ngImport: i0, type: IconsModule, declarations: [IconComponent], imports: [CommonModule], exports: [IconComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: IconsModule, providers: [provideHttpClient(withInterceptorsFromDi())], imports: [CommonModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: IconsModule, decorators: [{
type: NgModule,
args: [{ declarations: [
IconComponent
],
exports: [
IconComponent
], imports: [CommonModule], providers: [provideHttpClient(withInterceptorsFromDi())] }]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { IconComponent, IconResourceService, IconsModule };
//# sourceMappingURL=obliczeniowo-elementary-icons.mjs.map