@scion/workbench 21.0.0-beta.4 → 21.0.0-beta.5

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.
@@ -6395,7 +6395,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
6395
6395
  */
6396
6396
  function trackFocus(target, workbenchElement) {
6397
6397
  const focusMonitor = inject(ɵWorkbenchFocusMonitor);
6398
- const subscription = toObservable(focusMonitor.activeElement)
6398
+ toObservable(focusMonitor.activeElement)
6399
6399
  .pipe(startWith(focusMonitor.activeElement()), // Immediately subscribe to `focusin` events, required when the DOM element is focused right after invocation.
6400
6400
  switchMap(activeWorkbenchElement => activeWorkbenchElement === workbenchElement ? EMPTY : merge(fromEvent(target, 'focusin', { once: true }), fromEvent(target, 'sci-microfrontend-focusin', { once: true }))), finalize(() => requestAnimationFrame(() => focusMonitor.unsetActiveElement(workbenchElement))), // Asynchronously unset the active workbench element to prevent a `null` focus during destruction until the next element gains focus.
6401
6401
  takeUntilDestroyed())
@@ -6404,7 +6404,6 @@ function trackFocus(target, workbenchElement) {
6404
6404
  });
6405
6405
  return {
6406
6406
  unsetActiveElement: () => focusMonitor.unsetActiveElement(workbenchElement),
6407
- destroy: () => subscription.unsubscribe(),
6408
6407
  };
6409
6408
  }
6410
6409
  class ɵWorkbenchFocusMonitor {
@@ -6426,7 +6425,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
6426
6425
  }] });
6427
6426
 
