UNPKG

@deepkit/desktop-ui

Version:

Library for desktop UI widgets in Angular 10+

857 lines (846 loc) 837 kB
import * as i0 from '@angular/core'; import { input, booleanAttribute, ContentChild, Component, output, signal, ChangeDetectorRef, HostListener, SkipSelf, forwardRef, model, inject, Injector, HostBinding, Input, Directive, Inject, Injectable, EventEmitter, ElementRef, ViewContainerRef, TemplateRef, computed, Renderer2, effect, viewChild, ViewChild, ApplicationRef, RendererFactory2, Optional, contentChild, ChangeDetectionStrategy, OutputEmitterRef, ɵNG_COMP_DEF as _NG_COMP_DEF, EmbeddedViewRef, PendingTasks, contentChildren, Pipe, ViewEncapsulation, ComponentRef, Output, ComponentFactoryResolver, numberAttribute, viewChildren } from '@angular/core'; import * as i1 from '@angular/forms'; import { NgControl, FormGroup, FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; import { KeyValuePipe, DOCUMENT, NgTemplateOutlet, formatDate, DecimalPipe } from '@angular/common'; import { nextTick, arrayRemoveItem, getClassName, isArray, humanBytes, __ΩTypeAnnotation as ___TypeAnnotation, __ΩClassType as ___ClassType, getClassTypeFromInstance, getPathValue, setPathValue, throttleTime, eachPair, first, indexOf, empty, arrayHasItem } from '@deepkit/core'; import { TemplatePortal, ComponentPortal, DomPortalOutlet } from '@angular/cdk/portal'; import * as i1$2 from '@angular/cdk/overlay'; import { OverlayRef, Overlay } from '@angular/cdk/overlay'; import * as i1$1 from '@angular/router'; import { Router, RouterLinkActive, ResolveEnd, NavigationEnd, RouterLink } from '@angular/router'; import { Subscription, Observable } from 'rxjs'; import * as i1$3 from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser'; import { ReflectionClass, ReflectionKind, __ΩExcluded as ___Excluded, resolveTypeMembers, typeAnnotation, Serializer, deserialize, serialize } from '@deepkit/type'; import { EventToken } from '@deepkit/event'; import onChange from 'on-change'; import { ProgressTracker } from '@deepkit/core-rxjs'; import { CdkVirtualScrollViewport, CdkFixedSizeVirtualScroll, CdkVirtualForOf } from '@angular/cdk/scrolling'; class BrowserText { constructor(fontSize = 11, fontFamily = getComputedStyle(document.querySelector('.dui-body') || document.body).fontFamily) { this.fontSize = fontSize; this.fontFamily = fontFamily; this.canvas = document.createElement('canvas'); this.context = this.canvas.getContext('2d'); document.body.appendChild(this.canvas); this.canvas.style.display = 'none'; } destroy() { document.body.removeChild(this.canvas); } getDimensions(text) { this.context.font = this.fontSize + 'px ' + this.fontFamily; const m = this.context.measureText(text); return { width: m.width, height: m.actualBoundingBoxAscent + m.actualBoundingBoxDescent }; } static { this.__type = ['canvas', function () { return document.createElement('canvas'); }, 'context', function () { return this.canvas.getContext('2d'); }, 'fontSize', () => 11, 'fontFamily', () => getComputedStyle(document.querySelector(".dui-body") || document.body).fontFamily, 'constructor', 'destroy', 'text', 'getDimensions', 'BrowserText', '!3!<>"!3#<>$P\'2%:>&&2\':>("0)P"0*P&2+"0,5w-']; } } /* * Deepkit Framework * Copyright (C) 2021 Deepkit UG, Marc J. Schmidt * * This program is free software: you can redistribute it and/or modify * it under the terms of the MIT License. * * You should have received a copy of the MIT License along with this program. */ class FormRowComponent { constructor() { this.label = (input.Ω = [['&']], input('')); this.description = (input.Ω = [['&']], input('')); this.labelWidth = (input.Ω = [['\'']], input()); this.left = input(false, { transform: booleanAttribute }); } isString(v) { return 'string' === typeof v; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: FormRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: FormRowComponent, isStandalone: true, selector: "dui-form-row", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, labelWidth: { classPropertyName: "labelWidth", publicName: "labelWidth", isSignal: true, isRequired: false, transformFunction: null }, left: { classPropertyName: "left", publicName: "left", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.left-aligned": "left()" } }, queries: [{ propertyName: "ngControl", first: true, predicate: NgControl, descendants: true }], ngImport: i0, template: ` <div class="label" [style.width.px]="labelWidth()">{{ label() }}@if (description()) { <div class="description">{{ description() }}</div> }</div> <div class="field"> <ng-content></ng-content> @if (ngControl && ngControl.errors && ngControl.touched) { <div class="error"> @for (kv of ngControl.errors|keyvalue; track kv) { <div> {{ isString(kv.value) ? '' : kv.key }}{{ isString(kv.value) ? kv.value : '' }} </div> } </div> } </div>`, isInline: true, styles: [":host{display:flex}:host:not(:last-child){margin-bottom:12px}:host .label{width:30%;margin-right:8px;line-height:20px;text-align:right}:host .field{flex:1;padding-right:5px}:host .field ::ng-deep>*{width:100%}:host .description{font-size:12px;color:var(--dui-text-light)}:host.left-aligned .label{text-align:left}.error{margin-top:2px;color:var(--dui-color-red)}\n"], dependencies: [{ kind: "pipe", type: KeyValuePipe, name: "keyvalue" }] }); } static { this.__type = ['label', function () { return (input.Ω = [['&']], input('')); }, 'description', function () { return (input.Ω = [['&']], input('')); }, 'labelWidth', function () { return (input.Ω = [['\'']], input()); }, 'left', function () { return input(false, { transform: booleanAttribute }); }, () => NgControl, 'ngControl', 'v', 'isString', '\u0275fac', function () { return i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: FormRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }, '\u0275cmp', function () { return i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: FormRowComponent, isStandalone: true, selector: "dui-form-row", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, labelWidth: { classPropertyName: "labelWidth", publicName: "labelWidth", isSignal: true, isRequired: false, transformFunction: null }, left: { classPropertyName: "left", publicName: "left", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.left-aligned": "left()" } }, queries: [{ propertyName: "ngControl", first: true, predicate: NgControl, descendants: true }], ngImport: i0, template: ` <div class="label" [style.width.px]="labelWidth()">{{ label() }}@if (description()) { <div class="description">{{ description() }}</div> }</div> <div class="field"> <ng-content></ng-content> @if (ngControl && ngControl.errors && ngControl.touched) { <div class="error"> @for (kv of ngControl.errors|keyvalue; track kv) { <div> {{ isString(kv.value) ? '' : kv.key }}{{ isString(kv.value) ? kv.value : '' }} </div> } </div> } </div>`, isInline: true, styles: [":host{display:flex}:host:not(:last-child){margin-bottom:12px}:host .label{width:30%;margin-right:8px;line-height:20px;text-align:right}:host .field{flex:1;padding-right:5px}:host .field ::ng-deep>*{width:100%}:host .description{font-size:12px;color:var(--dui-text-light)}:host.left-aligned .label{text-align:left}.error{margin-top:2px;color:var(--dui-color-red)}\n"], dependencies: [{ kind: "pipe", type: KeyValuePipe, name: "keyvalue" }] }); }, 'FormRowComponent', '!3!>"!3#>$!3%>&!3\'>(P7)3*8P"2+"0,!3-s>.!3/s>05w1']; } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: FormRowComponent, decorators: [{ type: Component, args: [{ selector: 'dui-form-row', template: ` <div class="label" [style.width.px]="labelWidth()">{{ label() }}@if (description()) { <div class="description">{{ description() }}</div> }</div> <div class="field"> <ng-content></ng-content> @if (ngControl && ngControl.errors && ngControl.touched) { <div class="error"> @for (kv of ngControl.errors|keyvalue; track kv) { <div> {{ isString(kv.value) ? '' : kv.key }}{{ isString(kv.value) ? kv.value : '' }} </div> } </div> } </div>`, host: { '[class.left-aligned]': 'left()', }, imports: [KeyValuePipe], styles: [":host{display:flex}:host:not(:last-child){margin-bottom:12px}:host .label{width:30%;margin-right:8px;line-height:20px;text-align:right}:host .field{flex:1;padding-right:5px}:host .field ::ng-deep>*{width:100%}:host .description{font-size:12px;color:var(--dui-text-light)}:host.left-aligned .label{text-align:left}.error{margin-top:2px;color:var(--dui-color-red)}\n"] }] }], propDecorators: { ngControl: [{ type: ContentChild, args: [NgControl, { static: false }] }] } }); class FormComponent { constructor(cd, cdParent) { this.cd = cd; this.cdParent = cdParent; this.formGroup = (input.Ω = [[() => FormGroup, 'P7!']], input(new FormGroup({}))); this.disabled = (input.Ω = [[')']], input(false)); this.submit = (input.Ω = [['', 'PP"`"J/!']], input()); this.success = output(); this.error = output(); this.errorText = signal(''); this.submitting = signal(false); } onEnter(event) { if (this.submit() && event.key.toLowerCase() === 'enter' && event.target && event.target.tagName.toLowerCase() === 'input') { this.submitForm(); } } get invalid() { return this.formGroup().invalid; } async submitForm() { if (this.disabled()) return; if (this.submitting()) return; const formGroup = this.formGroup(); if (formGroup.invalid) return; this.errorText.set(''); this.submitting.set(true); try { const submit = this.submit(); if (submit) { try { await submit(); this.success.emit(); } catch (error) { this.error.emit(error); if (error.errors && error.errors[0]) { //we got a validation-like error object for (const item of error.errors) { const control = formGroup.get(item.path); if (control) { control.setErrors({ ...control.errors, [item.code]: item.message, }); } } } else { this.errorText.set(error.message || error); } } } } finally { this.submitting.set(false); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: FormComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ChangeDetectorRef, skipSelf: true }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: FormComponent, isStandalone: true, selector: "dui-form", inputs: { formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, submit: { classPropertyName: "submit", publicName: "submit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { success: "success", error: "error" }, host: { listeners: { "keyup": "onEnter($event)" } }, ngImport: i0, template: ` <form [formGroup]="formGroup()" (submit)="$event.preventDefault();submitForm()"> <ng-content></ng-content> @if (errorText(); as text) { <div class="error">{{ text }}</div> } </form> `, isInline: true, styles: [":host{display:block;margin-top:15px}.error{padding:5px;color:var(--dui-color-red)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }] }); } static { this.__type = ['formGroup', function () { return (input.Ω = [[() => FormGroup, 'P7!']], input(new FormGroup({}))); }, 'disabled', function () { return (input.Ω = [[')']], input(false)); }, 'submit', function () { return (input.Ω = [['', 'PP"`"J/!']], input()); }, 'success', function () { return output(); }, 'error', function () { return output(); }, 'errorText', function () { return signal(''); }, 'submitting', function () { return signal(false); }, () => ChangeDetectorRef, 'cd', () => ChangeDetectorRef, 'cdParent', 'constructor', 'event', 'onEnter', 'submitForm', '\u0275fac', function () { return i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: FormComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ChangeDetectorRef, skipSelf: true }], target: i0.ɵɵFactoryTarget.Component }); }, '\u0275cmp', function () { return i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: FormComponent, isStandalone: true, selector: "dui-form", inputs: { formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, submit: { classPropertyName: "submit", publicName: "submit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { success: "success", error: "error" }, host: { listeners: { "keyup": "onEnter($event)" } }, ngImport: i0, template: ` <form [formGroup]="formGroup()" (submit)="$event.preventDefault();submitForm()"> <ng-content></ng-content> @if (errorText(); as text) { <div class="error">{{ text }}</div> } </form> `, isInline: true, styles: [":host{display:block;margin-top:15px}.error{padding:5px;color:var(--dui-color-red)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }] }); }, 'FormComponent', '!3!>"!3#>$!3%>&!3\'>(!3)>*!3+>,!3->.PP7/20<P7122<"03P!24"05!P"06!37s>8!39s>:5w;']; } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: FormComponent, decorators: [{ type: Component, args: [{ selector: 'dui-form', template: ` <form [formGroup]="formGroup()" (submit)="$event.preventDefault();submitForm()"> <ng-content></ng-content> @if (errorText(); as text) { <div class="error">{{ text }}</div> } </form> `, imports: [FormsModule, ReactiveFormsModule], styles: [":host{display:block;margin-top:15px}.error{padding:5px;color:var(--dui-color-red)}\n"] }] }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ChangeDetectorRef, decorators: [{ type: SkipSelf }] }], propDecorators: { onEnter: [{ type: HostListener, args: ['keyup', ['$event']] }] } }); function ngValueAccessor(clazz) { return { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => clazz), multi: true, }; } ngValueAccessor.__type = ['Type', 'clazz', 'ngValueAccessor', 'P"w!2""/#']; class ValueAccessorBase { constructor() { this._ngControlFetched = false; this.value = (model.Ω = [['P!-J']], model(undefined)); this.disabled = model(false); this._changedCallback = []; this._touchedCallback = []; this.required = input(false); this.injector = inject(Injector); } get isDisabled() { if (this.formComponent && this.formComponent.disabled()) return true; if (this.ngControl) { return !!this.ngControl.disabled; } return this.disabled(); } get isValid() { return this.valid === true; } get isError() { if (undefined === this.error && this.ngControl) { return (this.ngControl.dirty || this.ngControl.touched) && this.ngControl.invalid; } return this.error; } get ngControl() { if (!this._ngControlFetched) { try { this._ngControl = this.injector.get(NgControl); } catch (e) { } this._ngControlFetched = true; } return this._ngControl; } setDisabledState(isDisabled) { this.disabled.set(isDisabled); } ngOnDestroy() { } /** * This is called whenever value() needs to update. Either through Angular forms or through setValue(). * Do not call this method in UI code, use setValue() instead so that angular forms informed about the change. * * This is a good place to normalize values whenever they change. (like clamping a number to a range) */ writeValue(value) { this.value.set(value); } /** * Set the value from UI code. */ setValue(value) { this.writeValue(value); for (const callback of this._changedCallback) { callback(this.value()); } } /** * Call this method to signal Angular's form or other users that this widget has been touched. */ touch() { for (const callback of this._touchedCallback) { callback(); } } registerOnChange(fn) { this._changedCallback.push(fn); } registerOnTouched(fn) { this._touchedCallback.push(fn); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: ValueAccessorBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.4", type: ValueAccessorBase, isStandalone: true, inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, valid: { classPropertyName: "valid", publicName: "valid", isSignal: false, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: false, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", disabled: "disabledChange" }, host: { properties: { "class.disabled": "this.isDisabled", "class.valid": "this.isValid", "class.error": "this.isError", "class.required": "this.required" } }, ngImport: i0 }); } static { this.__type = ['T', () => NgControl, '_ngControl', '_ngControlFetched', function () { return false; }, 'value', function () { return (model.Ω = [['P!-J']], model(undefined)); }, 'disabled', function () { return model(false); }, 'valid', 'error', () => FormComponent, 'formComponent', '', '_changedCallback', function () { return []; }, '_touchedCallback', function () { return []; }, 'required', function () { return input(false); }, 'injector', function () { return inject(Injector); }, 'isDisabled', 'setDisabledState', 'ngOnDestroy', 'writeValue', 'setValue', 'touch', 'fn', 'registerOnChange', 'registerOnTouched', '\u0275fac', function () { return i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: ValueAccessorBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }, '\u0275dir', function () { return i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.4", type: ValueAccessorBase, isStandalone: true, inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, valid: { classPropertyName: "valid", publicName: "valid", isSignal: false, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: false, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", disabled: "disabledChange" }, host: { properties: { "class.disabled": "this.isDisabled", "class.valid": "this.isValid", "class.error": "this.isError", "class.required": "this.required" } }, ngImport: i0 }); }, 'ControlValueAccessor', 'OnDestroy', 'ValueAccessorBase', 'b!P7"3#8;)3$;>%!3&>\'!3(>))3*8)3+8P7,3-8<PPe#!-J2&$/.F3/<>0P$/.F31<>2!!!!33>4!35<>6!P)27$08P$09Pe"!2&8"0:PPe#!-J2&"0;P"0<PPPe$!-J2&$/.2="0>PP$/.2="0?!3@s>A!3Bs>C5"wD"wEx#wF']; } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: ValueAccessorBase, decorators: [{ type: Directive }], propDecorators: { valid: [{ type: Input }], error: [{ type: Input }], isDisabled: [{ type: HostBinding, args: ['class.disabled'] }], isValid: [{ type: HostBinding, args: ['class.valid'] }], isError: [{ type: HostBinding, args: ['class.error'] }], required: [{ type: HostBinding, args: ['class.required'] }] } }); const electron = 'undefined' === typeof window ? undefined : window.electron || (window.require ? window.require('electron') : undefined); class BrowserWindow { constructor(window) { this.window = window; } isElectron() { return !!this.window?.setVibrancy; } getWindow() { return this.window; } setVibrancy(vibrancy) { if (!this.window) return; if (this.window.setVibrancy) { this.window.setVibrancy(vibrancy); } else { console.warn('setVibrancy is not supported by this window.'); } } addListener(event, listener) { if (!this.window) return; if (this.window.addEventListener) { this.window.addEventListener(event, listener); } else if (this.window.addListener) { this.window.addListener(event, listener); } } removeListener(event, listener) { if (!this.window) return; if (this.window.removeEventListener) { this.window.removeEventListener(event, listener); } else if (this.window.removeListener) { this.window.removeListener(event, listener); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: BrowserWindow, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: BrowserWindow, providedIn: 'root' }); } static { this.__type = ['ElectronOrBrowserWindow', 'window', 'constructor', 'isElectron', 'getWindow', 'vibrancy', 'setVibrancy', 'event', 'listener', 'addListener', 'removeListener', '\u0275fac', function () { return i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: BrowserWindow, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); }, '\u0275prov', function () { return i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: BrowserWindow, providedIn: 'root' }); }, 'BrowserWindow', 'P"w!2"8;"0#P"0$PP"w!-J0%P&2&$0\'P&2("2)$0*P&2("2)$0+!3,s>-!3.s>/5w0']; } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: BrowserWindow, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT] }] }] }); class Electron { static getRemote() { if (!electron) { throw new Error('No Electron available.'); } return electron.remote; } static getIpc() { if (!electron) { throw new Error('No Electron available.'); } return electron.ipcRenderer; } static isAvailable() { return !!electron; } static getRemoteOrUndefined() { return electron ? electron.remote : undefined; } static getProcess() { return Electron.getRemote().process; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: Electron, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: Electron, providedIn: 'root' }); } static { this.__type = ['getRemote', 'getIpc', 'isAvailable', 'getRemoteOrUndefined', 'getProcess', '\u0275fac', function () { return i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: Electron, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }, '\u0275prov', function () { return i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: Electron, providedIn: 'root' }); }, 'Electron', 'P"0!sP"0"sP"0#sP"0$sP"0%s!3&s>\'!3(s>)5w*']; } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: Electron, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class AsyncEventEmitter extends EventEmitter { emit(value) { super.emit(value); } subscribe(generatorOrNext, error, complete) { return super.subscribe(generatorOrNext, error, complete); } } class ExecutionState { constructor(cd, func) { this.cd = cd; this.func = func; this.running = false; this.error = ''; } async execute(...args) { if (this.running) { throw new Error('Executor still running'); } this.running = true; this.error = ''; this.cd.detectChanges(); try { return await this.func(...args); } catch (error) { this.error = error.message || error.toString(); throw error; } finally { this.running = false; this.cd.detectChanges(); } } } /** * Checks if `target` is children of `parent` or if `target` is `parent`. */ function isTargetChildOf(target, parent) { if (!target) return false; if (target === parent) return true; return parent.contains(target); } function isMacOs() { if ('undefined' === typeof navigator) return false; return navigator.platform.indexOf('Mac') > -1; } function isWindows() { if ('undefined' === typeof navigator) return false; return navigator.platform.indexOf('Win') > -1; } /** * Checks if `target` is children of `parent` or if `target` is `parent`. */ function findParentWithClass(start, className) { let current = start; do { if (current.classList.contains(className)) return current; current = current.parentElement; } while (current); return undefined; } function triggerResize() { if ('undefined' === typeof window) return; nextTick(() => { window.dispatchEvent(new Event('resize')); }); } /** * Observes focus changes on target elements and emits when focus is lost. * * This is used to track multi-element focus changes, such as when a user clicks from a dropdown toggle into the dropdown menu. */ function focusWatcher(target, allowedFocuses = [], onBlur, customChecker) { const doc = target.ownerDocument; if (doc.body.tabIndex === -1) doc.body.tabIndex = 1; let currentlyFocused = target; let subscribed = true; function isFocusAllowed() { if (!currentlyFocused) { return false; } if (currentlyFocused === target || target.contains(currentlyFocused)) { return true; } for (const focus of allowedFocuses) { if (focus && currentlyFocused === focus || focus.contains(currentlyFocused)) { return true; } } return customChecker ? customChecker(currentlyFocused) : false; } function emitBlurIfNeeded(event) { if (!currentlyFocused) { // Shouldn't be possible to have no element at all with focus. // This means usually that the item that had previously focus was deleted. currentlyFocused = target; } if (subscribed && !isFocusAllowed()) { onBlur(event); unsubscribe(); return true; } return false; } function onFocusOut(event) { currentlyFocused = null; emitBlurIfNeeded(event); } function onFocusIn(event) { currentlyFocused = event.target; emitBlurIfNeeded(event); } function onMouseDown(event) { currentlyFocused = event.target; if (emitBlurIfNeeded(event)) { event.stopImmediatePropagation(); event.preventDefault(); } } doc.addEventListener('mousedown', onMouseDown, true); doc.addEventListener('focusin', onFocusIn); doc.addEventListener('focusout', onFocusOut); function unsubscribe() { if (!subscribed) return; subscribed = false; doc.removeEventListener('mousedown', onMouseDown, true); doc.removeEventListener('focusin', onFocusIn); doc.removeEventListener('focusout', onFocusOut); } return unsubscribe; } function redirectScrollableParentsToWindowResize(node, passive = true) { const parents = getScrollableParents(node); function redirect() { window.dispatchEvent(new Event('resize')); } for (const parent of parents) { parent.addEventListener('scroll', redirect, { passive }); } return () => { for (const parent of parents) { parent.removeEventListener('scroll', redirect); } }; } function getScrollableParents(node) { const scrollableParents = []; let parent = node.parentNode; while (parent) { if (!(parent instanceof Element)) { parent = parent.parentNode; continue; } const computedStyle = window.getComputedStyle(parent); const overflow = computedStyle.getPropertyValue('overflow'); if (overflow === 'overlay' || overflow === 'scroll' || overflow === 'auto') { scrollableParents.push(parent); } parent = parent.parentNode; } return scrollableParents; } function trackByIndex(index) { return index; } class DuiDocument { constructor() { this.document = inject(DOCUMENT, { optional: true }); this.activeElement = (signal.Ω = [['P!-J']], signal(undefined)); this.onFocus = () => { if (!this.document) return; this.activeElement.set(this.document.activeElement || undefined); }; this.document?.addEventListener('focusin', this.onFocus); this.document?.addEventListener('focusout', this.onFocus); } ngOnDestroy() { this.document?.removeEventListener('focusin', this.onFocus); this.document?.removeEventListener('focusout', this.onFocus); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: DuiDocument, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: DuiDocument, providedIn: 'root' }); } static { this.__type = ['document', function () { return inject(DOCUMENT, { optional: true }); }, 'activeElement', function () { return (signal.Ω = [['P!-J']], signal(undefined)); }, 'onFocus', function () { return () => { if (!this.document) return; this.activeElement.set(this.document.activeElement || undefined); }; }, 'constructor', 'ngOnDestroy', '\u0275fac', function () { return i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: DuiDocument, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }, '\u0275prov', function () { return i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: DuiDocument, providedIn: 'root' }); }, 'OnDestroy', 'DuiDocument', '!3!>"!3#>$!3%>&P"0\'P"0(!3)s>*!3+s>,5"w-x"w.']; } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: DuiDocument, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [] }); /* * Deepkit Framework * Copyright (C) 2021 Deepkit UG, Marc J. Schmidt * * This program is free software: you can redistribute it and/or modify * it under the terms of the MIT License. * * You should have received a copy of the MIT License along with this program. */ function injectDocument() { return inject(DOCUMENT, { optional: true }) || undefined; } injectDocument.__type = ['injectDocument', 'PP!-J/!']; function injectElementRef() { return inject(ElementRef); } injectElementRef.__type = [() => ElementRef, 'injectElementRef', 'PP!7!/"']; function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } clamp.__type = ['value', 'min', 'max', 'clamp', 'P\'2!\'2"\'2#\'/$']; class OpenExternalDirective { constructor(element) { this.element = element; this.openExternal = (input.Ω = [['&']], input('')); this.href = (input.Ω = [['&']], input('')); // this.element.nativeElement.href = '#'; } ngOnChanges() { // this.element.nativeElement.href = this.getLink(); if (this.element.nativeElement instanceof HTMLAnchorElement) { this.element.nativeElement.setAttribute('href', this.getLink()); } } getLink() { return this.openExternal() || this.href(); } onClick(event) { event.stopPropagation(); event.preventDefault(); if (Electron.isAvailable()) { event.preventDefault(); Electron.getRemote().shell.openExternal(this.getLink()); } else { window.open(this.getLink(), '_blank'); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: OpenExternalDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.4", type: OpenExternalDirective, isStandalone: true, selector: "[openExternal], a[href]", inputs: { openExternal: { classPropertyName: "openExternal", publicName: "openExternal", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick($event)" } }, usesOnChanges: true, ngImport: i0 }); } static { this.__type = ['openExternal', function () { return (input.Ω = [['&']], input('')); }, 'href', function () { return (input.Ω = [['&']], input('')); }, () => ElementRef, 'element', 'constructor', 'ngOnChanges', 'getLink', 'event', 'onClick', '\u0275fac', function () { return i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: OpenExternalDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }, '\u0275dir', function () { return i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.4", type: OpenExternalDirective, isStandalone: true, selector: "[openExternal], a[href]", inputs: { openExternal: { classPropertyName: "openExternal", publicName: "openExternal", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick($event)" } }, usesOnChanges: true, ngImport: i0 }); }, 'OnChanges', 'OpenExternalDirective', '!3!>"!3#>$PP7%2&;"0\'P$0(P"0)P!2*"0+!3,s>-!3.s>/5"w0x"w1']; } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: OpenExternalDirective, decorators: [{ type: Directive, args: [{ selector: '[openExternal], a[href]' }] }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { onClick: [{ type: HostListener, args: ['click', ['$event']] }] } }); let lastScheduleResize; function scheduleWindowResizeEvent() { if (lastScheduleResize) cancelAnimationFrame(lastScheduleResize); lastScheduleResize = nextTick(() => { window.dispatchEvent(new Event('resize')); lastScheduleResize = undefined; }); } scheduleWindowResizeEvent.__type = ['scheduleWindowResizeEvent', 'P"/!']; class TemplateContextTypeDirective { static ngTemplateContextGuard(dir, ctx) { return true; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: TemplateContextTypeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.4", type: TemplateContextTypeDirective, isStandalone: true, selector: "ng-template[templateType]", inputs: { templateType: "templateType" }, ngImport: i0 }); } static { this.__type = ['T', 'templateType', () => TemplateContextTypeDirective, 'dir', 'ctx', 'ngTemplateContextGuard', '\u0275fac', function () { return i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: TemplateContextTypeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }, '\u0275dir', function () { return i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.4", type: TemplateContextTypeDirective, isStandalone: true, selector: "ng-template[templateType]", inputs: { templateType: "templateType" }, ngImport: i0 }); }, 'TemplateContextTypeDirective', 'b!e!!3"<PPe#!7#2$#2%!0&s!3\'s>(!3)s>*5w+']; } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: TemplateContextTypeDirective, decorators: [{ type: Directive, args: [{ selector: 'ng-template[templateType]' }] }], propDecorators: { templateType: [{ type: Input }] } }); class OnDomCreationDirective { constructor() { this.onDomCreation = (output.Ω = [['!']], output()); this.onDomCreationDestroy = (output.Ω = [['!']], output()); this.element = injectElementRef(); } ngOnInit() { this.onDomCreation.emit(this.element.nativeElement); } ngOnDestroy() { this.onDomCreationDestroy.emit(this.element.nativeElement); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: OnDomCreationDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.4", type: OnDomCreationDirective, isStandalone: true, selector: "[onDomCreation]", outputs: { onDomCreation: "onDomCreation", onDomCreationDestroy: "onDomCreationDestroy" }, ngImport: i0 }); } static { this.__type = ['onDomCreation', function () { return (output.Ω = [['!']], output()); }, 'onDomCreationDestroy', function () { return (output.Ω = [['!']], output()); }, () => ElementRef, 'element', function () { return injectElementRef(); }, 'ngOnInit', 'ngOnDestroy', '\u0275fac', function () { return i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: OnDomCreationDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }, '\u0275dir', function () { return i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.4", type: OnDomCreationDirective, isStandalone: true, selector: "[onDomCreation]", outputs: { onDomCreation: "onDomCreation", onDomCreationDestroy: "onDomCreationDestroy" }, ngImport: i0 }); }, 'OnInit', 'OnDestroy', 'OnDomCreationDirective', '!3!>"!3#>$P!7%3&;>\'P"0(P"0)!3*s>+!3,s>-5"w."w/x#w0']; } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: OnDomCreationDirective, decorators: [{ type: Directive, args: [{ selector: '[onDomCreation]' }] }] }); const __ΩRegisterEventListenerRemove = ['', 'RegisterEventListenerRemove', 'P$/!w"y']; function registerEventListener(element, type, listener, options) { element.addEventListener(type, listener, options); return () => element.removeEventListener(type, listener, options); } registerEventListener.__type = ['element', 'type', 'ev', '', 'listener', 'options', () => __ΩRegisterEventListenerRemove, 'registerEventListener', 'P"2!"2"P""f2#"/$2%!2&8n\'/(']; function __assignType$i(fn, args) { fn.__type = args; return fn; } const __ΩPositionObserverDisconnect = ['', 'PositionObserverDisconnect', 'P$/!w"y']; function observePosition(element, callback, debugPosition = false) { if ('undefined' === typeof IntersectionObserver) return () => undefined; let lastObserver; const resizeObserver = new ResizeObserver(() => { setupObserver(); }); resizeObserver.observe(element); const debug = debugPosition ? document.createElement('div') : undefined; if (debug) { debug.style.position = 'fixed'; debug.style.zIndex = '999999'; debug.style.backgroundColor = 'rgba(255, 0, 0, 0.5)'; debug.style.pointerEvents = 'none'; document.body.appendChild(debug); } function setupObserver() { const box = element.getBoundingClientRect(); if (box.width === 0 || box.height === 0) { return; } const vw = document.body.clientWidth; const vh = window.innerHeight; const top = Math.floor(box.top); const left = Math.floor(box.left); const right = Math.floor(vw - box.right); const bottom = Math.floor(vh - box.bottom); const rootMargin = `${-top}px ${-right}px ${-bottom}px ${-left}px`; if (debug) { debug.style.top = `${top}px`; debug.style.left = `${left}px`; debug.style.right = `${right}px`; debug.style.bottom = `${bottom}px`; } const size = box.width > box.height ? box.width : box.height; const onePixelInPercent = 1 / size; // To not create a new IntersectionObserver every event, we use several thresholds. // To not create too many thresholds (when the element is very big), // we generate 100 items, each the size of one pixel in percent. // In the callback we rebuild a new observer when intersectionRatio is // either bigger than the biggest threshold or smaller than the smallest threshold. const thresholdCount = Math.min(size, 100); const thresholds = Array.from({ length: thresholdCount }, __assignType$i((_, i) => 1 - ((i + 1) * onePixelInPercent), ['_', 'i', '', 'P"2!"2""/#'])); // console.log('rootMargin', rootMargin, box, thresholds); const minRatio = thresholds[thresholds.length - 1]; if (lastObserver) lastObserver.disconnect(); lastObserver = new IntersectionObserver(__assignType$i((entries, observer) => { for (const entry of entries) { callback(entry.boundingClientRect); } if (entries[0].intersectionRatio <= minRatio) { observer.disconnect(); setupObserver(); } }, ['entries', 'observer', '', 'P"2!"2""/#']), { root: null, rootMargin, threshold: thresholds }); lastObserver.observe(element); } setupObserver.__type = ['setupObserver', 'P"/!']; setupObserver(); return () => { lastObserver?.disconnect(); lastObserver = undefined; resizeObserver.disconnect(); if (debug) { debug.remove(); } }; } observePosition.__type = ['element', 'entry', '', 'callback', 'debugPosition', () => __ΩPositionObserverDisconnect, 'observePosition', 'P!2!P!2"$/#2$"2%n&/\'']; class PositionChangeDirective { constructor() { this.duiPositionChange = (output.Ω = [['"']], output()); this.elementRef = injectElementRef(); this.observer = observePosition(this.elementRef.nativeElement, __assignType$i((rect) => { this.duiPositionChange.emit(rect); }, ['rect', '', 'P"2!"/"'])); } ngOnInit() { } ngOnDestroy() { this.observer(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: PositionChangeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.4", type: PositionChangeDirective, isStandalone: true, selector: "[duiPositionChange]", outputs: { duiPositionChange: "duiPositionChange" }, ngImport: i0 }); } static { this.__type = ['duiPositionChange', function () { return (output.Ω = [['"']], output()); }, 'elementRef', function () { return injectElementRef(); }, 'observer', function () { return observePosition(this.elementRef.nativeElement, __assignType$i((rect) => { this.duiPositionChange.emit(rect); }, ['rect', '', 'P"2!"/"'])); }, 'ngOnInit', 'ngOnDestroy', '\u0275fac', function () { return i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: PositionChangeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }, '\u0275dir', function () { return i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.4", type: PositionChangeDirective, isStandalone: true, selector: "[duiPositionChange]", outputs: { duiPositionChange: "duiPositionChange" }, ngImport: i0 }); }, 'OnInit', 'OnDestroy', 'PositionChangeDirective', '!3!>"!3#>$!3%>&P"0\'P"0(!3)s>*!3+s>,5"w-"w.x#w/']; } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: PositionChangeDirective, decorators: [{ type: Directive, args: [{ selector: '[duiPositionChange]', }] }] }); const __ΩBuiltTemplateItem = ['BuiltTemplateItem', 'P&"LMw!y']; // This is probably broken for current Electron versions, but we keep it for future work function buildElectronMenuTemplate(menu) { const submenu = []; for (const item of menu.children()) { if (item === menu) continue; if (!item.validOs()) { continue; } submenu.push(buildElectronMenuTemplate(item)); } const result = { click: () => { menu.active(); }, }; const label = menu.label(); if (label) result['label'] = label; const sublabel = menu.sublabel(); if (sublabel) result['sublabel'] = sublabel; if (!menu.enabled()) result['enabled'] = false; if (menu.type) result['type'] = menu.type; const accelerator = menu.accelerator(); if (accelerator) result['accelerator'] = accelerator; const role = menu.role(); if (role) result['role'