@yuuvis/client-framework 2.4.4 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/common/lib/components/busy-overlay/busy-overlay.component.d.ts +10 -0
  2. package/common/lib/components/busy-overlay/busy-overlay.interface.d.ts +4 -0
  3. package/common/lib/components/dialog/dialog.component.d.ts +5 -1
  4. package/common/lib/components/index.d.ts +1 -0
  5. package/common/lib/directives/busy-overlay.directive.d.ts +51 -13
  6. package/fesm2022/yuuvis-client-framework-actions.mjs +1 -1
  7. package/fesm2022/yuuvis-client-framework-actions.mjs.map +1 -1
  8. package/fesm2022/yuuvis-client-framework-common.mjs +166 -74
  9. package/fesm2022/yuuvis-client-framework-common.mjs.map +1 -1
  10. package/fesm2022/yuuvis-client-framework-forms.mjs +97 -76
  11. package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
  12. package/fesm2022/yuuvis-client-framework-object-details.mjs +28 -32
  13. package/fesm2022/yuuvis-client-framework-object-details.mjs.map +1 -1
  14. package/fesm2022/yuuvis-client-framework-object-flavor.mjs +2 -2
  15. package/fesm2022/yuuvis-client-framework-object-flavor.mjs.map +1 -1
  16. package/fesm2022/yuuvis-client-framework-object-relationship.mjs +3 -3
  17. package/fesm2022/yuuvis-client-framework-object-relationship.mjs.map +1 -1
  18. package/fesm2022/yuuvis-client-framework-object-summary.mjs +1 -1
  19. package/fesm2022/yuuvis-client-framework-object-summary.mjs.map +1 -1
  20. package/fesm2022/yuuvis-client-framework-object-versions.mjs +1 -1
  21. package/fesm2022/yuuvis-client-framework-object-versions.mjs.map +1 -1
  22. package/fesm2022/yuuvis-client-framework-tile-list.mjs +1 -1
  23. package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
  24. package/fesm2022/yuuvis-client-framework-widget-grid.mjs +2 -2
  25. package/fesm2022/yuuvis-client-framework-widget-grid.mjs.map +1 -1
  26. package/forms/lib/elements/catalog/catalog.component.d.ts +4 -1
  27. package/forms/lib/elements/data-grid/model/data-grid.interface.d.ts +6 -0
  28. package/forms/lib/elements/organization/organization.component.d.ts +6 -10
  29. package/object-details/lib/object-details-header/object-details-header.component.d.ts +9 -7
  30. package/object-details/lib/object-details-shell/object-details-shell.component.d.ts +3 -1
  31. package/object-details/lib/object-details.component.d.ts +3 -1
  32. package/object-details/lib/object-metadata/object-metadata.component.d.ts +2 -2
  33. package/package.json +16 -16
@@ -1,29 +1,33 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, ChangeDetectionStrategy, Component, inject, ElementRef, Input, Directive, computed, EnvironmentInjector, ApplicationRef, createComponent, HostBinding, EventEmitter, HostListener, Output, NgZone, output, contentChildren, forwardRef, NgModule, signal, Injectable } from '@angular/core';
2
+ import { input, ChangeDetectionStrategy, Component, inject, ElementRef, Input, Directive, computed, effect, output, signal, EnvironmentInjector, ViewContainerRef, EventEmitter, HostListener, Output, NgZone, contentChildren, HostBinding, forwardRef, NgModule, Injectable } from '@angular/core';
3
3
  import { CommonModule, DOCUMENT } from '@angular/common';
4
4
  import { MatButtonModule } from '@angular/material/button';
5
5
  import * as i2 from '@angular/material/dialog';
6
6
  import { MatDialogActions, MatDialogTitle, MatDialogContent, MAT_DIALOG_DATA, MatDialogModule, MatDialog } from '@angular/material/dialog';
7
7
  import * as i1 from '@ngx-translate/core';
8
8
  import { TranslateModule, TranslateService } from '@ngx-translate/core';
9
- import { YmtButtonDirective } from '@yuuvis/material';
9
+ import { YmtButtonDirective, YmtIconButtonDirective } from '@yuuvis/material';
10
10
  import { TranslateModule as TranslateModule$1, Utils, RetentionService, LocaleDatePipe } from '@yuuvis/client-core';