6428
6427
  /*
6429
- * Copyright (c) 2018-2023 Swiss Federal Railways
6428
+ * Copyright (c) 2018-2026 Swiss Federal Railways
6430
6429
  *
6431
6430
  * This program and the accompanying materials are made
6432
6431
  * available under the terms of the Eclipse Public License 2.0
@@ -6854,7 +6853,7 @@ class WbComponentPortal {
6854
6853
  this.detach();
6855
6854
  }
6856
6855
  this._viewContainerRef.set(viewContainerRef);
6857
- this._componentRef.update(componentRef => componentRef ?? createPortalComponent(this._componentType, { providers: this._options?.providers, injector: viewContainerRef.injector }));
6856
+ this._componentRef.update(componentRef => componentRef ?? createPortalComponent(this._componentType, { providers: this._options?.providers, injector: this._options?.injector ?? viewContainerRef.injector }));
6858
6857
  this._logger.debug(() => 'Attaching portal', LoggerNames.LIFECYCLE, this._options?.debugName ?? this._componentType.name);
6859
6858
  this._componentRef().changeDetectorRef.reattach();
6860
6859
  this._viewContainerRef().insert(this._componentRef().hostView);
@@ -8330,7 +8329,7 @@ class MainAreaPartComponent {
8330
8329
  });
8331
8330
  }
8332
8331
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: MainAreaPartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8333
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: MainAreaPartComponent, isStandalone: true, selector: "wb-part[data-partid=\"part.main-area\"]", host: { properties: { "attr.data-grid": "dasherize(part.gridName())", "attr.data-active": "part.active() ? '' : null" } }, ngImport: i0, template: "@if (mainAreaGrid().root.visible) {\n <wb-grid [grid]=\"mainAreaGrid()\"\n [gridDropZone]=\"{\n dropRegionSize: 100,\n dropPlaceholderSize: 100,\n dropZoneAttributes: {\n 'data-grid': 'main-area',\n 'data-partid': part.id,\n }\n }\"\n [attr.data-grid]=\"'main-area'\"\n class=\"e2e-content\"/>\n} @else {\n <div wbViewDropZone\n [wbViewDropZoneRegions]=\"canDrop() && {center: true, north: false, south: false, west: false, east: false}\"\n [wbViewDropZoneAttributes]=\"{\n 'data-desktop': '',\n 'data-partid': part.id,\n }\"\n (wbViewDropZoneDrop)=\"onDesktopViewDrop($event)\"\n class=\"desktop e2e-part-content e2e-content\">\n @if (part.navigation()) {\n <ng-container *wbPortalOutlet=\"part.slot.portal; destroyOnDetach: false\"/>\n } @else {\n <ng-container *wbPortalOutlet=\"desktop.slot.portal; destroyOnDetach: false\"/>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-direction:column}:host>wb-grid{flex:auto}:host>div.desktop{flex:auto;display:grid;position:relative}\n"], dependencies: [{ kind: "component", type: GridComponent, selector: "wb-grid", inputs: ["grid", "gridDropZone"] }, { kind: "directive", type: ViewDropZoneDirective, selector: "[wbViewDropZone]", inputs: ["wbViewDropZoneRegions", "wbViewDropZoneAttributes", "wbViewDropZoneRegionSize", "wbViewDropZonePlaceholderSize"], outputs: ["wbViewDropZoneDrop"] }, { kind: "directive", type: WorkbenchPortalOutletDirective, selector: "ng-template[wbPortalOutlet]", inputs: ["wbPortalOutlet", "wbPortalOutletDestroyOnDetach"] }] });
8332
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: MainAreaPartComponent, isStandalone: true, selector: "wb-part[data-partid=\"part.main-area\"]", host: { properties: { "attr.data-grid": "dasherize(part.gridName())", "attr.data-active": "part.active() ? '' : null" } }, ngImport: i0, template: "@if (mainAreaGrid().root.visible) {\n <wb-grid [grid]=\"mainAreaGrid()\"\n [gridDropZone]=\"{\n dropRegionSize: 100,\n dropPlaceholderSize: 100,\n dropZoneAttributes: {\n 'data-grid': 'main-area',\n 'data-partid': part.id,\n }\n }\"\n [attr.data-grid]=\"'main-area'\"\n class=\"e2e-slot\"/>\n} @else {\n <div wbViewDropZone\n [wbViewDropZoneRegions]=\"canDrop() && {center: true, north: false, south: false, west: false, east: false}\"\n [wbViewDropZoneAttributes]=\"{\n 'data-desktop': '',\n 'data-partid': part.id,\n }\"\n (wbViewDropZoneDrop)=\"onDesktopViewDrop($event)\"\n class=\"desktop e2e-part-slot e2e-slot\">\n @if (part.navigation()) {\n <ng-container *wbPortalOutlet=\"part.slot.portal; destroyOnDetach: false\"/>\n } @else {\n <ng-container *wbPortalOutlet=\"desktop.slot.portal; destroyOnDetach: false\"/>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-direction:column}:host>wb-grid{flex:auto}:host>div.desktop{flex:auto;display:grid;position:relative}\n"], dependencies: [{ kind: "component", type: GridComponent, selector: "wb-grid", inputs: ["grid", "gridDropZone"] }, { kind: "directive", type: ViewDropZoneDirective, selector: "[wbViewDropZone]", inputs: ["wbViewDropZoneRegions", "wbViewDropZoneAttributes", "wbViewDropZoneRegionSize", "wbViewDropZonePlaceholderSize"], outputs: ["wbViewDropZoneDrop"] }, { kind: "directive", type: WorkbenchPortalOutletDirective, selector: "ng-template[wbPortalOutlet]", inputs: ["wbPortalOutlet", "wbPortalOutletDestroyOnDetach"] }] });
8334
8333
  }
8335
8334
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: MainAreaPartComponent, decorators: [{
8336
8335
  type: Component,
@@ -8341,7 +8340,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
8341
8340
  ], host: {
8342
8341
  '[attr.data-grid]': 'dasherize(part.gridName())',
8343
8342
  '[attr.data-active]': `part.active() ? '' : null`,
8344
- }, template: "@if (mainAreaGrid().root.visible) {\n <wb-grid [grid]=\"mainAreaGrid()\"\n [gridDropZone]=\"{\n dropRegionSize: 100,\n dropPlaceholderSize: 100,\n dropZoneAttributes: {\n 'data-grid': 'main-area',\n 'data-partid': part.id,\n }\n }\"\n [attr.data-grid]=\"'main-area'\"\n class=\"e2e-content\"/>\n} @else {\n <div wbViewDropZone\n [wbViewDropZoneRegions]=\"canDrop() && {center: true, north: false, south: false, west: false, east: false}\"\n [wbViewDropZoneAttributes]=\"{\n 'data-desktop': '',\n 'data-partid': part.id,\n }\"\n (wbViewDropZoneDrop)=\"onDesktopViewDrop($event)\"\n class=\"desktop e2e-part-content e2e-content\">\n @if (part.navigation()) {\n <ng-container *wbPortalOutlet=\"part.slot.portal; destroyOnDetach: false\"/>\n } @else {\n <ng-container *wbPortalOutlet=\"desktop.slot.portal; destroyOnDetach: false\"/>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-direction:column}:host>wb-grid{flex:auto}:host>div.desktop{flex:auto;display:grid;position:relative}\n"] }]
8343
+ }, template: "@if (mainAreaGrid().root.visible) {\n <wb-grid [grid]=\"mainAreaGrid()\"\n [gridDropZone]=\"{\n dropRegionSize: 100,\n dropPlaceholderSize: 100,\n dropZoneAttributes: {\n 'data-grid': 'main-area',\n 'data-partid': part.id,\n }\n }\"\n [attr.data-grid]=\"'main-area'\"\n class=\"e2e-slot\"/>\n} @else {\n <div wbViewDropZone\n [wbViewDropZoneRegions]=\"canDrop() && {center: true, north: false, south: false, west: false, east: false}\"\n [wbViewDropZoneAttributes]=\"{\n 'data-desktop': '',\n 'data-partid': part.id,\n }\"\n (wbViewDropZoneDrop)=\"onDesktopViewDrop($event)\"\n class=\"desktop e2e-part-slot e2e-slot\">\n @if (part.navigation()) {\n <ng-container *wbPortalOutlet=\"part.slot.portal; destroyOnDetach: false\"/>\n } @else {\n <ng-container *wbPortalOutlet=\"desktop.slot.portal; destroyOnDetach: false\"/>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-direction:column}:host>wb-grid{flex:auto}:host>div.desktop{flex:auto;display:grid;position:relative}\n"] }]
8345
8344
  }] });
8346
8345
 
8347
8346
  /*
@@ -9723,7 +9722,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
9723
9722
  }] });
9724
9723
 
9725
9724
  /*
9726
- * Copyright (c) 2018-2023 Swiss Federal Railways
9725
+ * Copyright (c) 2018-2026 Swiss Federal Railways
9727
9726
  *
9728
9727
  * This program and the accompanying materials are made
9729
9728
  * available under the terms of the Eclipse Public License 2.0
@@ -9745,7 +9744,8 @@ class WorkbenchDialogComponent {
9745
9744
  headerHeight = signal(undefined, { ...(ngDevMode ? { debugName: "headerHeight" } : {}) });
9746
9745
  transformTranslateX = signal(0, { ...(ngDevMode ? { debugName: "transformTranslateX" } : {}) });
9747
9746
  transformTranslateY = signal(0, { ...(ngDevMode ? { debugName: "transformTranslateY" } : {}) });
9748
- dialogContent = viewChild.required(SciViewportComponent, { read: (ElementRef) });
9747
+ slotAnchorName = this.dialog.id.replace('.', '_'); // Anchor must not contain a dot.
9748
+ dialogSlotBounds = viewChild.required('slot_bounds', { read: (ElementRef) });
9749
9749
  constructor() {
9750
9750
  this.setDialogOffset();
9751
9751
  this.trackFocus();
@@ -9847,7 +9847,7 @@ class WorkbenchDialogComponent {
9847
9847
  this.focus();
9848
9848
  }
9849
9849
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9850
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: WorkbenchDialogComponent, isStandalone: true, selector: "wb-dialog", host: { listeners: { "keydown.escape": "onEscape($event)" }, properties: { "attr.data-dialogid": "dialog.id", "class.justified": "!dialog.padding()", "style.--\u0275dialog-transform-translate-x": "transformTranslateX()", "style.--\u0275dialog-transform-translate-y": "transformTranslateY()", "style.--\u0275dialog-min-height": "dialog.size.minHeight() ?? headerHeight()", "style.--\u0275dialog-height": "dialog.size.height()", "style.--\u0275dialog-max-height": "dialog.size.maxHeight()", "style.--\u0275dialog-min-width": "dialog.size.minWidth() ?? '100px'", "style.--\u0275dialog-width": "dialog.size.width()", "style.--\u0275dialog-max-width": "dialog.size.maxWidth()", "class": "dialog.cssClass()" } }, viewQueries: [{ propertyName: "_cdkTrapFocus", first: true, predicate: CdkTrapFocus, descendants: true, isSignal: true }, { propertyName: "_dialogElement", first: true, predicate: ["dialog_element"], descendants: true, isSignal: true }, { propertyName: "dialogContent", first: true, predicate: SciViewportComponent, descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: "<div class=\"dialog e2e-dialog\"\n [class.blinking]=\"dialog.blinking$ | async\"\n [tabindex]=\"-1\"\n wbMovable [wbHandle]=\"header\" (wbMovableMove)=\"onMove($event)\"\n (mousedown)=\"onDialogMouseDown()\"\n wbResizable [wbResizableEnabled]=\"dialog.resizable()\" (wbResizableResize)=\"onResize($event)\"\n @enter\n [@.disabled]=\"!dialog.animate\"\n wbGlassPane\n #dialog_element>\n <div class=\"dialog-box e2e-dialog-box\" cdkTrapFocus>\n <header #header\n class=\"e2e-dialog-header\"\n [class.divider]=\"dialog.header?.divider() ?? true\"\n sciDimension (sciDimensionChange)=\"onHeaderDimensionChange($event)\">\n <ng-container *ngTemplateOutlet=\"dialog.header?.template ?? default_dialog_header\"/>\n </header>\n\n <sci-viewport class=\"content e2e-dialog-content\">\n <ng-container *ngComponentOutlet=\"dialog.component; inputs: dialog.inputs\"/>\n </sci-viewport>\n\n @if (dialog.footer || dialog.actions.length) {\n <footer class=\"e2e-dialog-footer\" [class.divider]=\"dialog.footer?.divider() ?? true\">\n <ng-container *ngTemplateOutlet=\"dialog.footer?.template ?? default_dialog_footer\"/>\n </footer>\n }\n </div>\n</div>\n\n<ng-template #default_dialog_header>\n <wb-dialog-header/>\n</ng-template>\n\n<ng-template #default_dialog_footer>\n <wb-dialog-footer/>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{--\\275 dialog-transform-translate-x: 0;--\\275 dialog-transform-translate-y: 0;--\\275 dialog-min-height: initial;--\\275 dialog-height: initial;--\\275 dialog-max-height: initial;--\\275 dialog-min-width: initial;--\\275 dialog-width: initial;--\\275 dialog-max-width: initial;--\\275 dialog-padding: var(--sci-workbench-dialog-padding)}:host.justified{--\\275 dialog-padding: 0}:host{display:flex;flex-direction:column;align-items:center;position:relative}:host>div.dialog{display:flex;flex-direction:column;position:absolute;top:3%;color:var(--sci-color-text);transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x))) translateY(calc(1px * var(--\\275 dialog-transform-translate-y)));min-height:var(--\\275 dialog-min-height);height:var(--\\275 dialog-height);max-height:var(--\\275 dialog-max-height);min-width:var(--\\275 dialog-min-width);width:var(--\\275 dialog-width);max-width:var(--\\275 dialog-max-width);outline:none;pointer-events:auto}:host>div.dialog>div.dialog-box{flex:auto;display:flex;flex-direction:column;gap:calc(1.25 * var(--\\275 dialog-padding));border:1px solid var(--sci-color-border);border-radius:var(--sci-corner);background-color:var(--sci-color-background-elevation);box-shadow:var(--sci-elevation) var(--sci-static-color-black);overflow:hidden}:host>div.dialog>div.dialog-box>header{flex:none}:host>div.dialog>div.dialog-box>header.divider{border-bottom:1px solid var(--sci-color-border)}:host>div.dialog>div.dialog-box>sci-viewport{flex:auto}:host>div.dialog>div.dialog-box>sci-viewport::part(content){padding-inline:var(--\\275 dialog-padding)}:host>div.dialog>div.dialog-box>footer{flex:none}:host>div.dialog>div.dialog-box>footer.divider{border-top:1px solid var(--sci-color-border)}:host>div.dialog.blinking{animation-duration:50ms;animation-iteration-count:infinite;animation-name:blink-animation}@keyframes blink-animation{0%{transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x) - 2px)) translateY(calc(1px * var(--\\275 dialog-transform-translate-y) - 1px))}to{transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x) + 2px)) translateY(calc(1px * var(--\\275 dialog-transform-translate-y) + 1px))}}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: MovableDirective, selector: "[wbMovable]", inputs: ["wbHandle"], outputs: ["wbMovableMove"] }, { kind: "directive", type: ResizableDirective, selector: "[wbResizable]", inputs: ["wbResizableEnabled"], outputs: ["wbResizableResize"] }, { kind: "component", type: SciViewportComponent, selector: "sci-viewport", inputs: ["scrollbarStyle"], outputs: ["scroll"] }, { kind: "directive", type: SciDimensionDirective, selector: "[sciDimension]", inputs: ["emitOutsideAngular"], outputs: ["sciDimensionChange"] }, { kind: "component", type: DialogHeaderComponent, selector: "wb-dialog-header" }, { kind: "component", type: DialogFooterComponent, selector: "wb-dialog-footer" }, { kind: "directive", type: GlassPaneDirective, selector: "[wbGlassPane]" }, { kind: "pipe", type: AsyncPipe, name: "async" }], viewProviders: [
9850
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: WorkbenchDialogComponent, isStandalone: true, selector: "wb-dialog", host: { listeners: { "keydown.escape": "onEscape($event)" }, properties: { "attr.data-dialogid": "dialog.id", "class.justified": "!dialog.padding()", "style.--\u0275dialog-transform-translate-x": "transformTranslateX()", "style.--\u0275dialog-transform-translate-y": "transformTranslateY()", "style.--\u0275dialog-min-height": "dialog.size.minHeight() ?? headerHeight()", "style.--\u0275dialog-height": "dialog.size.height()", "style.--\u0275dialog-max-height": "dialog.size.maxHeight()", "style.--\u0275dialog-min-width": "dialog.size.minWidth() ?? '100px'", "style.--\u0275dialog-width": "dialog.size.width()", "style.--\u0275dialog-max-width": "dialog.size.maxWidth()", "style.--\u0275slot-anchor": "`--${slotAnchorName}`", "class": "dialog.cssClass()" } }, viewQueries: [{ propertyName: "_cdkTrapFocus", first: true, predicate: CdkTrapFocus, descendants: true, isSignal: true }, { propertyName: "_dialogElement", first: true, predicate: ["dialog_element"], descendants: true, isSignal: true }, { propertyName: "dialogSlotBounds", first: true, predicate: ["slot_bounds"], descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: "<div class=\"dialog e2e-dialog\"\n [class.blinking]=\"dialog.blinking$ | async\"\n [tabindex]=\"-1\"\n wbMovable [wbHandle]=\"header\" (wbMovableMove)=\"onMove($event)\"\n (mousedown)=\"onDialogMouseDown()\"\n wbResizable [wbResizableEnabled]=\"dialog.resizable()\" (wbResizableResize)=\"onResize($event)\"\n @enter\n [@.disabled]=\"!dialog.animate\"\n wbGlassPane\n #dialog_element>\n <div class=\"dialog-box e2e-dialog-box\" cdkTrapFocus>\n <header #header\n class=\"e2e-dialog-header\"\n [class.divider]=\"dialog.header?.divider() ?? true\"\n sciDimension (sciDimensionChange)=\"onHeaderDimensionChange($event)\">\n <ng-container *ngTemplateOutlet=\"dialog.header?.template ?? default_dialog_header\"/>\n </header>\n\n <sci-viewport class=\"e2e-dialog-slot\">\n <ng-container *ngComponentOutlet=\"dialog.component; inputs: dialog.inputs\"/>\n </sci-viewport>\n\n <!-- Extra DIV to capture bounds available to slotted content, excluding viewport content padding. May differ from the actual content size if content overflows or does not fill the slot. -->\n <div class=\"slot-bounds e2e-dialog-slot-bounds\" #slot_bounds></div>\n\n @if (dialog.footer || dialog.actions.length) {\n <footer class=\"e2e-dialog-footer\" [class.divider]=\"dialog.footer?.divider() ?? true\">\n <ng-container *ngTemplateOutlet=\"dialog.footer?.template ?? default_dialog_footer\"/>\n </footer>\n }\n </div>\n</div>\n\n<ng-template #default_dialog_header>\n <wb-dialog-header/>\n</ng-template>\n\n<ng-template #default_dialog_footer>\n <wb-dialog-footer/>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{--\\275 dialog-transform-translate-x: 0;--\\275 dialog-transform-translate-y: 0;--\\275 dialog-min-height: initial;--\\275 dialog-height: initial;--\\275 dialog-max-height: initial;--\\275 dialog-min-width: initial;--\\275 dialog-width: initial;--\\275 dialog-max-width: initial;--\\275 dialog-padding: var(--sci-workbench-dialog-padding)}:host.justified{--\\275 dialog-padding: 0}:host{display:flex;flex-direction:column;align-items:center;position:relative}:host>div.dialog{display:flex;flex-direction:column;position:absolute;top:3%;color:var(--sci-color-text);transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x))) translateY(calc(1px * var(--\\275 dialog-transform-translate-y)));min-height:var(--\\275 dialog-min-height);height:var(--\\275 dialog-height);max-height:var(--\\275 dialog-max-height);min-width:var(--\\275 dialog-min-width);width:var(--\\275 dialog-width);max-width:var(--\\275 dialog-max-width);outline:none;pointer-events:auto}:host>div.dialog>div.dialog-box{flex:auto;display:flex;flex-direction:column;gap:calc(1.25 * var(--\\275 dialog-padding));border:1px solid var(--sci-color-border);border-radius:var(--sci-corner);background-color:var(--sci-color-background-elevation);box-shadow:var(--sci-elevation) var(--sci-static-color-black);overflow:hidden}:host>div.dialog>div.dialog-box>header{flex:none}:host>div.dialog>div.dialog-box>header.divider{border-bottom:1px solid var(--sci-color-border)}:host>div.dialog>div.dialog-box>sci-viewport{flex:auto;anchor-name:var(--\\275slot-anchor)}:host>div.dialog>div.dialog-box>sci-viewport::part(content){padding-inline:var(--\\275 dialog-padding)}:host>div.dialog>div.dialog-box>div.slot-bounds{position:absolute;position-anchor:var(--\\275slot-anchor);inset:anchor(top) anchor(right) anchor(bottom) anchor(left);margin-inline:var(--\\275 dialog-padding);visibility:hidden}:host>div.dialog>div.dialog-box>footer{flex:none}:host>div.dialog>div.dialog-box>footer.divider{border-top:1px solid var(--sci-color-border)}:host>div.dialog.blinking{animation-duration:50ms;animation-iteration-count:infinite;animation-name:blink-animation}@keyframes blink-animation{0%{transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x) - 2px)) translateY(calc(1px * var(--\\275 dialog-transform-translate-y) - 1px))}to{transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x) + 2px)) translateY(calc(1px * var(--\\275 dialog-transform-translate-y) + 1px))}}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: MovableDirective, selector: "[wbMovable]", inputs: ["wbHandle"], outputs: ["wbMovableMove"] }, { kind: "directive", type: ResizableDirective, selector: "[wbResizable]", inputs: ["wbResizableEnabled"], outputs: ["wbResizableResize"] }, { kind: "component", type: SciViewportComponent, selector: "sci-viewport", inputs: ["scrollbarStyle"], outputs: ["scroll"] }, { kind: "directive", type: SciDimensionDirective, selector: "[sciDimension]", inputs: ["emitOutsideAngular"], outputs: ["sciDimensionChange"] }, { kind: "component", type: DialogHeaderComponent, selector: "wb-dialog-header" }, { kind: "component", type: DialogFooterComponent, selector: "wb-dialog-footer" }, { kind: "directive", type: GlassPaneDirective, selector: "[wbGlassPane]" }, { kind: "pipe", type: AsyncPipe, name: "async" }], viewProviders: [
9851
9851
  configureDialogGlassPane(),
9852
9852
  ], animations: [
9853
9853
  trigger('enter', provideEnterAnimation()),
@@ -9882,9 +9882,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
9882
9882
  '[style.--ɵdialog-min-width]': 'dialog.size.minWidth() ?? \'100px\'',
9883
9883
  '[style.--ɵdialog-width]': 'dialog.size.width()',
9884
9884
  '[style.--ɵdialog-max-width]': 'dialog.size.maxWidth()',
9885
+ '[style.--ɵslot-anchor]': '`--${slotAnchorName}`',
9885
9886
  '[class]': 'dialog.cssClass()',
9886
- }, template: "<div class=\"dialog e2e-dialog\"\n [class.blinking]=\"dialog.blinking$ | async\"\n [tabindex]=\"-1\"\n wbMovable [wbHandle]=\"header\" (wbMovableMove)=\"onMove($event)\"\n (mousedown)=\"onDialogMouseDown()\"\n wbResizable [wbResizableEnabled]=\"dialog.resizable()\" (wbResizableResize)=\"onResize($event)\"\n @enter\n [@.disabled]=\"!dialog.animate\"\n wbGlassPane\n #dialog_element>\n <div class=\"dialog-box e2e-dialog-box\" cdkTrapFocus>\n <header #header\n class=\"e2e-dialog-header\"\n [class.divider]=\"dialog.header?.divider() ?? true\"\n sciDimension (sciDimensionChange)=\"onHeaderDimensionChange($event)\">\n <ng-container *ngTemplateOutlet=\"dialog.header?.template ?? default_dialog_header\"/>\n </header>\n\n <sci-viewport class=\"content e2e-dialog-content\">\n <ng-container *ngComponentOutlet=\"dialog.component; inputs: dialog.inputs\"/>\n </sci-viewport>\n\n @if (dialog.footer || dialog.actions.length) {\n <footer class=\"e2e-dialog-footer\" [class.divider]=\"dialog.footer?.divider() ?? true\">\n <ng-container *ngTemplateOutlet=\"dialog.footer?.template ?? default_dialog_footer\"/>\n </footer>\n }\n </div>\n</div>\n\n<ng-template #default_dialog_header>\n <wb-dialog-header/>\n</ng-template>\n\n<ng-template #default_dialog_footer>\n <wb-dialog-footer/>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{--\\275 dialog-transform-translate-x: 0;--\\275 dialog-transform-translate-y: 0;--\\275 dialog-min-height: initial;--\\275 dialog-height: initial;--\\275 dialog-max-height: initial;--\\275 dialog-min-width: initial;--\\275 dialog-width: initial;--\\275 dialog-max-width: initial;--\\275 dialog-padding: var(--sci-workbench-dialog-padding)}:host.justified{--\\275 dialog-padding: 0}:host{display:flex;flex-direction:column;align-items:center;position:relative}:host>div.dialog{display:flex;flex-direction:column;position:absolute;top:3%;color:var(--sci-color-text);transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x))) translateY(calc(1px * var(--\\275 dialog-transform-translate-y)));min-height:var(--\\275 dialog-min-height);height:var(--\\275 dialog-height);max-height:var(--\\275 dialog-max-height);min-width:var(--\\275 dialog-min-width);width:var(--\\275 dialog-width);max-width:var(--\\275 dialog-max-width);outline:none;pointer-events:auto}:host>div.dialog>div.dialog-box{flex:auto;display:flex;flex-direction:column;gap:calc(1.25 * var(--\\275 dialog-padding));border:1px solid var(--sci-color-border);border-radius:var(--sci-corner);background-color:var(--sci-color-background-elevation);box-shadow:var(--sci-elevation) var(--sci-static-color-black);overflow:hidden}:host>div.dialog>div.dialog-box>header{flex:none}:host>div.dialog>div.dialog-box>header.divider{border-bottom:1px solid var(--sci-color-border)}:host>div.dialog>div.dialog-box>sci-viewport{flex:auto}:host>div.dialog>div.dialog-box>sci-viewport::part(content){padding-inline:var(--\\275 dialog-padding)}:host>div.dialog>div.dialog-box>footer{flex:none}:host>div.dialog>div.dialog-box>footer.divider{border-top:1px solid var(--sci-color-border)}:host>div.dialog.blinking{animation-duration:50ms;animation-iteration-count:infinite;animation-name:blink-animation}@keyframes blink-animation{0%{transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x) - 2px)) translateY(calc(1px * var(--\\275 dialog-transform-translate-y) - 1px))}to{transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x) + 2px)) translateY(calc(1px * var(--\\275 dialog-transform-translate-y) + 1px))}}\n"] }]
9887
- }], ctorParameters: () => [], propDecorators: { _cdkTrapFocus: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkTrapFocus), { isSignal: true }] }], _dialogElement: [{ type: i0.ViewChild, args: ['dialog_element', { isSignal: true }] }], dialogContent: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SciViewportComponent), { ...{ read: (ElementRef) }, isSignal: true }] }], onEscape: [{
9887
+ }, template: "<div class=\"dialog e2e-dialog\"\n [class.blinking]=\"dialog.blinking$ | async\"\n [tabindex]=\"-1\"\n wbMovable [wbHandle]=\"header\" (wbMovableMove)=\"onMove($event)\"\n (mousedown)=\"onDialogMouseDown()\"\n wbResizable [wbResizableEnabled]=\"dialog.resizable()\" (wbResizableResize)=\"onResize($event)\"\n @enter\n [@.disabled]=\"!dialog.animate\"\n wbGlassPane\n #dialog_element>\n <div class=\"dialog-box e2e-dialog-box\" cdkTrapFocus>\n <header #header\n class=\"e2e-dialog-header\"\n [class.divider]=\"dialog.header?.divider() ?? true\"\n sciDimension (sciDimensionChange)=\"onHeaderDimensionChange($event)\">\n <ng-container *ngTemplateOutlet=\"dialog.header?.template ?? default_dialog_header\"/>\n </header>\n\n <sci-viewport class=\"e2e-dialog-slot\">\n <ng-container *ngComponentOutlet=\"dialog.component; inputs: dialog.inputs\"/>\n </sci-viewport>\n\n <!-- Extra DIV to capture bounds available to slotted content, excluding viewport content padding. May differ from the actual content size if content overflows or does not fill the slot. -->\n <div class=\"slot-bounds e2e-dialog-slot-bounds\" #slot_bounds></div>\n\n @if (dialog.footer || dialog.actions.length) {\n <footer class=\"e2e-dialog-footer\" [class.divider]=\"dialog.footer?.divider() ?? true\">\n <ng-container *ngTemplateOutlet=\"dialog.footer?.template ?? default_dialog_footer\"/>\n </footer>\n }\n </div>\n</div>\n\n<ng-template #default_dialog_header>\n <wb-dialog-header/>\n</ng-template>\n\n<ng-template #default_dialog_footer>\n <wb-dialog-footer/>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{--\\275 dialog-transform-translate-x: 0;--\\275 dialog-transform-translate-y: 0;--\\275 dialog-min-height: initial;--\\275 dialog-height: initial;--\\275 dialog-max-height: initial;--\\275 dialog-min-width: initial;--\\275 dialog-width: initial;--\\275 dialog-max-width: initial;--\\275 dialog-padding: var(--sci-workbench-dialog-padding)}:host.justified{--\\275 dialog-padding: 0}:host{display:flex;flex-direction:column;align-items:center;position:relative}:host>div.dialog{display:flex;flex-direction:column;position:absolute;top:3%;color:var(--sci-color-text);transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x))) translateY(calc(1px * var(--\\275 dialog-transform-translate-y)));min-height:var(--\\275 dialog-min-height);height:var(--\\275 dialog-height);max-height:var(--\\275 dialog-max-height);min-width:var(--\\275 dialog-min-width);width:var(--\\275 dialog-width);max-width:var(--\\275 dialog-max-width);outline:none;pointer-events:auto}:host>div.dialog>div.dialog-box{flex:auto;display:flex;flex-direction:column;gap:calc(1.25 * var(--\\275 dialog-padding));border:1px solid var(--sci-color-border);border-radius:var(--sci-corner);background-color:var(--sci-color-background-elevation);box-shadow:var(--sci-elevation) var(--sci-static-color-black);overflow:hidden}:host>div.dialog>div.dialog-box>header{flex:none}:host>div.dialog>div.dialog-box>header.divider{border-bottom:1px solid var(--sci-color-border)}:host>div.dialog>div.dialog-box>sci-viewport{flex:auto;anchor-name:var(--\\275slot-anchor)}:host>div.dialog>div.dialog-box>sci-viewport::part(content){padding-inline:var(--\\275 dialog-padding)}:host>div.dialog>div.dialog-box>div.slot-bounds{position:absolute;position-anchor:var(--\\275slot-anchor);inset:anchor(top) anchor(right) anchor(bottom) anchor(left);margin-inline:var(--\\275 dialog-padding);visibility:hidden}:host>div.dialog>div.dialog-box>footer{flex:none}:host>div.dialog>div.dialog-box>footer.divider{border-top:1px solid var(--sci-color-border)}:host>div.dialog.blinking{animation-duration:50ms;animation-iteration-count:infinite;animation-name:blink-animation}@keyframes blink-animation{0%{transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x) - 2px)) translateY(calc(1px * var(--\\275 dialog-transform-translate-y) - 1px))}to{transform:translate(calc(1px * var(--\\275 dialog-transform-translate-x) + 2px)) translateY(calc(1px * var(--\\275 dialog-transform-translate-y) + 1px))}}\n"] }]
9888
+ }], ctorParameters: () => [], propDecorators: { _cdkTrapFocus: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkTrapFocus), { isSignal: true }] }], _dialogElement: [{ type: i0.ViewChild, args: ['dialog_element', { isSignal: true }] }], dialogSlotBounds: [{ type: i0.ViewChild, args: ['slot_bounds', { ...{ read: (ElementRef) }, isSignal: true }] }], onEscape: [{
9888
9889
  type: HostListener,
9889
9890
  args: ['keydown.escape', ['$event']]
9890
9891
  }] } });
@@ -10246,7 +10247,7 @@ class WorkbenchMessageBoxComponent {
10246
10247
  this.empty.set(!dimension.offsetHeight);
10247
10248
  }
10248
10249
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchMessageBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10249
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: WorkbenchMessageBoxComponent, isStandalone: true, selector: "wb-message-box", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "keydown.escape": "onEscape()" }, properties: { "attr.tabindex": "-1", "class.empty": "empty()", "class.content-selectable": "options()?.contentSelectable", "class.has-title": "!!this.options()?.title" } }, ngImport: i0, template: "@let options = this.options() ?? {};\n<ng-template wbDialogHeader [divider]=\"false\">\n <wb-message-box-header [title]=\"options.title\" [severity]=\"options.severity ?? 'info'\"/>\n</ng-template>\n\n@let message = this.message();\n<div class=\"message e2e-message\" [class.text]=\"message | wbTypeof:'string'\" sciDimension (sciDimensionChange)=\"onContentDimensionChange($event)\">\n @if (message | wbTypeof:'string') {\n {{($any(message) | wbText)()}}\n } @else {\n <ng-container *ngComponentOutlet=\"message; inputs: options.inputs\"/>\n }\n</div>\n\n<ng-template wbDialogFooter>\n <wb-message-box-footer [actions]=\"options.actions ?? {ok: '%workbench.ok.action'}\"\n [severity]=\"options.severity ?? 'info'\"\n (action)=\"onAction($event)\"\n (keydown.escape)=\"onEscape()\"\n (preferredSizeChange)=\"onFooterPreferredSizeChange($event)\"/>\n</ng-template>\n", styles: [":host{display:grid;outline:none;padding-inline:var(--sci-workbench-messagebox-padding);padding-bottom:var(--sci-workbench-messagebox-padding)}:host.has-title:not(.empty){padding-top:var(--sci-workbench-messagebox-padding)}:host:not(.content-selectable){-webkit-user-select:none;user-select:none}:host>div.message.text{word-break:break-word;white-space:pre-line;text-align:var(--sci-workbench-messagebox-text-align)}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: SciDimensionDirective, selector: "[sciDimension]", inputs: ["emitOutsideAngular"], outputs: ["sciDimensionChange"] }, { kind: "directive", type: WorkbenchDialogHeaderDirective, selector: "ng-template[wbDialogHeader]", inputs: ["divider"] }, { kind: "directive", type: WorkbenchDialogFooterDirective, selector: "ng-template[wbDialogFooter]", inputs: ["divider"] }, { kind: "component", type: MessageBoxHeaderComponent, selector: "wb-message-box-header", inputs: ["title", "severity"] }, { kind: "component", type: MessageBoxFooterComponent, selector: "wb-message-box-footer", inputs: ["actions", "severity"], outputs: ["action", "preferredSizeChange"] }, { kind: "pipe", type: TypeofPipe, name: "wbTypeof" }, { kind: "pipe", type: TextPipe, name: "wbText" }] });
10250
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: WorkbenchMessageBoxComponent, isStandalone: true, selector: "wb-message-box", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "keydown.escape": "onEscape()" }, properties: { "attr.tabindex": "-1", "class.empty": "empty()", "class.content-selectable": "options()?.contentSelectable", "class.has-title": "!!this.options()?.title" } }, ngImport: i0, template: "@let options = this.options() ?? {};\n<ng-template wbDialogHeader [divider]=\"false\">\n <wb-message-box-header [title]=\"options.title\" [severity]=\"options.severity ?? 'info'\"/>\n</ng-template>\n\n@let message = this.message();\n<div class=\"slot e2e-slot\" [class.text]=\"message | wbTypeof:'string'\" sciDimension (sciDimensionChange)=\"onContentDimensionChange($event)\">\n @if (message | wbTypeof:'string') {\n {{($any(message) | wbText)()}}\n } @else {\n <ng-container *ngComponentOutlet=\"message; inputs: options.inputs\"/>\n }\n</div>\n\n<ng-template wbDialogFooter>\n <wb-message-box-footer [actions]=\"options.actions ?? {ok: '%workbench.ok.action'}\"\n [severity]=\"options.severity ?? 'info'\"\n (action)=\"onAction($event)\"\n (keydown.escape)=\"onEscape()\"\n (preferredSizeChange)=\"onFooterPreferredSizeChange($event)\"/>\n</ng-template>\n", styles: [":host{display:grid;outline:none;padding-inline:var(--sci-workbench-messagebox-padding);padding-bottom:var(--sci-workbench-messagebox-padding)}:host.has-title:not(.empty){padding-top:var(--sci-workbench-messagebox-padding)}:host:not(.content-selectable){-webkit-user-select:none;user-select:none}:host>div.slot.text{word-break:break-word;white-space:pre-line;text-align:var(--sci-workbench-messagebox-text-align)}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: SciDimensionDirective, selector: "[sciDimension]", inputs: ["emitOutsideAngular"], outputs: ["sciDimensionChange"] }, { kind: "directive", type: WorkbenchDialogHeaderDirective, selector: "ng-template[wbDialogHeader]", inputs: ["divider"] }, { kind: "directive", type: WorkbenchDialogFooterDirective, selector: "ng-template[wbDialogFooter]", inputs: ["divider"] }, { kind: "component", type: MessageBoxHeaderComponent, selector: "wb-message-box-header", inputs: ["title", "severity"] }, { kind: "component", type: MessageBoxFooterComponent, selector: "wb-message-box-footer", inputs: ["actions", "severity"], outputs: ["action", "preferredSizeChange"] }, { kind: "pipe", type: TypeofPipe, name: "wbTypeof" }, { kind: "pipe", type: TextPipe, name: "wbText" }] });
10250
10251
  }
10251
10252
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchMessageBoxComponent, decorators: [{
10252
10253
  type: Component,
@@ -10266,7 +10267,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
10266
10267
  '[class.content-selectable]': 'options()?.contentSelectable',
10267
10268
  '[class.has-title]': '!!this.options()?.title',
10268
10269
  '(keydown.escape)': 'onEscape()',
10269
- }, template: "@let options = this.options() ?? {};\n<ng-template wbDialogHeader [divider]=\"false\">\n <wb-message-box-header [title]=\"options.title\" [severity]=\"options.severity ?? 'info'\"/>\n</ng-template>\n\n@let message = this.message();\n<div class=\"message e2e-message\" [class.text]=\"message | wbTypeof:'string'\" sciDimension (sciDimensionChange)=\"onContentDimensionChange($event)\">\n @if (message | wbTypeof:'string') {\n {{($any(message) | wbText)()}}\n } @else {\n <ng-container *ngComponentOutlet=\"message; inputs: options.inputs\"/>\n }\n</div>\n\n<ng-template wbDialogFooter>\n <wb-message-box-footer [actions]=\"options.actions ?? {ok: '%workbench.ok.action'}\"\n [severity]=\"options.severity ?? 'info'\"\n (action)=\"onAction($event)\"\n (keydown.escape)=\"onEscape()\"\n (preferredSizeChange)=\"onFooterPreferredSizeChange($event)\"/>\n</ng-template>\n", styles: [":host{display:grid;outline:none;padding-inline:var(--sci-workbench-messagebox-padding);padding-bottom:var(--sci-workbench-messagebox-padding)}:host.has-title:not(.empty){padding-top:var(--sci-workbench-messagebox-padding)}:host:not(.content-selectable){-webkit-user-select:none;user-select:none}:host>div.message.text{word-break:break-word;white-space:pre-line;text-align:var(--sci-workbench-messagebox-text-align)}\n"] }]
10270
+ }, template: "@let options = this.options() ?? {};\n<ng-template wbDialogHeader [divider]=\"false\">\n <wb-message-box-header [title]=\"options.title\" [severity]=\"options.severity ?? 'info'\"/>\n</ng-template>\n\n@let message = this.message();\n<div class=\"slot e2e-slot\" [class.text]=\"message | wbTypeof:'string'\" sciDimension (sciDimensionChange)=\"onContentDimensionChange($event)\">\n @if (message | wbTypeof:'string') {\n {{($any(message) | wbText)()}}\n } @else {\n <ng-container *ngComponentOutlet=\"message; inputs: options.inputs\"/>\n }\n</div>\n\n<ng-template wbDialogFooter>\n <wb-message-box-footer [actions]=\"options.actions ?? {ok: '%workbench.ok.action'}\"\n [severity]=\"options.severity ?? 'info'\"\n (action)=\"onAction($event)\"\n (keydown.escape)=\"onEscape()\"\n (preferredSizeChange)=\"onFooterPreferredSizeChange($event)\"/>\n</ng-template>\n", styles: [":host{display:grid;outline:none;padding-inline:var(--sci-workbench-messagebox-padding);padding-bottom:var(--sci-workbench-messagebox-padding)}:host.has-title:not(.empty){padding-top:var(--sci-workbench-messagebox-padding)}:host:not(.content-selectable){-webkit-user-select:none;user-select:none}:host>div.slot.text{word-break:break-word;white-space:pre-line;text-align:var(--sci-workbench-messagebox-text-align)}\n"] }]
10270
10271
  }], ctorParameters: () => [], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }] } });
10271
10272
  function nullIfEmptyMessage(message) {
10272
10273
  return message !== '' ? message : null;
@@ -10923,6 +10924,38 @@ const LEGACY_POPUP_INPUT = new InjectionToken('LEGACY_POPUP_INPUT');
10923
10924
  *
10924
10925
  * SPDX-License-Identifier: EPL-2.0
10925
10926
  */
