@deepkit/desktop-ui
Version:
Library for desktop UI widgets in Angular 10+
857 lines (846 loc) • 837 kB
JavaScript
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'