11
11
  import { MatProgressSpinner } from '@angular/material/progress-spinner';
12
+ import * as i1$1 from '@angular/material/icon';
13
+ import { MatIconModule } from '@angular/material/icon';
12
14
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
13
15
  import { Subject, fromEvent, merge, timer, of } from 'rxjs';
14
16
  import { debounceTime, tap, filter, switchMap, map, takeUntil } from 'rxjs/operators';
15
17
  import { NG_VALUE_ACCESSOR, NgControl, FormControlDirective, FormControlName, NgModel } from '@angular/forms';
16
18
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
17
- import * as i2$1 from '@angular/material/icon';
18
- import { MatIconModule } from '@angular/material/icon';
19
19
 
20
20
  class DialogComponent {
21
21
  constructor() {
22
+ this.headertitle = input(null);
23
+ /**
24
+ * @deprecated use headertitle instead
25
+ */
22
26
  this.headertitel = input(null);
23
27
  }
24
28
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
25
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: DialogComponent, isStandalone: true, selector: "yuv-dialog", inputs: { headertitel: { classPropertyName: "headertitel", publicName: "headertitel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
26
- @let title = headertitel();
29
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: DialogComponent, isStandalone: true, selector: "yuv-dialog", inputs: { headertitle: { classPropertyName: "headertitle", publicName: "headertitle", isSignal: true, isRequired: false, transformFunction: null }, headertitel: { classPropertyName: "headertitel", publicName: "headertitel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
30
+ @let title = headertitle() ?? headertitel();
27
31
  @if (title) {
28
32
  <h2 mat-dialog-title>{{ title }}</h2>
29
33
  }
@@ -39,7 +43,7 @@ class DialogComponent {
39
43
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DialogComponent, decorators: [{
40
44
  type: Component,
41
45
  args: [{ selector: 'yuv-dialog', imports: [TranslateModule, MatDialogActions, MatDialogTitle, MatDialogContent], template: `
42
- @let title = headertitel();
46
+ @let title = headertitle() ?? headertitel();
43
47
  @if (title) {
44
48
  <h2 mat-dialog-title>{{ title }}</h2>
45
49
  }
@@ -58,7 +62,7 @@ class ConfirmComponent {
58
62
  this.dialogData = inject(MAT_DIALOG_DATA);
59
63
  }
60
64
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ConfirmComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
61
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: ConfirmComponent, isStandalone: true, selector: "yuv-confirm", ngImport: i0, template: "<yuv-dialog [headertitel]=\"dialogData.title || ''\">\n <main>{{ dialogData.message }}</main>\n <footer>\n @if (!dialogData.hideCancelButton) {\n <button ymtButton=\"secondary\" mat-dialog-close type=\"button\">\n {{ dialogData.cancelLabel || ('yuv.confirm.cancel' | translate) }}\n </button>\n }\n <button ymtButton=\"primary\" type=\"button\" [mat-dialog-close]=\"true\">{{ dialogData.confirmLabel || ('yuv.confirm.confirm' | translate) }}</button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:contents}:host main{padding:var(--ymt-spacing-m)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: TranslateModule$1 }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i2.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitel"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }] }); }
65
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: ConfirmComponent, isStandalone: true, selector: "yuv-confirm", ngImport: i0, template: "<yuv-dialog [headertitel]=\"dialogData.title || ''\">\n <main>{{ dialogData.message }}</main>\n <footer>\n @if (!dialogData.hideCancelButton) {\n <button ymtButton=\"secondary\" mat-dialog-close type=\"button\">\n {{ dialogData.cancelLabel || ('yuv.confirm.cancel' | translate) }}\n </button>\n }\n <button ymtButton=\"primary\" type=\"button\" [mat-dialog-close]=\"true\">{{ dialogData.confirmLabel || ('yuv.confirm.confirm' | translate) }}</button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:contents}:host main{padding:var(--ymt-spacing-m)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: TranslateModule$1 }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i2.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitle", "headertitel"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }] }); }
62
66
  }
63
67
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ConfirmComponent, decorators: [{
64
68
  type: Component,
@@ -138,108 +142,196 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
138
142
  }]
139
143
  }] });
140
144
 
145
+ class BusyOverlayComponent {
146
+ constructor() {
147
+ this.config = input();
148
+ this.error = input(undefined);
149
+ this.x = effect(() => {
150
+ console.log('BusyOverlayComponent error changed:', this.error());
151
+ });
152
+ this.errorDismiss = output();
153
+ }
154
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: BusyOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
155
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: BusyOverlayComponent, isStandalone: true, selector: "yuv-busy-overlay", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { errorDismiss: "errorDismiss" }, host: { properties: { "class.error": "!!error()", "class.blured": "!!config()?.blur", "style.--backdrop-background": "config()?.backdropColor || \"var(--ymt-surface-app)\"" } }, ngImport: i0, template: "<div class=\"backdrop\"></div>\n\n@let e = error();\n@if (e) {\n <div class=\"error\">\n <button ymtIconButton icon-button-size=\"small\" (click)=\"errorDismiss.emit()\">\n <mat-icon>close</mat-icon>\n </button>\n <p>{{ e }}</p>\n </div>\n} @else {\n <mat-progress-spinner class=\"ymt-progress-spinner--giant\" [mode]=\"'indeterminate'\"></mat-progress-spinner>\n}\n", styles: [":host{position:absolute;transition:opacity .2s;inset:0;display:grid;place-items:center;z-index:5}:host.blured{backdrop-filter:blur(2px)}:host{--mdc-circular-progress-active-indicator-color: currentColor}:host .error,:host mat-progress-spinner{opacity:0;animation:fadeIn .2s ease-in forwards;animation-delay:.2s}:host .error{display:flex;flex-direction:column;background-color:var(--ymt-danger-container);color:var(--ymt-on-danger-container);border:var(--ymt-danger);padding:var(--ymt-spacing-xs);border-radius:var(--ymt-corner-xs);max-width:60ch;margin:var(--ymt-spacing-m);overflow-y:auto;align-items:end}:host .error p{margin:var(--ymt-spacing-m)}:host .backdrop{position:absolute;inset:0;background-color:rgb(from var(--backdrop-background) r g b/.5);animation:fadeIn .2s ease-in}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }] }); }
156
+ }
157
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: BusyOverlayComponent, decorators: [{
158
+ type: Component,
159
+ args: [{ selector: 'yuv-busy-overlay', imports: [CommonModule,
160
+ YmtIconButtonDirective,
161
+ MatIconModule,
162
+ MatProgressSpinner], host: {
163
+ '[class.error]': '!!error()',
164
+ '[class.blured]': '!!config()?.blur',
165
+ '[style.--backdrop-background]': 'config()?.backdropColor || "var(--ymt-surface-app)"'
166
+ }, template: "<div class=\"backdrop\"></div>\n\n@let e = error();\n@if (e) {\n <div class=\"error\">\n <button ymtIconButton icon-button-size=\"small\" (click)=\"errorDismiss.emit()\">\n <mat-icon>close</mat-icon>\n </button>\n <p>{{ e }}</p>\n </div>\n} @else {\n <mat-progress-spinner class=\"ymt-progress-spinner--giant\" [mode]=\"'indeterminate'\"></mat-progress-spinner>\n}\n", styles: [":host{position:absolute;transition:opacity .2s;inset:0;display:grid;place-items:center;z-index:5}:host.blured{backdrop-filter:blur(2px)}:host{--mdc-circular-progress-active-indicator-color: currentColor}:host .error,:host mat-progress-spinner{opacity:0;animation:fadeIn .2s ease-in forwards;animation-delay:.2s}:host .error{display:flex;flex-direction:column;background-color:var(--ymt-danger-container);color:var(--ymt-on-danger-container);border:var(--ymt-danger);padding:var(--ymt-spacing-xs);border-radius:var(--ymt-corner-xs);max-width:60ch;margin:var(--ymt-spacing-m);overflow-y:auto;align-items:end}:host .error p{margin:var(--ymt-spacing-m)}:host .backdrop{position:absolute;inset:0;background-color:rgb(from var(--backdrop-background) r g b/.5);animation:fadeIn .2s ease-in}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}\n"] }]
167
+ }] });
168
+
141
169
  /**
142
170
  * A directive that will overlay its host component with a translucent background
143
171
  * and a loading spinner once the condition resolves with true. This is useful for example to
144
172
  * prevent user intercation while component data is loading or some processing is done.
145
173
  *
146
- * It'll also set the `inert` attribute on the host element. This will disable the host and
147
- * all elements inside (like buttons, inputs etc.)
174
+ * It'll also prevent the overlayed element from beiong interacted with.
148
175
  *
149
- * @example
150
- * <div class="result-list" [yuvBusyOverlay]="waitingForServerResponse">...</div>
176
+ * ```html
177
+ * <div class="data-panel" [yuvBusyOverlay]="isLoadingData">...</div>
178
+ * ```
179
+ * Setting a `yuvBusyError` will replace the loading spinner by the provided error message.
180
+ * You need to keep the `yuvBusyOverlay` condition true to show the error.
181
+ * The error element rendered has a dismiss/close action that trigger the `yuvBusyErrorDismiss`
182
+ * output event, that you then can use to set the busy condition to false.
183
+ *
184
+ * ```html
185
+ * <div class="result-list"
186
+ * [yuvBusyOverlay]="waitingForServerResponse"
187
+ * (yuvBusyErrorDismiss)="waitingForServerResponse = false"
188
+ * [yuvBusyError]="errorMessage">
189
+ * ...
190
+ * </div>
191
+ * ```
192
+ *
193
+ * ```ts
194
+ * // in your component code
195
+ * this.waitingForServerResponse = true;
196
+ * fetchData().subscribe({
197
+ * next: (data) => {
198
+ * ...
199
+ * this.waitingForServerResponse = false;
200
+ * }
201
+ * error: (err) => {
202
+ * this.errorMessage = 'Failed to load data from server: ' + err.message;
203
+ * }
204
+ * });
205
+ * ```
151
206
  *
152
207
  */
153
208
  class BusyOverlayDirective {
154
209
  constructor() {
155
- this.stylePosition = 'initial';
210
+ this.#initialStylePosition = signal('initial');
211
+ this.stylePosition = signal(this.#initialStylePosition());
156
212
  this.#elRef = inject(ElementRef);
157
213
  this.#environmentInjector = inject(EnvironmentInjector);
158
- this.#applicationRef = inject(ApplicationRef);
159
- this.#overlayId = null;
214
+ this.#vcRef = inject(ViewContainerRef);
215
+ /**
216
+ * The Boolean expression to evaluate as the condition for showing the busy overlay
217
+ */
218
+ this.yuvBusyOverlay = input(false);
219
+ this.#yuvBusyOverlayEffect = effect(() => {
220
+ const busy = this.yuvBusyOverlay();
221
+ if (busy === true) {
222
+ this.#addBusyOverlay();
223
+ }
224
+ else {
225
+ this.#removeBusyOverlay();
226
+ }
227
+ });
228
+ /**
229
+ * Configuration options for the busy overlay. These include
230
+ * e.g. backdrops bacckground color and whether to blur the
231
+ * overlayed content.
232
+ */
160
233
  this.yuvBusyOverlayConfig = input();
234
+ /**
235
+ * Error message to display in the overlay. If set, the loading spinner is replaced by the error message.
236
+ */
237
+ this.yuvBusyError = input();
238
+ this.#yuvBusyErrorEffect = effect(() => {
239
+ this.#busyOverlayComponentRef?.setInput('error', this.yuvBusyError());
240
+ });
241
+ /**
242
+ * Event emitted when the error message's dismiss action is triggered.
243
+ */
244
+ this.yuvBusyErrorDismiss = output();
245
+ this.#outputSubscriptions = [];
161
246
  }
247
+ #initialStylePosition;
162
248
  #elRef;
163
249
  #environmentInjector;
164
- #applicationRef;
165
- #overlayId;
166
- /**
167
- * The Boolean expression to evaluate as the condition for showing the busy overlay
168
- */
169
- set yuvBusyOverlay(b) {
170
- if (b === true) {
171
- this.#addBusyOverlay();
172
- }
173
- else if (this.#overlayId) {
174
- this.#removeBusyOverlay();
250
+ #vcRef;
251
+ #yuvBusyOverlayEffect;
252
+ #yuvBusyErrorEffect;
253
+ #busyOverlayComponentRef;
254
+ #outputSubscriptions;
255
+ #attachOverlay() {
256
+ if (this.#busyOverlayComponentRef) {
257
+ // Already attached; just refresh inputs/outputs
258
+ this.#applyInputs();
259
+ return;
175
260
  }
176
- }
177
- #createSpinner(mode = 'indeterminate', value = 0) {
178
- const componentRef = createComponent(MatProgressSpinner, {
261
+ // Create the component inside the directive’s host
262
+ this.#busyOverlayComponentRef = this.#vcRef.createComponent(BusyOverlayComponent, {
179
263
  environmentInjector: this.#environmentInjector
180
264
  });
181
- this.#applicationRef.attachView(componentRef.hostView);
182
- componentRef.changeDetectorRef.detectChanges();
183
- componentRef.setInput('mode', mode);
184
- componentRef.setInput('value', value);
185
- componentRef.location.nativeElement.classList.add('ymt-progress-spinner--giant');
186
- return componentRef;
265
+ const node = this.#busyOverlayComponentRef.location.nativeElement;
266
+ this.#elRef.nativeElement.appendChild(node);
267
+ this.#applyInputs();
268
+ this.#bindOutputs();
269
+ this.#busyOverlayComponentRef.changeDetectorRef?.detectChanges?.();
270
+ }
271
+ #detachOverlay() {
272
+ // Unsubscribe outputs first
273
+ this.#outputSubscriptions.forEach((sub) => sub.unsubscribe());
274
+ this.#outputSubscriptions = [];
275
+ // Destroy componentRef and clear container
276
+ if (this.#busyOverlayComponentRef) {
277
+ this.#busyOverlayComponentRef.destroy();
278
+ this.#busyOverlayComponentRef = undefined;
279
+ }
280
+ this.#vcRef.clear();
281
+ }
282
+ #applyInputs() {
283
+ if (!this.#busyOverlayComponentRef)
284
+ return;
285
+ this.#busyOverlayComponentRef.setInput('config', this.yuvBusyOverlayConfig());
286
+ this.#busyOverlayComponentRef.setInput('error', this.yuvBusyError());
287
+ }
288
+ #bindOutputs() {
289
+ if (!this.#busyOverlayComponentRef)
290
+ return;
291
+ // Clean up old subscriptions if re-binding
292
+ this.#outputSubscriptions.forEach((sub) => sub.unsubscribe());
293
+ this.#outputSubscriptions = [];
294
+ const errorDismissOutput = this.#busyOverlayComponentRef.instance.errorDismiss;
295
+ this.#outputSubscriptions.push(errorDismissOutput.subscribe(() => {
296
+ this.yuvBusyErrorDismiss.emit();
297
+ }));
187
298
  }
188
299
  #addBusyOverlay() {
189
- this.stylePosition = 'relative';
190
- const overlay = document.createElement('div');
191
- overlay.style.position = 'absolute';
192
- overlay.style.transition = 'opacity 200ms';
193
- overlay.style.opacity = '0';
194
- overlay.style.inset = '0';
195
- overlay.style.display = 'grid';
196
- overlay.style.alignItems = 'center';
197
- overlay.style.justifyContent = 'center';
198
- overlay.style.zIndex = '5';
199
- const backdropBackground = this.yuvBusyOverlayConfig()?.backdropColor || 'var(--ymt-surface-app)';
200
- overlay.style.backgroundColor = `rgb(from ${backdropBackground} r g b / .5)`;
201
- if (this.yuvBusyOverlayConfig()?.blur) {
202
- overlay.style.backdropFilter = 'blur(2px)';
203
- }
204
- this.#overlayId = `p${Utils.uuid()}`;
205
- overlay.setAttribute('id', this.#overlayId);
206
- overlay.append(this.#createSpinner('indeterminate').location.nativeElement);
207
- const el = this.#elRef.nativeElement;
208
- el.setAttribute('inert', '');
209
- el.append(overlay);
210
- setTimeout(() => {
211
- overlay.style.opacity = '1';
212
- });
300
+ this.stylePosition.set('relative');
301
+ this.#attachOverlay();
213
302
  }
214
303
  #removeBusyOverlay() {
215
- const el = this.#elRef.nativeElement.querySelector(`#${this.#overlayId}`);
304
+ if (!this.#busyOverlayComponentRef)
305
+ return;
306
+ const el = this.#busyOverlayComponentRef.location.nativeElement;
216
307
  if (el) {
217
308
  el.style.opacity = '0';
218
309
  setTimeout(() => {
219
- el.remove();
310
+ this.#detachOverlay();
311
+ this.stylePosition.set(this.#initialStylePosition());
220
312
  }, 200);
221
313
  }
222
- this.#elRef.nativeElement.removeAttribute('inert');
223
- this.#overlayId = null;
224
314
  }
225
315
  ngOnInit() {
226
- this.stylePosition = getComputedStyle(this.#elRef.nativeElement).position;
316
+ this.#initialStylePosition.set(getComputedStyle(this.#elRef.nativeElement).position);
317
+ }
318
+ ngOnDestroy() {
319
+ this.#detachOverlay();
227
320
  }
228
321
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: BusyOverlayDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
229
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.15", type: BusyOverlayDirective, isStandalone: true, selector: "[yuvBusyOverlay]", inputs: { yuvBusyOverlay: { classPropertyName: "yuvBusyOverlay", publicName: "yuvBusyOverlay", isSignal: false, isRequired: false, transformFunction: null }, yuvBusyOverlayConfig: { classPropertyName: "yuvBusyOverlayConfig", publicName: "yuvBusyOverlayConfig", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.position": "this.stylePosition" } }, ngImport: i0 }); }
322
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.15", type: BusyOverlayDirective, isStandalone: true, selector: "[yuvBusyOverlay]", inputs: { yuvBusyOverlay: { classPropertyName: "yuvBusyOverlay", publicName: "yuvBusyOverlay", isSignal: true, isRequired: false, transformFunction: null }, yuvBusyOverlayConfig: { classPropertyName: "yuvBusyOverlayConfig", publicName: "yuvBusyOverlayConfig", isSignal: true, isRequired: false, transformFunction: null }, yuvBusyError: { classPropertyName: "yuvBusyError", publicName: "yuvBusyError", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { yuvBusyErrorDismiss: "yuvBusyErrorDismiss" }, host: { properties: { "attr.aria-busy": "yuvBusyOverlay() ? \"true\" : \"false\"", "style.position": "stylePosition()" } }, ngImport: i0 }); }
230
323
  }
231
324
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: BusyOverlayDirective, decorators: [{
232
325
  type: Directive,
233
326
  args: [{
234
327
  selector: '[yuvBusyOverlay]',
235
- standalone: true
328
+ standalone: true,
329
+ host: {
330
+ '[attr.aria-busy]': 'yuvBusyOverlay() ? "true" : "false"',
331
+ '[style.position]': 'stylePosition()'
332
+ }
236
333
  }]
237
- }], propDecorators: { stylePosition: [{
238
- type: HostBinding,
239
- args: ['style.position']
240
- }], yuvBusyOverlay: [{
241
- type: Input
242
- }] } });
334
+ }] });
243
335
 