10927
+ /**
10928
+ * Registry for {@link WorkbenchNotification} elements.
10929
+ */
10930
+ class WorkbenchNotificationRegistry extends WorkbenchElementRegistry {
10931
+ /**
10932
+ * Gets the most recently opened notification.
10933
+ */
10934
+ top;
10935
+ constructor() {
10936
+ super({
10937
+ nullElementErrorFn: notificationId => Error(`[NullNotificationError] Notification '${notificationId}' not found.`),
10938
+ onUnregister: notification => notification.destroy(),
10939
+ });
10940
+ this.top = computed(() => this.elements().at(-1), { ...(ngDevMode ? { debugName: "top" } : {}) });
10941
+ }
10942
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchNotificationRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
10943
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchNotificationRegistry, providedIn: 'root' });
10944
+ }
10945
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchNotificationRegistry, decorators: [{
10946
+ type: Injectable,
10947
+ args: [{ providedIn: 'root' }]
10948
+ }], ctorParameters: () => [] });
10949
+
10950
+ /*
10951
+ * Copyright (c) 2018-2026 Swiss Federal Railways
10952
+ *
10953
+ * This program and the accompanying materials are made
10954
+ * available under the terms of the Eclipse Public License 2.0
10955
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
10956
+ *
10957
+ * SPDX-License-Identifier: EPL-2.0
10958
+ */
10926
10959
  /**
10927
10960
  * Creates the invocation context for given element.
10928
10961
  *
@@ -10978,6 +11011,16 @@ function createInvocationContext(elementId, options) {
10978
11011
  peripheral: signal(false),
10979
11012
  };
10980
11013
  }
11014
+ else if (isNotificationId(contextualElementId)) {
11015
+ const notification = injector.get(WorkbenchNotificationRegistry).get(contextualElementId);
11016
+ return {
11017
+ elementId: notification.id,
11018
+ attached: computed(() => !notification.destroyed()),
11019
+ bounds: notification.bounds,
11020
+ destroyed: notification.destroyed,
11021
+ peripheral: signal(true),
11022
+ };
11023
+ }
10981
11024
  return null;
10982
11025
  }
10983
11026
 
@@ -11175,7 +11218,7 @@ function provideWorkbenchDialogContext() {
11175
11218
  }
11176
11219
 
11177
11220
  /*
11178
- * Copyright (c) 2018-2023 Swiss Federal Railways
11221
+ * Copyright (c) 2018-2026 Swiss Federal Railways
11179
11222
  *
11180
11223
  * This program and the accompanying materials are made
11181
11224
  * available under the terms of the Eclipse Public License 2.0
@@ -11210,7 +11253,7 @@ class ɵWorkbenchDialog {
11210
11253
  focused = computed(() => this._focusMonitor.activeElement()?.id === this.id, { ...(ngDevMode ? { debugName: "focused" } : {}) });
11211
11254
  attached;
11212
11255
  destroyed = signal(false, { ...(ngDevMode ? { debugName: "destroyed" } : {}) });
11213
- bounds = boundingClientRect(computed(() => this._componentRef()?.instance.dialogContent()));
11256
+ bounds = boundingClientRect(computed(() => this._componentRef()?.instance.dialogSlotBounds()));
11214
11257
  modal;
11215
11258
  blinking$ = new BehaviorSubject(false);
11216
11259
  header;
@@ -13680,7 +13723,7 @@ class PartComponent {
13680
13723
  inject(DestroyRef).onDestroy(() => logger.debug(() => `Destroying PartComponent [partId=${this.part.id}]'`, LoggerNames.LIFECYCLE));
13681
13724
  }
13682
13725
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: PartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13683
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: PartComponent, isStandalone: true, selector: "wb-part", host: { properties: { "attr.data-partid": "part.id", "attr.data-peripheral": "part.peripheral() ? '' : null", "attr.data-grid": "dasherize(part.gridName())", "attr.data-active": "part.active() ? '' : null", "attr.data-referencepart": "part.referencePart() ? '' : null", "attr.tabindex": "-1", "class": "part.classList.asList()" } }, ngImport: i0, template: "@if (part.title() || part.views().length || part.actions().length || part.canMinimize()) {\n <wb-part-bar/>\n}\n\n@if (part.views().length) {\n <!-- Prevent splitting if there is no active view, i.e, when dragging the last view out of the tabbar. -->\n @let canSplit = !!part.activeView();\n <div wbViewDropZone\n [wbViewDropZoneRegionSize]=\".25\"\n [wbViewDropZonePlaceholderSize]=\".5\"\n [wbViewDropZoneAttributes]=\"{'data-partid': part.id}\"\n [wbViewDropZoneRegions]=\"canDrop() && {center: true, north: canSplit, south: canSplit, west: canSplit, east: canSplit}\"\n (wbViewDropZoneDrop)=\"onViewDrop($event)\"\n class=\"content e2e-content e2e-view-content\">\n <ng-container *wbPortalOutlet=\"part.activeView()?.slot!.portal; destroyOnDetach: false\"/>\n </div>\n} @else {\n <div wbViewDropZone\n [wbViewDropZoneRegions]=\"canDrop() && {center: false, north: true, south: true, west: true, east: true}\"\n [wbViewDropZoneAttributes]=\"{'data-partid': part.id}\"\n (wbViewDropZoneDrop)=\"onViewDrop($event)\"\n class=\"content e2e-content e2e-part-content\">\n <ng-container *wbPortalOutlet=\"part.slot.portal; destroyOnDetach: false\"/>\n </div>\n}\n", styles: [":host{display:flex;flex-direction:column;outline:none;background-color:var(--sci-workbench-part-background-color);overflow:hidden}:host[data-peripheral]{background-color:var(--sci-workbench-part-peripheral-background-color)}:host>wb-part-bar{flex:none}:host>div.content{flex:auto;display:grid;position:relative}\n"], dependencies: [{ kind: "component", type: PartBarComponent, selector: "wb-part-bar" }, { kind: "directive", type: ViewDropZoneDirective, selector: "[wbViewDropZone]", inputs: ["wbViewDropZoneRegions", "wbViewDropZoneAttributes", "wbViewDropZoneRegionSize", "wbViewDropZonePlaceholderSize"], outputs: ["wbViewDropZoneDrop"] }, { kind: "directive", type: WorkbenchPortalOutletDirective, selector: "ng-template[wbPortalOutlet]", inputs: ["wbPortalOutlet", "wbPortalOutletDestroyOnDetach"] }] });
13726
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: PartComponent, isStandalone: true, selector: "wb-part", host: { properties: { "attr.data-partid": "part.id", "attr.data-peripheral": "part.peripheral() ? '' : null", "attr.data-grid": "dasherize(part.gridName())", "attr.data-active": "part.active() ? '' : null", "attr.data-referencepart": "part.referencePart() ? '' : null", "attr.tabindex": "-1", "class": "part.classList.asList()" } }, ngImport: i0, template: "@if (part.title() || part.views().length || part.actions().length || part.canMinimize()) {\n <wb-part-bar/>\n}\n\n@if (part.views().length) {\n <!-- Prevent splitting if there is no active view, i.e, when dragging the last view out of the tabbar. -->\n @let canSplit = !!part.activeView();\n <div wbViewDropZone\n [wbViewDropZoneRegionSize]=\".25\"\n [wbViewDropZonePlaceholderSize]=\".5\"\n [wbViewDropZoneAttributes]=\"{'data-partid': part.id}\"\n [wbViewDropZoneRegions]=\"canDrop() && {center: true, north: canSplit, south: canSplit, west: canSplit, east: canSplit}\"\n (wbViewDropZoneDrop)=\"onViewDrop($event)\"\n class=\"slot e2e-slot e2e-view-slot\">\n <ng-container *wbPortalOutlet=\"part.activeView()?.slot!.portal; destroyOnDetach: false\"/>\n </div>\n} @else {\n <div wbViewDropZone\n [wbViewDropZoneRegions]=\"canDrop() && {center: false, north: true, south: true, west: true, east: true}\"\n [wbViewDropZoneAttributes]=\"{'data-partid': part.id}\"\n (wbViewDropZoneDrop)=\"onViewDrop($event)\"\n class=\"slot e2e-slot e2e-part-slot\">\n <ng-container *wbPortalOutlet=\"part.slot.portal; destroyOnDetach: false\"/>\n </div>\n}\n", styles: [":host{display:flex;flex-direction:column;outline:none;background-color:var(--sci-workbench-part-background-color);overflow:hidden}:host[data-peripheral]{background-color:var(--sci-workbench-part-peripheral-background-color)}:host>wb-part-bar{flex:none}:host>div.slot{flex:auto;display:grid;position:relative}\n"], dependencies: [{ kind: "component", type: PartBarComponent, selector: "wb-part-bar" }, { kind: "directive", type: ViewDropZoneDirective, selector: "[wbViewDropZone]", inputs: ["wbViewDropZoneRegions", "wbViewDropZoneAttributes", "wbViewDropZoneRegionSize", "wbViewDropZonePlaceholderSize"], outputs: ["wbViewDropZoneDrop"] }, { kind: "directive", type: WorkbenchPortalOutletDirective, selector: "ng-template[wbPortalOutlet]", inputs: ["wbPortalOutlet", "wbPortalOutletDestroyOnDetach"] }] });
13684
13727
  }
13685
13728
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: PartComponent, decorators: [{
13686
13729
  type: Component,
@@ -13696,7 +13739,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
13696
13739
  '[attr.data-referencepart]': `part.referencePart() ? '' : null`,
13697
13740
  '[attr.tabindex]': '-1',
13698
13741
  '[class]': 'part.classList.asList()',
13699
- }, template: "@if (part.title() || part.views().length || part.actions().length || part.canMinimize()) {\n <wb-part-bar/>\n}\n\n@if (part.views().length) {\n <!-- Prevent splitting if there is no active view, i.e, when dragging the last view out of the tabbar. -->\n @let canSplit = !!part.activeView();\n <div wbViewDropZone\n [wbViewDropZoneRegionSize]=\".25\"\n [wbViewDropZonePlaceholderSize]=\".5\"\n [wbViewDropZoneAttributes]=\"{'data-partid': part.id}\"\n [wbViewDropZoneRegions]=\"canDrop() && {center: true, north: canSplit, south: canSplit, west: canSplit, east: canSplit}\"\n (wbViewDropZoneDrop)=\"onViewDrop($event)\"\n class=\"content e2e-content e2e-view-content\">\n <ng-container *wbPortalOutlet=\"part.activeView()?.slot!.portal; destroyOnDetach: false\"/>\n </div>\n} @else {\n <div wbViewDropZone\n [wbViewDropZoneRegions]=\"canDrop() && {center: false, north: true, south: true, west: true, east: true}\"\n [wbViewDropZoneAttributes]=\"{'data-partid': part.id}\"\n (wbViewDropZoneDrop)=\"onViewDrop($event)\"\n class=\"content e2e-content e2e-part-content\">\n <ng-container *wbPortalOutlet=\"part.slot.portal; destroyOnDetach: false\"/>\n </div>\n}\n", styles: [":host{display:flex;flex-direction:column;outline:none;background-color:var(--sci-workbench-part-background-color);overflow:hidden}:host[data-peripheral]{background-color:var(--sci-workbench-part-peripheral-background-color)}:host>wb-part-bar{flex:none}:host>div.content{flex:auto;display:grid;position:relative}\n"] }]
13742
+ }, template: "@if (part.title() || part.views().length || part.actions().length || part.canMinimize()) {\n <wb-part-bar/>\n}\n\n@if (part.views().length) {\n <!-- Prevent splitting if there is no active view, i.e, when dragging the last view out of the tabbar. -->\n @let canSplit = !!part.activeView();\n <div wbViewDropZone\n [wbViewDropZoneRegionSize]=\".25\"\n [wbViewDropZonePlaceholderSize]=\".5\"\n [wbViewDropZoneAttributes]=\"{'data-partid': part.id}\"\n [wbViewDropZoneRegions]=\"canDrop() && {center: true, north: canSplit, south: canSplit, west: canSplit, east: canSplit}\"\n (wbViewDropZoneDrop)=\"onViewDrop($event)\"\n class=\"slot e2e-slot e2e-view-slot\">\n <ng-container *wbPortalOutlet=\"part.activeView()?.slot!.portal; destroyOnDetach: false\"/>\n </div>\n} @else {\n <div wbViewDropZone\n [wbViewDropZoneRegions]=\"canDrop() && {center: false, north: true, south: true, west: true, east: true}\"\n [wbViewDropZoneAttributes]=\"{'data-partid': part.id}\"\n (wbViewDropZoneDrop)=\"onViewDrop($event)\"\n class=\"slot e2e-slot e2e-part-slot\">\n <ng-container *wbPortalOutlet=\"part.slot.portal; destroyOnDetach: false\"/>\n </div>\n}\n", styles: [":host{display:flex;flex-direction:column;outline:none;background-color:var(--sci-workbench-part-background-color);overflow:hidden}:host[data-peripheral]{background-color:var(--sci-workbench-part-peripheral-background-color)}:host>wb-part-bar{flex:none}:host>div.slot{flex:auto;display:grid;position:relative}\n"] }]
13700
13743
  }], ctorParameters: () => [] });
13701
13744
 
13702
13745
  /*
@@ -17815,27 +17858,183 @@ class Notification {
17815
17858
  * SPDX-License-Identifier: EPL-2.0
17816
17859
  */
