UNPKG

@ngaox/icons

Version:

Inline SVG icons from (src | files | your favorite icons library | ...)!

214 lines (205 loc) 9.11 kB
import { DOCUMENT } from '@angular/common'; import * as i1 from '@angular/common/http'; import * as i0 from '@angular/core'; import { InjectionToken, makeEnvironmentProviders, Injectable, Inject, Optional, input, inject, DestroyRef, signal, effect, Component, HostBinding } from '@angular/core'; import { of, map, shareReplay } from 'rxjs'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import * as i2 from '@angular/platform-browser'; const NGAOX_FALLBACK = new InjectionToken('NgaoxFallbackIcon'); const NgaoxGlobalIcons = new InjectionToken('NgaoxGlobalIcons'); function provideNgaoxIcons(icons = [], fallbackIcon = undefined) { return makeEnvironmentProviders([ IconsService, { provide: NgaoxGlobalIcons, useValue: icons }, { provide: NGAOX_FALLBACK, useValue: fallbackIcon } ]); } const defaultFallbackIcon = ` <svg viewBox="0 0 612 612" xmlns="http://www.w3.org/2000/svg" fill="currentColor"> <path d="M306 50C164.6 50 50 164.6 50 306C50 447.4 164.6 562 306 562C447.4 562 562 447.4 562 306C562 164.6 447.4 50 306 50ZM282 202C282 188.8 292.8 178 306 178C319.2 178 330 188.75 330 202V330C330 343.25 319.25 354 306 354C292.75 354 282 343.3 282 330V202ZM306 450C288.64 450 274.56 435.92 274.56 418.56C274.56 401.2 288.63 387.12 306 387.12C323.37 387.12 337.44 401.2 337.44 418.56C337.4 435.9 323.4 450 306 450Z"/> </svg> `; class IconsService { constructor(http, document, fallbackIcon = defaultFallbackIcon, icons) { this.http = http; this.document = document; this.fallbackIcon = fallbackIcon; this.icons = new Map(); this.lazyIcons = new Map(); icons ??= []; this.addAll(icons); } textToSvgElement(svg) { const div = this.document.createElement('div'); div.innerHTML = svg; const svgEl = div.querySelector('svg'); if (svgEl) { svgEl.setAttribute('height', '100%'); svgEl.setAttribute('width', '100%'); } return svgEl; } /** * Get the fallback icon specified in the import of the `IconsModule.forRoot` * Used in the `ngaox-icon` component when the icon is not found * @see {@link https://ngaox-lab.web.app/docs/icons#fallback-icon} */ getFallbackIcon() { return this.fallbackIcon; } /** * get an already registered/added icon * * @see {@link IconsService.add} */ get(name) { if (this.icons.has(name)) { return of(this.icons.get(name)); } else if (this.lazyIcons.has(name)) { return this.lazyIcons.get(name) ?? of(undefined); } return of(undefined); } /** * Add an SVG icon to the NgaoxIcons registry * * @param name the name of the Icon in the registry (used in `ngaox-icon` component and {@link IconsService.get}) * @param value the SVG content or {@link ILazyIcon} for lazy loaded icons * @param override (default to true) whether or not replacing existing `svg` if `name` already exists * */ add(name, value) { if (typeof value === 'string') { this.icons.set(name, this.textToSvgElement(value)); } else { this.lazyIcons.set(name, this.http.get(value.url, { responseType: 'text' }).pipe(map(svg => this.textToSvgElement(svg)), shareReplay(1))); } return this.get(name); } addAll(icons) { icons.forEach(icon => { this.add(icon.name, icon.data); }); } /** * remove a registered icon */ remove(name) { if (this.icons.has(name)) { this.icons.delete(name); } if (this.lazyIcons.has(name)) { this.lazyIcons.delete(name); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: IconsService, deps: [{ token: i1.HttpClient }, { token: DOCUMENT }, { token: NGAOX_FALLBACK, optional: true }, { token: NgaoxGlobalIcons, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: IconsService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: IconsService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.HttpClient }, { type: Document, decorators: [{ type: Inject, args: [DOCUMENT] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [NGAOX_FALLBACK] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [NgaoxGlobalIcons] }] }] }); class NgaoxIconComponent { get _width() { return this.width(); } get _height() { return this.height(); } get _svgContent() { return this.svgContent(); } constructor(service, sanitizer) { this.service = service; this.sanitizer = sanitizer; this.name = input.required(); this.url = input(); this.width = input(); this.height = input(); this.destroyRef = inject(DestroyRef); this.svgContent = signal(this.sanitizer.bypassSecurityTrustHtml(this.service.getFallbackIcon())); effect(() => { const name = this.name(); const url = this.url(); let icon; if (url) { icon = this.service.add(name, { url, lazy: true }); } else { icon = this.service.get(name); } icon.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({ next: svg => { const outerHTML = svg?.outerHTML; if (!outerHTML) { throw new Error(`Icon '${name}' not found or has incorrect content.`); } this.svgContent.set(this.sanitizer.bypassSecurityTrustHtml(outerHTML)); }, error: () => { this.svgContent.set(this.sanitizer.bypassSecurityTrustHtml(this.service.getFallbackIcon())); throw new Error(`Icon '${name}' not found or has incorrect content.`); } }); }, { allowSignalWrites: true }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: NgaoxIconComponent, deps: [{ token: IconsService }, { token: i2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.0.3", type: NgaoxIconComponent, isStandalone: true, selector: "ngaox-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.width": "this._width", "style.height": "this._height", "innerHTML": "this._svgContent" } }, ngImport: i0, template: ``, isInline: true, styles: [":host{display:inline-block;vertical-align:middle}\n"] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: NgaoxIconComponent, decorators: [{ type: Component, args: [{ selector: 'ngaox-icon', template: ``, standalone: true, styles: [":host{display:inline-block;vertical-align:middle}\n"] }] }], ctorParameters: () => [{ type: IconsService }, { type: i2.DomSanitizer }], propDecorators: { _width: [{ type: HostBinding, args: ['style.width'] }], _height: [{ type: HostBinding, args: ['style.height'] }], _svgContent: [{ type: HostBinding, args: ['innerHTML'] }] } }); function CompactIconsAdapter(icons) { return Object.entries(icons).map(([name, data]) => { return { name, data }; }); } /* * Public API Surface of @ngaox/icons */ /** * Generated bundle index. Do not edit. */ export { CompactIconsAdapter, IconsService, NGAOX_FALLBACK, NgaoxGlobalIcons, NgaoxIconComponent, provideNgaoxIcons }; //# sourceMappingURL=ngaox-icons.mjs.map