244
336
  /**
245
337
  * Fixes the issue of 'click' event beeing triggered on 'doubleclick' by defining new outputs that
@@ -1231,7 +1323,7 @@ class RetentionBadgeComponent {
1231
1323
  }
1232
1324
  #retention;
1233
1325
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: RetentionBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1234
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: RetentionBadgeComponent, isStandalone: true, selector: "yuv-retention-badge", inputs: { dmsObject: { classPropertyName: "dmsObject", publicName: "dmsObject", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@let rd = retentionData();\n@if (rd.underRetention) {\n <div class=\"badge\">\n <span class=\"badge__icon\">\n <mat-icon class=\"ymt-icon--size-s\">lock_clock</mat-icon>\n </span>\n <span class=\"badge__label\">\n <span class=\"badge__label-truncated\">\n {{\n 'yuv.retention-badge.retain'\n | translate\n : {\n from: rd.start | localeDate: 'shortDate',\n until: rd.end | localeDate: 'shortDate'\n }\n }}\n </span>\n </span>\n </div>\n}\n", styles: [":host{display:contents}:host .badge{font:var(--ymt-font-body-subtle);color:var(--badge-retention-color, var(--ymt-on-surface));display:inline-flex;overflow:hidden;padding:var(--ymt-spacing-2xs) var(--ymt-spacing-s) var(--ymt-spacing-2xs) var(--ymt-spacing-xs);background-color:var(--badge-retention-background, var(--ymt-primary-container));border-radius:var(--ymt-corner-full);gap:var(--ymt-spacing-s)}:host .badge__icon{flex-shrink:0;color:var(--badge-retention-icon-color, var(--ymt-on-primary-container));display:flex;align-items:center;justify-content:center}:host .badge__label{color:var(--badge-retention-color, var(--ymt-on-surface));align-self:stretch;display:flex;align-items:center;justify-content:center;border-top-right-radius:var(--ymt-corner-full);border-bottom-right-radius:var(--ymt-corner-full);overflow:hidden}:host .badge__label-truncated{text-overflow:ellipsis;overflow:hidden;white-space:nowrap;display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule$1 }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "pipe", type: LocaleDatePipe, name: "localeDate" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
1326
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: RetentionBadgeComponent, isStandalone: true, selector: "yuv-retention-badge", inputs: { dmsObject: { classPropertyName: "dmsObject", publicName: "dmsObject", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@let rd = retentionData();\n@if (rd.underRetention) {\n <div class=\"badge\">\n <span class=\"badge__icon\">\n <mat-icon class=\"ymt-icon--size-s\">lock_clock</mat-icon>\n </span>\n <span class=\"badge__label\">\n <span class=\"badge__label-truncated\">\n {{\n 'yuv.retention-badge.retain'\n | translate\n : {\n from: rd.start | localeDate: 'shortDate',\n until: rd.end | localeDate: 'shortDate'\n }\n }}\n </span>\n </span>\n </div>\n}\n", styles: [":host{display:contents}:host .badge{font:var(--ymt-font-body-subtle);color:var(--badge-retention-color, var(--ymt-on-surface));display:inline-flex;overflow:hidden;padding:var(--ymt-spacing-2xs) var(--ymt-spacing-s) var(--ymt-spacing-2xs) var(--ymt-spacing-xs);background-color:var(--badge-retention-background, var(--ymt-primary-container));border-radius:var(--ymt-corner-full);gap:var(--ymt-spacing-s)}:host .badge__icon{flex-shrink:0;color:var(--badge-retention-icon-color, var(--ymt-on-primary-container));display:flex;align-items:center;justify-content:center}:host .badge__label{color:var(--badge-retention-color, var(--ymt-on-surface));align-self:stretch;display:flex;align-items:center;justify-content:center;border-top-right-radius:var(--ymt-corner-full);border-bottom-right-radius:var(--ymt-corner-full);overflow:hidden}:host .badge__label-truncated{text-overflow:ellipsis;overflow:hidden;white-space:nowrap;display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule$1 }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "pipe", type: LocaleDatePipe, name: "localeDate" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
1235
1327
  }
1236
1328
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: RetentionBadgeComponent, decorators: [{
1237
1329
  type: Component,
@@ -1260,5 +1352,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
1260
1352
  * Generated bundle index. Do not edit.
1261
1353
  */