17817
17860
  /**
17818
- * Registry for {@link WorkbenchNotification} elements.
17861
+ * TODO [Angular 22] Remove with Angular 22. Used for backward compatiblity.
17819
17862
  */
17820
- class WorkbenchNotificationRegistry extends WorkbenchElementRegistry {
17863
+ class RemoveLegacyInputPipe {
17864
+ transform(inputs) {
17865
+ const inputsCopy = { ...inputs ?? {} };
17866
+ delete inputsCopy[LEGACY_NOTIFICATION_INPUT]; // eslint-disable-line @typescript-eslint/no-dynamic-delete
17867
+ return inputsCopy;
17868
+ }
17869
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: RemoveLegacyInputPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
17870
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.1", ngImport: i0, type: RemoveLegacyInputPipe, isStandalone: true, name: "wbRemoveLegacyInput" });
17871
+ }
17872
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: RemoveLegacyInputPipe, decorators: [{
17873
+ type: Pipe,
17874
+ args: [{ name: 'wbRemoveLegacyInput' }]
17875
+ }] });
17876
+
17877
+ /*
17878
+ * Copyright (c) 2018-2026 Swiss Federal Railways
17879
+ *
17880
+ * This program and the accompanying materials are made
17881
+ * available under the terms of the Eclipse Public License 2.0
17882
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
17883
+ *
17884
+ * SPDX-License-Identifier: EPL-2.0
17885
+ */
17886
+ /**
17887
+ * Renders the content of a workbench notification.
17888
+ */
17889
+ class WorkbenchNotificationComponent {
17890
+ notification = inject(ɵWorkbenchNotification);
17891
+ hover = signal(false, { ...(ngDevMode ? { debugName: "hover" } : {}) });
17892
+ slotAnchorName = this.notification.id.replace('.', '_'); // Anchor must not contain a dot.
17893
+ notificationSlotBounds = viewChild('slot_bounds', { ...(ngDevMode ? { debugName: "notificationSlotBounds" } : {}), read: (ElementRef) });
17894
+ constructor() {
17895
+ this.installAutoCloseTimer();
17896
+ this.closeOnEscapeIfOnTop();
17897
+ trackFocus(inject(ElementRef).nativeElement, this.notification);
17898
+ }
17899
+ onClose() {
17900
+ this.notification.close();
17901
+ }
17902
+ onEscape(event) {
17903
+ if (this.notification.focused()) {
17904
+ event.stopPropagation(); // stop propagation to prevent closing the most recently displayed notification
17905
+ this.notification.close();
17906
+ }
17907
+ }
17908
+ onAuxClick(event) {
17909
+ if (event.button === 1) { // primary aux button
17910
+ event.preventDefault(); // prevent user-agent default action
17911
+ this.notification.close();
17912
+ }
17913
+ }
17821
17914
  /**
17822
- * Gets the most recently opened notification.
17915
+ * Closes this notification when pressing escape if it is the most recently displayed notification.
17823
17916
  */
17824
- top;
17825
- constructor() {
17826
- super({
17827
- nullElementErrorFn: notificationId => Error(`[NullNotificationError] Notification '${notificationId}' not found.`),
17828
- onUnregister: notification => notification.destroy(),
17917
+ closeOnEscapeIfOnTop() {
17918
+ const zone = inject(NgZone);
17919
+ const document = inject(DOCUMENT);
17920
+ effect(onCleanup => {
17921
+ if (!this.notification.top()) {
17922
+ return;
17923
+ }
17924
+ const subscription = fromEvent(document, 'keydown')
17925
+ .pipe(subscribeIn(fn => zone.runOutsideAngular(fn)), filter((event) => event.key === 'Escape'), observeIn(fn => zone.run(fn)))
17926
+ .subscribe(() => this.notification.close());
17927
+ onCleanup(() => subscription.unsubscribe());
17829
17928
  });
17830
- this.top = computed(() => this.elements().at(-1), { ...(ngDevMode ? { debugName: "top" } : {}) });
17831
17929
  }
17832
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchNotificationRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
17833
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchNotificationRegistry, providedIn: 'root' });
17930
+ /**
17931
+ * Installs a timer to close the notification.
17932
+ */
17933
+ installAutoCloseTimer() {
17934
+ effect(onCleanup => {
17935
+ const duration = this.notification.duration();
17936
+ const focus = this.notification.focused();
17937
+ const blockedBy = this.notification.blockedBy();
17938
+ const hover = this.hover();
17939
+ if (hover || focus || blockedBy) {
17940
+ return;
17941
+ }
17942
+ untracked(() => {
17943
+ const subscription = fromDuration$(duration).subscribe(() => this.notification.close());
17944
+ onCleanup(() => subscription.unsubscribe());
17945
+ });
17946
+ });
17947
+ function fromDuration$(duration) {
17948
+ switch (duration) {
17949
+ case 'short':
17950
+ return timer(7000);
17951
+ case 'medium':
17952
+ return timer(15000);
17953
+ case 'long':
17954
+ return timer(30000);
17955
+ default:
17956
+ if (typeof duration === 'number') {
17957
+ return timer(duration);
17958
+ }
17959
+ return NEVER;
17960
+ }
17961
+ }
17962
+ }
17963
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchNotificationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
17964
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: WorkbenchNotificationComponent, isStandalone: true, selector: "wb-notification", host: { listeners: { "mouseenter": "hover.set(true)", "mouseleave": "hover.set(false)", "auxclick": "onAuxClick($event)", "keydown.escape": "onEscape($event)" }, properties: { "attr.data-notificationid": "notification.id", "attr.data-severity": "notification.severity()", "style.min-height": "notification.size.minHeight()", "style.height": "notification.size.height()", "style.max-height": "notification.size.maxHeight()", "style.--\u0275slot-anchor": "`--${slotAnchorName}`", "attr.tabindex": "-1", "class": "notification.cssClass()" } }, providers: [
17965
+ configureNotificationGlassPane(),
17966
+ ], viewQueries: [{ propertyName: "notificationSlotBounds", first: true, predicate: ["slot_bounds"], descendants: true, read: ElementRef, isSignal: true }], hostDirectives: [{ directive: GlassPaneDirective }], ngImport: i0, template: "<!-- Title -->\n@if (notification.title(); as title) {\n <header class=\"e2e-title\">{{(title | wbText)()}}</header>\n}\n\n<!-- Message -->\n<div class=\"slot e2e-slot\" [class.text]=\"!!notification.slot.text?.length\">\n @if (notification.slot.text?.length) {\n {{(notification.slot.text | wbText)()}}\n } @else if (notification.slot.component) {\n <sci-viewport class=\"e2e-notification-slot\">\n <ng-container *ngComponentOutlet=\"notification.slot.component; inputs: notification.inputs | wbRemoveLegacyInput;\"/>\n </sci-viewport>\n\n <!-- Extra DIV to capture bounds available to slotted content, excluding viewport content padding. May differ from the actual content size if content overflows or does not fill the slot. -->\n <div class=\"slot-bounds e2e-notification-slot-bounds\" #slot_bounds></div>\n }\n</div>\n\n<button (click)=\"onClose()\"\n [title]=\"('%workbench.close.tooltip' | wbText)()\"\n class=\"close e2e-close\">\n <wb-icon icon=\"workbench.close\"/>\n</button>\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:.75em;background-color:var(--sci-color-background-elevation);color:var(--sci-color-text);font-size:.9em;border:1px solid var(--sci-color-border);border-radius:var(--sci-corner);box-shadow:var(--sci-elevation) var(--sci-static-color-black);padding:1em 0;overflow:hidden;outline:none;position:relative}:host:before{content:\"\";position:absolute;top:0;left:0;bottom:0;width:var(--sci-workbench-notification-severity-indicator-size)}:host[data-severity=info]:before{background-color:var(--sci-color-accent)}:host[data-severity=warn]:before{background-color:var(--sci-color-notice)}:host[data-severity=error]:before{background-color:var(--sci-color-negative)}:host>header{flex:none;font-weight:700;padding:0 var(--sci-workbench-notification-padding);word-break:break-word;white-space:pre-line}:host>div.slot{flex:auto;overflow:hidden;display:grid}:host>div.slot.text{word-break:break-word;white-space:pre-line;padding:0 var(--sci-workbench-notification-padding)}:host>div.slot>sci-viewport{anchor-name:var(--\\275slot-anchor)}:host>div.slot>sci-viewport::part(content){padding-inline:var(--sci-workbench-notification-padding)}:host>div.slot>div.slot-bounds{position:absolute;position-anchor:var(--\\275slot-anchor);inset:anchor(top) anchor(right) anchor(bottom) anchor(left);margin-inline:var(--sci-workbench-notification-padding);visibility:hidden}:host>button.close:is(button,#sci-reset){all:unset;display:inline-grid;place-content:center;place-items:center;padding:.25em;border-radius:var(--sci-corner);-webkit-user-select:none;user-select:none;overflow:hidden;cursor:var(--sci-workbench-button-cursor)}:host>button.close:is(button,#sci-reset):hover:where(:not(:disabled)){background-color:var(--sci-workbench-button-background-color-hover)}:host>button.close:is(button,#sci-reset):active:where(:not(:disabled)){background-color:var(--sci-workbench-button-background-color-active)}:host>button.close:is(button,#sci-reset):focus:not(:focus-visible){outline:none}:host>button.close:is(button,#sci-reset):focus-visible{outline:var(--sci-workbench-button-outline-width-focus) solid var(--sci-color-accent)}:host>button.close:is(button,#sci-reset):disabled{color:var(--sci-color-gray-500)}:host>button.close:is(button,#sci-reset){position:absolute;top:.275em;right:.275em;padding:.125em;border-radius:var(--sci-corner-small);font-size:1rem}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "wb-icon", inputs: ["icon"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: SciViewportComponent, selector: "sci-viewport", inputs: ["scrollbarStyle"], outputs: ["scroll"] }, { kind: "pipe", type: TextPipe, name: "wbText" }, { kind: "pipe", type: RemoveLegacyInputPipe, name: "wbRemoveLegacyInput" }] });
17967
+ }
17968
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchNotificationComponent, decorators: [{
17969
+ type: Component,
17970
+ args: [{ selector: 'wb-notification', imports: [
17971
+ TextPipe,
17972
+ IconComponent,
17973
+ NgComponentOutlet,
17974
+ RemoveLegacyInputPipe,
17975
+ SciViewportComponent,
17976
+ ], hostDirectives: [
17977
+ GlassPaneDirective,
17978
+ ], providers: [
17979
+ configureNotificationGlassPane(),
17980
+ ], host: {
17981
+ '[attr.data-notificationid]': 'notification.id',
17982
+ '[attr.data-severity]': 'notification.severity()',
17983
+ '[style.min-height]': 'notification.size.minHeight()',
17984
+ '[style.height]': 'notification.size.height()',
17985
+ '[style.max-height]': 'notification.size.maxHeight()',
17986
+ '[style.--ɵslot-anchor]': '`--${slotAnchorName}`',
17987
+ '[attr.tabindex]': '-1',
17988
+ '[class]': 'notification.cssClass()',
17989
+ '(mouseenter)': 'hover.set(true)',
17990
+ '(mouseleave)': 'hover.set(false)',
17991
+ '(auxclick)': 'onAuxClick($event)',
17992
+ '(keydown.escape)': 'onEscape($event)',
17993
+ }, template: "<!-- Title -->\n@if (notification.title(); as title) {\n <header class=\"e2e-title\">{{(title | wbText)()}}</header>\n}\n\n<!-- Message -->\n<div class=\"slot e2e-slot\" [class.text]=\"!!notification.slot.text?.length\">\n @if (notification.slot.text?.length) {\n {{(notification.slot.text | wbText)()}}\n } @else if (notification.slot.component) {\n <sci-viewport class=\"e2e-notification-slot\">\n <ng-container *ngComponentOutlet=\"notification.slot.component; inputs: notification.inputs | wbRemoveLegacyInput;\"/>\n </sci-viewport>\n\n <!-- Extra DIV to capture bounds available to slotted content, excluding viewport content padding. May differ from the actual content size if content overflows or does not fill the slot. -->\n <div class=\"slot-bounds e2e-notification-slot-bounds\" #slot_bounds></div>\n }\n</div>\n\n<button (click)=\"onClose()\"\n [title]=\"('%workbench.close.tooltip' | wbText)()\"\n class=\"close e2e-close\">\n <wb-icon icon=\"workbench.close\"/>\n</button>\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:.75em;background-color:var(--sci-color-background-elevation);color:var(--sci-color-text);font-size:.9em;border:1px solid var(--sci-color-border);border-radius:var(--sci-corner);box-shadow:var(--sci-elevation) var(--sci-static-color-black);padding:1em 0;overflow:hidden;outline:none;position:relative}:host:before{content:\"\";position:absolute;top:0;left:0;bottom:0;width:var(--sci-workbench-notification-severity-indicator-size)}:host[data-severity=info]:before{background-color:var(--sci-color-accent)}:host[data-severity=warn]:before{background-color:var(--sci-color-notice)}:host[data-severity=error]:before{background-color:var(--sci-color-negative)}:host>header{flex:none;font-weight:700;padding:0 var(--sci-workbench-notification-padding);word-break:break-word;white-space:pre-line}:host>div.slot{flex:auto;overflow:hidden;display:grid}:host>div.slot.text{word-break:break-word;white-space:pre-line;padding:0 var(--sci-workbench-notification-padding)}:host>div.slot>sci-viewport{anchor-name:var(--\\275slot-anchor)}:host>div.slot>sci-viewport::part(content){padding-inline:var(--sci-workbench-notification-padding)}:host>div.slot>div.slot-bounds{position:absolute;position-anchor:var(--\\275slot-anchor);inset:anchor(top) anchor(right) anchor(bottom) anchor(left);margin-inline:var(--sci-workbench-notification-padding);visibility:hidden}:host>button.close:is(button,#sci-reset){all:unset;display:inline-grid;place-content:center;place-items:center;padding:.25em;border-radius:var(--sci-corner);-webkit-user-select:none;user-select:none;overflow:hidden;cursor:var(--sci-workbench-button-cursor)}:host>button.close:is(button,#sci-reset):hover:where(:not(:disabled)){background-color:var(--sci-workbench-button-background-color-hover)}:host>button.close:is(button,#sci-reset):active:where(:not(:disabled)){background-color:var(--sci-workbench-button-background-color-active)}:host>button.close:is(button,#sci-reset):focus:not(:focus-visible){outline:none}:host>button.close:is(button,#sci-reset):focus-visible{outline:var(--sci-workbench-button-outline-width-focus) solid var(--sci-color-accent)}:host>button.close:is(button,#sci-reset):disabled{color:var(--sci-color-gray-500)}:host>button.close:is(button,#sci-reset){position:absolute;top:.275em;right:.275em;padding:.125em;border-radius:var(--sci-corner-small);font-size:1rem}\n"] }]
17994
+ }], ctorParameters: () => [], propDecorators: { notificationSlotBounds: [{ type: i0.ViewChild, args: ['slot_bounds', { ...{ read: (ElementRef) }, isSignal: true }] }] } });
17995
+ /**
17996
+ * Blocks this notification when dialog(s) overlay it.
17997
+ */
17998
+ function configureNotificationGlassPane() {
17999
+ return [
18000
+ {
18001
+ provide: GLASS_PANE_BLOCKABLE,
18002
+ useFactory: () => inject(ɵWorkbenchNotification),
18003
+ },
18004
+ {
18005
+ provide: GLASS_PANE_OPTIONS,
18006
+ useFactory: () => ({ attributes: { 'data-notificationid': inject(ɵWorkbenchNotification).id } }),
18007
+ },
18008
+ ];
18009
+ }
18010
+
18011
+ /*
18012
+ * Copyright (c) 2018-2026 Swiss Federal Railways
18013
+ *
18014
+ * This program and the accompanying materials are made
18015
+ * available under the terms of the Eclipse Public License 2.0
18016
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
18017
+ *
18018
+ * SPDX-License-Identifier: EPL-2.0
18019
+ */
18020
+ /**
18021
+ * DI token to register providers available for DI if in the context of a workbench notification.
18022
+ */
18023
+ const WORKBENCH_NOTIFICATION_CONTEXT = new InjectionToken('WORKBENCH_NOTIFICATION_CONTEXT');
18024
+ /**
18025
+ * Provides providers available for DI if in the context of a workbench notification.
18026
+ */
18027
+ function provideWorkbenchNotificationContext() {
18028
+ return {
18029
+ provide: WORKBENCH_NOTIFICATION_CONTEXT,
18030
+ useFactory: () => [
18031
+ provideWorkbenchDialogService(),
18032
+ provideWorkbenchMessageBoxService(),
18033
+ provideWorkbenchPopupService(),
18034
+ ],
18035
+ multi: true,
18036
+ };
17834
18037
  }
