UNPKG

@cisstech/nge

Version:

NG Essentials is a collection of libraries for Angular developers.

336 lines (328 loc) 13.3 kB
import * as i0 from '@angular/core'; import { Injectable, createNgModule, inject } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import { Observable, of, from, forkJoin } from 'rxjs'; import { take, shareReplay, concatMap } from 'rxjs/operators'; /** Service to programmatically open file dialog. */ class PickerBrowserService { /** * Open file dialog to select files. * @param options picker options. * @returns A promise that resolves with the picked files or and empty array. */ pickFiles(options) { return new Promise(async (resolve) => { const input = document.createElement('input'); input.type = 'file'; input.multiple = options.multiple ?? true; input.accept = options.accept ?? '*'; input.style.visibility = 'hidden'; input.onchange = (event) => { const target = event.target || event.srcElement; if (target.value.length > 0) { input.remove(); resolve(target.files); } else { input.remove(); resolve([]); } }; // handle cancel button click. setTimeout(() => { let onfocus; onfocus = () => { if (!input.value.length) { resolve([]); input.remove(); } window.removeEventListener('click', onfocus); }; window.addEventListener('click', onfocus); }, 300); document.body.appendChild(input); input.focus(); input.click(); }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: PickerBrowserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: PickerBrowserService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: PickerBrowserService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class ClipboardService { copy(data) { return navigator.clipboard.writeText(data); } read() { return navigator.clipboard.readText(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: ClipboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: ClipboardService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: ClipboardService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class CompilerService { constructor() { this.modules = []; } async render(options) { const { component } = await this.resolveComponent(options.type, options.container.injector); return await this.renderComponent(options.inputs, options.container.createComponent(component, { index: 0, injector: options.container.injector, })); } async resolveComponent(type, injector) { // https://blog.ninja-squad.com/2019/05/07/what-is-angular-ivy/ // https://juristr.com/blog/2019/10/lazyload-module-ivy-viewengine if (!('ɵmod' in type) && !('ɵcmp' in type)) { throw new Error(`[render]: type "${type.name}" does not refers to a Component or a NgModule`); } let component = type; let componentInjector = injector; if ('ɵmod' in type) { const module = await this.resolveModuleInfo(type, injector); componentInjector = module.injector; component = module.instance.component; } return { component, injector: componentInjector, }; } async renderComponent(inputs, componentRef) { const changes = {}; const { instance, changeDetectorRef } = componentRef; if (inputs) { Object.keys(inputs).forEach((k) => { instance[k] = inputs[k]; changes[k] = { currentValue: inputs[k], previousValue: undefined, firstChange: true, isFirstChange: () => true, }; }); } if (instance.ngOnChanges) { await instance.ngOnChanges(changes); } changeDetectorRef.markForCheck(); return componentRef; } async resolveModuleInfo(type, injector) { const moduleInfo = this.modules.find((e) => e.type === type); if (moduleInfo) { return moduleInfo.module; } const module = createNgModule(type, injector); if (typeof module.instance.component !== 'function') { throw new Error(`[compiler]: The module "${type.name}" does not define a public "component" field.`); } this.modules.push({ type: type, module: module }); return module; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: CompilerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: CompilerService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: CompilerService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class InjectorService { constructor(injector) { this.injector = injector; } get(token) { const service = this.injector.get(token, []).find((e) => e.injectable()); if (!service) { throw new Error('[InjectorService]: No provider found for ' + token); } return service; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: InjectorService, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: InjectorService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: InjectorService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i0.Injector }] }); class ResourceLoaderConfig { } class LoadRequest { get isFinished() { return this.finished; } constructor(asset, document, config) { this.asset = asset; this.document = document; this.config = config; this.finished = false; } run() { if (this.asset[0] === 'style') { return this.loadStyle(); } return this.loadScript(); } loadStyle() { return (this.request ?? (this.request = new Observable((observer) => { const url = this.buildUrl(this.asset[1]); const style = this.document.createElement('link'); style.href = url; style.rel = 'stylesheet'; style.onload = () => { observer.next(this.asset); observer.complete(); this.finished = true; }; style.onerror = (err) => { observer.error(err); this.finished = true; }; const attributes = this.asset[2]; if (attributes) { for (const key in attributes) { if (attributes.hasOwnProperty(key)) { style.setAttribute(key, attributes[key]); } } } this.document.head.appendChild(style); }).pipe(take(1), shareReplay(1)))); } loadScript() { return (this.request ?? (this.request = new Observable((observer) => { const url = this.buildUrl(this.asset[1]); const script = this.document.createElement('script'); script.src = url; script.onload = () => { observer.next(this.asset); observer.complete(); this.finished = true; }; script.onerror = (err) => { observer.error(err); this.finished = true; }; const attributes = this.asset[2]; if (attributes) { for (const key in attributes) { if (attributes.hasOwnProperty(key)) { script.setAttribute(key, attributes[key]); } } } this.document.head.appendChild(script); }).pipe(take(1), shareReplay(1)))); } buildUrl(url) { if (!this.config?.useDocumentBaseURI) { return url; } if (url.startsWith('http')) { return url; } if (!url.startsWith(document.baseURI)) { url = url.startsWith('/') ? url.slice(1) : url; return document.baseURI + url; } return url; } } /** * Services that dynamically inject scripts and styles elements to the DOM. */ class ResourceLoaderService { constructor() { this.document = inject(DOCUMENT); this.config = inject(ResourceLoaderConfig, { optional: true }); this.requests = new Map(); } waitForPendings() { return new Promise((resolve) => { const interval = setInterval(() => { for (const request of this.requests.values()) { if (!request.isFinished) { return; } } clearInterval(interval); resolve(); }, 100); }); } /** * Injects styles and scripts from given urls to the head of the DOM. * This method loads assets from same url once and the assets are * loaded in the same order that given. * @param resources Resources to load. */ loadAllSync(resources) { if (!resources.length) { return of([]); } const requests = this.createRequests(resources); return new Observable((observer) => { const response = []; const subs = from(requests) .pipe(concatMap((e) => e.run())) .subscribe((e) => { response.push(e); if (response.length === resources.length) { observer.next(response); observer.complete(); } }); return () => { subs?.unsubscribe(); }; }); } /** * Injects styles and scripts from given urls to target place in DOM * This method loads style and script from same url once. * @param resources Resources to load. */ loadAllAsync(resources) { if (!resources.length) { return of([]); } const loaders = this.createRequests(resources); return forkJoin(loaders.map((e) => e.run())); } createRequests(resources) { return resources.map((asset) => { const url = asset[1]; let request = this.requests.get(url); if (!request) { this.requests.set(url, (request = new LoadRequest(asset, this.document, this.config))); } return request; }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: ResourceLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: ResourceLoaderService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.1", ngImport: i0, type: ResourceLoaderService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }] }); const ResourceLoaderConfigProvider = (config) => ({ provide: ResourceLoaderConfig, useValue: config, }); /** * Generated bundle index. Do not edit. */ export { ClipboardService, CompilerService, InjectorService, PickerBrowserService, ResourceLoaderConfig, ResourceLoaderConfigProvider, ResourceLoaderService }; //# sourceMappingURL=cisstech-nge-services.mjs.map