1262
1354
 
1263
- export { AbstractMatFormField, AutofocusChildDirective, AutofocusDelayedDirective, BusyOverlayDirective, ClickDoubleDirective, ConfirmComponent, ConfirmService, ContainerSizeDirective, DialogComponent, DialogSize, DragScrollDirective, DragSelectDirective, DragSelectItemDirective, FileDropZoneDirective, FocusWithinDirective, FormTranslateService, LayoutSettingsService, LightDismissDirective, LongPressDirective, NoopValueAccessorDirective, RetentionBadgeComponent, YuvCommonModule, getFirstFocusableChild, getFocusableChildren, injectNgControl };
1355
+ export { AbstractMatFormField, AutofocusChildDirective, AutofocusDelayedDirective, BusyOverlayComponent, BusyOverlayDirective, ClickDoubleDirective, ConfirmComponent, ConfirmService, ContainerSizeDirective, DialogComponent, DialogSize, DragScrollDirective, DragSelectDirective, DragSelectItemDirective, FileDropZoneDirective, FocusWithinDirective, FormTranslateService, LayoutSettingsService, LightDismissDirective, LongPressDirective, NoopValueAccessorDirective, RetentionBadgeComponent, YuvCommonModule, getFirstFocusableChild, getFocusableChildren, injectNgControl };
1264
1356
  //# sourceMappingURL=yuuvis-client-framework-common.mjs.map