17835
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchNotificationRegistry, decorators: [{
17836
- type: Injectable,
17837
- args: [{ providedIn: 'root' }]
17838
- }], ctorParameters: () => [] });
17839
18038
 
17840
18039
  /** @inheritDoc */
17841
18040
  class ɵWorkbenchNotification {
@@ -17850,17 +18049,20 @@ class ɵWorkbenchNotification {
17850
18049
  _severity;
17851
18050
  _duration;
17852
18051
  _cssClass;
18052
+ portal;
17853
18053
  size = new ɵWorkbenchNotificationSize();
17854
18054
  focused = computed(() => this._focusMonitor.activeElement()?.id === this.id, { ...(ngDevMode ? { debugName: "focused" } : {}) });
17855
18055
  /** Checks if this notification is the most recently displayed notification. */
17856
18056
  top = computed(() => this._notificationRegistry.top() === this, { ...(ngDevMode ? { debugName: "top" } : {}) });
17857
18057
  destroyed = signal(false, { ...(ngDevMode ? { debugName: "destroyed" } : {}) });
18058
+ bounds;
18059
+ blockedBy;
17858
18060
  group;
17859
18061
  constructor(id, content, _options) {
17860
18062
  this.id = id;
17861
18063
  this._options = _options;
18064
+ this.portal = this.createPortal();
17862
18065
  this.slot = {
17863
- injector: this.createInjector(),
17864
18066
  component: typeof content === 'function' ? content : undefined,
17865
18067
  text: typeof content === 'string' ? content : undefined,
17866
18068
  };
@@ -17869,24 +18071,25 @@ class ɵWorkbenchNotification {
17869
18071
  this._duration = signal(this._options.duration ?? 'medium', { ...(ngDevMode ? { debugName: "_duration" } : {}) });
17870
18072
  this._cssClass = signal(Arrays.coerce(this._options.cssClass), { ...(ngDevMode ? { debugName: "_cssClass" } : {}) });
17871
18073
  this.group = this._options.group;
18074
+ this.blockedBy = inject(WorkbenchDialogRegistry).top(this.id);
18075
+ this.bounds = boundingClientRect(computed(() => this.portal.componentRef()?.instance.notificationSlotBounds()));
17872
18076
  inject(DestroyRef).onDestroy(() => this.destroyed.set(true));
17873
18077
  }
17874
18078
  /**
17875
- * Creates an injector to render content in the notification's injection context.
18079
+ * Creates a portal to render {@link WorkbenchNotificationComponent} in the notification's injection context.
17876
18080
  */
17877
- createInjector() {
17878
- const injector = Injector.create({
17879
- parent: this._options.injector ?? inject(Injector),
18081
+ createPortal() {
18082
+ return new WbComponentPortal(WorkbenchNotificationComponent, {
18083
+ injector: this._options.injector,
17880
18084
  providers: [
17881
18085
  { provide: ɵWorkbenchNotification, useValue: this },
17882
18086
  { provide: WorkbenchNotification, useExisting: ɵWorkbenchNotification },
17883
18087
  { provide: Notification, useClass: ɵNotification },
17884
18088
  { provide: WORKBENCH_ELEMENT, useExisting: ɵWorkbenchNotification },
18089
+ inject(WORKBENCH_NOTIFICATION_CONTEXT, { optional: true }) ?? [],
17885
18090
  ...this._options.providers ?? [],
17886
18091
  ],
17887
18092
  });
17888
- inject(DestroyRef).onDestroy(() => injector.destroy());
17889
- return injector;
17890
18093
  }
17891
18094
  /** @inheritDoc */
17892
18095
  get title() {
@@ -17922,6 +18125,9 @@ class ɵWorkbenchNotification {
17922
18125
  }
17923
18126
  /** @inheritDoc */
17924
18127
  close() {
18128
+ if (this.blockedBy()) {
18129
+ return;
18130
+ }
17925
18131
  this.destroy();
17926
18132
  }
17927
18133
  /**
@@ -18434,6 +18640,7 @@ function provideMicrofrontendNotification() {
18434
18640
  MicrofrontendNotificationCapabilityValidator,
18435
18641
  MicrofrontendTextNotificationCapabilityProvider,
18436
18642
  MicrofrontendNotificationIntentHandler,
18643
+ provideWorkbenchNotificationContext(),
18437
18644
  provideMicrofrontendTextNotificationRoute(),
18438
18645
  provideMicrofrontendPlatformInitializer(onPreStartup, { phase: MicrofrontendPlatformStartupPhase.PreStartup }),
18439
18646
  ]);
@@ -18445,6 +18652,20 @@ function provideMicrofrontendNotification() {
18445
18652
  // Register notification intent handler.
18446
18653
  Beans.register(IntentInterceptor, { useValue: inject(MicrofrontendNotificationIntentHandler), multi: true });
18447
18654
  }
18655
+ /**
18656
+ * Provides beans of @scion/workbench-client available for DI if in the context of a workbench notification.
18657
+ */
18658
+ function provideWorkbenchNotificationContext() {
18659
+ return {
18660
+ provide: WORKBENCH_NOTIFICATION_CONTEXT,
18661
+ useFactory: () => [
18662
+ { provide: WorkbenchDialogService$1, useFactory: () => new _WorkbenchDialogService(inject(WorkbenchNotification).id) },
18663
+ { provide: WorkbenchMessageBoxService$1, useFactory: () => new _WorkbenchMessageBoxService(inject(WorkbenchNotification).id) },
18664
+ { provide: WorkbenchPopupService$1, useFactory: () => new _WorkbenchPopupService(inject(WorkbenchNotification).id) },
18665
+ ],
18666
+ multi: true,
18667
+ };
18668
+ }
18448
18669
  }
18449
18670
 
18450
18671
  /*
@@ -20291,6 +20512,7 @@ function provideWorkbench(config) {
20291
20512
  provideWorkbenchViewContext(),
20292
20513
  provideWorkbenchDialogContext(),
20293
20514
  provideWorkbenchPopupContext(),
20515
+ provideWorkbenchNotificationContext(),
20294
20516
  provideWorkbenchMicrofrontendSupport(config),
20295
20517
  ]);
20296
20518
  }
@@ -20384,32 +20606,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
20384
20606
  args: [{ selector: 'wb-splash', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SciThrobberComponent], template: "<sci-throbber type=\"ellipsis\"/>\n", styles: [":host{display:grid;justify-content:center;margin-top:3em}:host>sci-throbber{--sci-throbber-size: 80px}\n"] }]
20385
20607
  }] });
20386
20608
 
20387
- /*
20388
- * Copyright (c) 2018-2025 Swiss Federal Railways
20389
- *
20390
- * This program and the accompanying materials are made
20391
- * available under the terms of the Eclipse Public License 2.0
20392
- * which is available at https://www.eclipse.org/legal/epl-2.0/
20393
- *
20394
- * SPDX-License-Identifier: EPL-2.0
20395
- */
20396
- /**
20397
- * TODO [Angular 22] Remove with Angular 22. Used for backward compatiblity.
20398
- */
20399
- class RemoveLegacyInputPipe {
20400
- transform(inputs) {
20401
- const inputsCopy = { ...inputs ?? {} };
20402
- delete inputsCopy[LEGACY_NOTIFICATION_INPUT]; // eslint-disable-line @typescript-eslint/no-dynamic-delete
20403
- return inputsCopy;
20404
- }
20405
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: RemoveLegacyInputPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
20406
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.1", ngImport: i0, type: RemoveLegacyInputPipe, isStandalone: true, name: "wbRemoveLegacyInput" });
20407
- }
20408
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: RemoveLegacyInputPipe, decorators: [{
20409
- type: Pipe,
20410
- args: [{ name: 'wbRemoveLegacyInput' }]
20411
- }] });
20412
-
20413
20609
  /*
20414
20610
  * Copyright (c) 2018-2026 Swiss Federal Railways
20415
20611
  *
@@ -20419,140 +20615,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImpor
20419
20615
  *
20420
20616
  * SPDX-License-Identifier: EPL-2.0
20421
20617
  */
20422
- /**
20423
- * Renders the content of a workbench notification.
20424
- */
20425
- class WorkbenchNotificationComponent {
20426
- notification = input.required({ ...(ngDevMode ? { debugName: "notification" } : {}) });
20427
- hover = signal(false, { ...(ngDevMode ? { debugName: "hover" } : {}) });
20428
- constructor() {
20429
- this.installAutoCloseTimer();
20430
- this.installFocusTracker();
20431
- this.closeOnEscapeIfOnTop();
20432
- }
20433
- onClose() {
20434
- this.notification().close();
20435
- }
20436
- onEscape(event) {
20437
- if (this.notification().focused()) {
20438
- event.stopPropagation(); // stop propagation to prevent closing the most recently displayed notification
20439
- this.notification().close();
20440
- }
20441
- }
20442
- onAuxClick(event) {
20443
- if (event.button === 1) { // primary aux button
20444
- event.preventDefault(); // prevent user-agent default action
20445
- this.notification().close();
20446
- }
20447
- }
20448
- /**
20449
- * Closes this notification when pressing escape if it is the most recently displayed notification.
20450
- */
20451
- closeOnEscapeIfOnTop() {
20452
- const zone = inject(NgZone);
20453
- const document = inject(DOCUMENT);
20454
- effect(onCleanup => {
20455
- if (!this.notification().top()) {
20456
- return;
20457
- }
20458
- const subscription = fromEvent(document, 'keydown')
20459
- .pipe(subscribeIn(fn => zone.runOutsideAngular(fn)), filter((event) => event.key === 'Escape'), observeIn(fn => zone.run(fn)))
20460
- .subscribe(() => this.notification().close());
20461
- onCleanup(() => subscription.unsubscribe());
20462
- });
20463
- }
20464
- /**
20465
- * Installs a timer to close the notification.
20466
- */
20467
- installAutoCloseTimer() {
20468
- effect(onCleanup => {
20469
- const notification = this.notification();
20470
- const duration = notification.duration();
20471
- const focus = notification.focused();
20472
- const hover = this.hover();
20473
- if (hover || focus) {
20474
- return;
20475
- }
20476
- untracked(() => {
20477
- const subscription = fromDuration$(duration).subscribe(() => this.notification().close());
20478
- onCleanup(() => subscription.unsubscribe());
20479
- });
20480
- });
20481
- function fromDuration$(duration) {
20482
- switch (duration) {
20483
- case 'short':
20484
- return timer(7000);
20485
- case 'medium':
20486
- return timer(15000);
20487
- case 'long':
20488
- return timer(30000);
20489
- default:
20490
- if (typeof duration === 'number') {
20491
- return timer(duration);
20492
- }
20493
- return NEVER;
20494
- }
20495
- }
20496
- }
20497
- installFocusTracker() {
20498
- const host = inject(ElementRef).nativeElement;
20499
- const injector = inject(Injector);
20500
- effect(onCleanup => {
20501
- const notification = this.notification();
20502
- untracked(() => {
20503
- const tracker = runInInjectionContext(injector, () => trackFocus(host, notification));
20504
- onCleanup(() => tracker.destroy());
20505
- });
20506
- });
20507
- }
20508
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchNotificationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
20509
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: WorkbenchNotificationComponent, isStandalone: true, selector: "wb-notification", inputs: { notification: { classPropertyName: "notification", publicName: "notification", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "mouseenter": "hover.set(true)", "mouseleave": "hover.set(false)", "auxclick": "onAuxClick($event)", "keydown.escape": "onEscape($event)" }, properties: { "attr.data-notificationid": "notification().id", "attr.data-severity": "notification().severity()", "style.min-height": "notification().size.minHeight()", "style.height": "notification().size.height()", "style.max-height": "notification().size.maxHeight()", "attr.tabindex": "-1", "class": "notification().cssClass()" } }, ngImport: i0, template: "<!-- Title -->\n@if (notification().title(); as title) {\n <header class=\"e2e-title\">{{(title | wbText)()}}</header>\n}\n\n<!-- Message -->\n<div class=\"message e2e-message\" [class.text]=\"!!notification().slot.text?.length\">\n @if (notification().slot.text?.length) {\n {{(notification().slot.text | wbText)()}}\n } @else if (notification().slot.component) {\n <sci-viewport class=\"e2e-message-viewport\">\n <ng-container *ngComponentOutlet=\"notification().slot.component!; inputs: notification().inputs | wbRemoveLegacyInput; injector: notification().slot.injector\"/>\n </sci-viewport>\n }\n</div>\n\n<button (click)=\"onClose()\"\n [title]=\"('%workbench.close.tooltip' | wbText)()\"\n class=\"close e2e-close\">\n <wb-icon icon=\"workbench.close\"/>\n</button>\n", styles: [":host{display:flex;flex-direction:column;gap:.75em;background-color:var(--sci-color-background-elevation);color:var(--sci-color-text);font-size:.9em;border:1px solid var(--sci-color-border);border-radius:var(--sci-corner);box-shadow:var(--sci-elevation) var(--sci-static-color-black);padding:1em 0;overflow:hidden;outline:none;position:relative}:host:before{content:\"\";position:absolute;top:0;left:0;bottom:0;width:var(--sci-workbench-notification-severity-indicator-size)}:host[data-severity=info]:before{background-color:var(--sci-color-accent)}:host[data-severity=warn]:before{background-color:var(--sci-color-notice)}:host[data-severity=error]:before{background-color:var(--sci-color-negative)}:host>header{flex:none;font-weight:700;padding:0 1.5em;word-break:break-word;white-space:pre-line}:host>div.message{flex:auto;overflow:hidden}:host>div.message.text{word-break:break-word;white-space:pre-line;padding:0 1.5em}:host>div.message>sci-viewport{height:100%}:host>div.message>sci-viewport::part(content){padding:0 1.5em}:host>button.close:is(button,#sci-reset){all:unset;display:inline-grid;place-content:center;place-items:center;padding:.25em;border-radius:var(--sci-corner);-webkit-user-select:none;user-select:none;overflow:hidden;cursor:var(--sci-workbench-button-cursor)}:host>button.close:is(button,#sci-reset):hover:where(:not(:disabled)){background-color:var(--sci-workbench-button-background-color-hover)}:host>button.close:is(button,#sci-reset):active:where(:not(:disabled)){background-color:var(--sci-workbench-button-background-color-active)}:host>button.close:is(button,#sci-reset):focus:not(:focus-visible){outline:none}:host>button.close:is(button,#sci-reset):focus-visible{outline:var(--sci-workbench-button-outline-width-focus) solid var(--sci-color-accent)}:host>button.close:is(button,#sci-reset):disabled{color:var(--sci-color-gray-500)}:host>button.close:is(button,#sci-reset){position:absolute;top:.275em;right:.275em;padding:.125em;border-radius:var(--sci-corner-small);font-size:1rem}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "wb-icon", inputs: ["icon"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: SciViewportComponent, selector: "sci-viewport", inputs: ["scrollbarStyle"], outputs: ["scroll"] }, { kind: "pipe", type: TextPipe, name: "wbText" }, { kind: "pipe", type: RemoveLegacyInputPipe, name: "wbRemoveLegacyInput" }] });
20510
- }
20511
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: WorkbenchNotificationComponent, decorators: [{
20512
- type: Component,
20513
- args: [{ selector: 'wb-notification', imports: [
20514
- TextPipe,
20515
- IconComponent,
20516
- NgComponentOutlet,
20517
- RemoveLegacyInputPipe,
20518
- SciViewportComponent,
20519
- ], host: {
20520
- '[attr.data-notificationid]': 'notification().id',
20521
- '[attr.data-severity]': 'notification().severity()',
20522
- '[style.min-height]': 'notification().size.minHeight()',
20523
- '[style.height]': 'notification().size.height()',
20524
- '[style.max-height]': 'notification().size.maxHeight()',
20525
- '[attr.tabindex]': '-1',
20526
- '[class]': 'notification().cssClass()',
20527
- '(mouseenter)': 'hover.set(true)',
20528
- '(mouseleave)': 'hover.set(false)',
20529
- '(auxclick)': 'onAuxClick($event)',
20530
- '(keydown.escape)': 'onEscape($event)',
20531
- }, template: "<!-- Title -->\n@if (notification().title(); as title) {\n <header class=\"e2e-title\">{{(title | wbText)()}}</header>\n}\n\n<!-- Message -->\n<div class=\"message e2e-message\" [class.text]=\"!!notification().slot.text?.length\">\n @if (notification().slot.text?.length) {\n {{(notification().slot.text | wbText)()}}\n } @else if (notification().slot.component) {\n <sci-viewport class=\"e2e-message-viewport\">\n <ng-container *ngComponentOutlet=\"notification().slot.component!; inputs: notification().inputs | wbRemoveLegacyInput; injector: notification().slot.injector\"/>\n </sci-viewport>\n }\n</div>\n\n<button (click)=\"onClose()\"\n [title]=\"('%workbench.close.tooltip' | wbText)()\"\n class=\"close e2e-close\">\n <wb-icon icon=\"workbench.close\"/>\n</button>\n", styles: [":host{display:flex;flex-direction:column;gap:.75em;background-color:var(--sci-color-background-elevation);color:var(--sci-color-text);font-size:.9em;border:1px solid var(--sci-color-border);border-radius:var(--sci-corner);box-shadow:var(--sci-elevation) var(--sci-static-color-black);padding:1em 0;overflow:hidden;outline:none;position:relative}:host:before{content:\"\";position:absolute;top:0;left:0;bottom:0;width:var(--sci-workbench-notification-severity-indicator-size)}:host[data-severity=info]:before{background-color:var(--sci-color-accent)}:host[data-severity=warn]:before{background-color:var(--sci-color-notice)}:host[data-severity=error]:before{background-color:var(--sci-color-negative)}:host>header{flex:none;font-weight:700;padding:0 1.5em;word-break:break-word;white-space:pre-line}:host>div.message{flex:auto;overflow:hidden}:host>div.message.text{word-break:break-word;white-space:pre-line;padding:0 1.5em}:host>div.message>sci-viewport{height:100%}:host>div.message>sci-viewport::part(content){padding:0 1.5em}:host>button.close:is(button,#sci-reset){all:unset;display:inline-grid;place-content:center;place-items:center;padding:.25em;border-radius:var(--sci-corner);-webkit-user-select:none;user-select:none;overflow:hidden;cursor:var(--sci-workbench-button-cursor)}:host>button.close:is(button,#sci-reset):hover:where(:not(:disabled)){background-color:var(--sci-workbench-button-background-color-hover)}:host>button.close:is(button,#sci-reset):active:where(:not(:disabled)){background-color:var(--sci-workbench-button-background-color-active)}:host>button.close:is(button,#sci-reset):focus:not(:focus-visible){outline:none}:host>button.close:is(button,#sci-reset):focus-visible{outline:var(--sci-workbench-button-outline-width-focus) solid var(--sci-color-accent)}:host>button.close:is(button,#sci-reset):disabled{color:var(--sci-color-gray-500)}:host>button.close:is(button,#sci-reset){position:absolute;top:.275em;right:.275em;padding:.125em;border-radius:var(--sci-corner-small);font-size:1rem}\n"] }]
20532
- }], ctorParameters: () => [], propDecorators: { notification: [{ type: i0.Input, args: [{ isSignal: true, alias: "notification", required: true }] }] } });
20533
-
20534
- /*
20535
- * Copyright (c) 2018-2022 Swiss Federal Railways
20536
- *
20537
- * This program and the accompanying materials are made
20538
- * available under the terms of the Eclipse Public License 2.0
20539
- * which is available at https://www.eclipse.org/legal/epl-2.0/
20540
- *
20541
- * SPDX-License-Identifier: EPL-2.0
20542
- */
20543
20618
  /**
20544
20619
  * Displays notifications on the right side, stacked vertically.
20545
20620
  */
20546
20621
  class NotificationListComponent {
20547
20622
  notifications = inject(WorkbenchNotificationRegistry).elements;
20548
20623
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: NotificationListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
20549
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: NotificationListComponent, isStandalone: true, selector: "wb-notification-list", ngImport: i0, template: "@for (notification of notifications(); track notification.group || notification.id) {\n <wb-notification [notification]=\"notification\"/>\n}\n", styles: [":host{display:flex;flex-flow:column wrap-reverse;gap:.5em;max-height:100%;align-items:flex-start;align-content:flex-start;pointer-events:none;margin:.5em}:host>wb-notification{pointer-events:auto;width:var(--sci-workbench-notification-width);max-width:100%;position:relative;animation:slide-in .3s ease-out}@keyframes slide-in{0%{opacity:0;left:100%}to{opacity:1;left:0}}\n"], dependencies: [{ kind: "component", type: WorkbenchNotificationComponent, selector: "wb-notification", inputs: ["notification"] }] });
20624
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: NotificationListComponent, isStandalone: true, selector: "wb-notification-list", ngImport: i0, template: "@for (notification of notifications(); track notification.group || notification.id) {\n <div class=\"notification\">\n <ng-container *wbPortalOutlet=\"notification.portal; destroyOnDetach: true\"/>\n </div>\n}\n", styles: [":host{display:flex;flex-flow:column wrap-reverse;gap:.5em;max-height:100%;align-items:flex-start;align-content:flex-start;pointer-events:none;margin:.5em}:host>div.notification{pointer-events:auto;width:var(--sci-workbench-notification-width);max-width:100%;position:relative;animation:slide-in .3s ease-out}@keyframes slide-in{0%{opacity:0;left:100%}to{opacity:1;left:0}}\n"], dependencies: [{ kind: "directive", type: WorkbenchPortalOutletDirective, selector: "ng-template[wbPortalOutlet]", inputs: ["wbPortalOutlet", "wbPortalOutletDestroyOnDetach"] }] });
20550
20625
  }
20551
20626
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: NotificationListComponent, decorators: [{
20552
20627
  type: Component,
20553
20628
  args: [{ selector: 'wb-notification-list', imports: [
20554
- WorkbenchNotificationComponent,
20555
- ], template: "@for (notification of notifications(); track notification.group || notification.id) {\n <wb-notification [notification]=\"notification\"/>\n}\n", styles: [":host{display:flex;flex-flow:column wrap-reverse;gap:.5em;max-height:100%;align-items:flex-start;align-content:flex-start;pointer-events:none;margin:.5em}:host>wb-notification{pointer-events:auto;width:var(--sci-workbench-notification-width);max-width:100%;position:relative;animation:slide-in .3s ease-out}@keyframes slide-in{0%{opacity:0;left:100%}to{opacity:1;left:0}}\n"] }]
20629
+ WorkbenchPortalOutletDirective,
20630
+ ], template: "@for (notification of notifications(); track notification.group || notification.id) {\n <div class=\"notification\">\n <ng-container *wbPortalOutlet=\"notification.portal; destroyOnDetach: true\"/>\n </div>\n}\n", styles: [":host{display:flex;flex-flow:column wrap-reverse;gap:.5em;max-height:100%;align-items:flex-start;align-content:flex-start;pointer-events:none;margin:.5em}:host>div.notification{pointer-events:auto;width:var(--sci-workbench-notification-width);max-width:100%;position:relative;animation:slide-in .3s ease-out}@keyframes slide-in{0%{opacity:0;left:100%}to{opacity:1;left:0}}\n"] }]
20556
20631
  }] });
20557
20632
 
20558
20633
  /*
@@ -20963,7 +21038,7 @@ function configureWorkbenchGlassPane() {
20963
21038
  },
20964
21039
  {
20965
21040
  provide: GLASS_PANE_OPTIONS,
20966
- useValue: { cssClass: 'e2e-workbench' },
21041
+ useFactory: () => ({ cssClass: 'e2e-workbench' }),
20967
21042
  },
20968
21043
  ];
20969
21044
  }
@@ -21572,7 +21647,7 @@ function migrateGroupInputReduceFn(config) {
21572
21647
  */
21573
21648
 
21574
21649
  /*
21575
- * Copyright (c) 2018-2022 Swiss Federal Railways
21650
+ * Copyright (c) 2018-2026 Swiss Federal Railways
21576
21651
  *
21577
21652
  * This program and the accompanying materials are made
21578
21653
  * available under the terms of the Eclipse Public License 2.0