@mohamedatia/fly-design-system 2.15.3 → 2.16.0

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, signal, computed, Injectable, inject, ErrorHandler, PLATFORM_ID, DestroyRef, ChangeDetectionStrategy, Component, Pipe, ElementRef, input, output, afterNextRender, HostListener, ViewChild, ChangeDetectorRef, forwardRef, DOCUMENT, EventEmitter, Output, Input, Injector, viewChild, effect, ViewEncapsulation, model, Directive, Renderer2 } from '@angular/core';
2
+ import { InjectionToken, signal, computed, Injectable, inject, ErrorHandler, PLATFORM_ID, DestroyRef, ChangeDetectionStrategy, Component, Pipe, ElementRef, input, output, afterNextRender, HostListener, ViewChild, ChangeDetectorRef, forwardRef, DOCUMENT, EventEmitter, Output, Input, effect, Injector, viewChild, ViewEncapsulation, model, Directive, Renderer2 } from '@angular/core';
3
3
  import * as i1$1 from '@angular/common';
4
4
  import { isPlatformBrowser, NgComponentOutlet, CommonModule, DOCUMENT as DOCUMENT$1 } from '@angular/common';
5
5
  import { Router, NavigationEnd } from '@angular/router';
@@ -17,6 +17,8 @@ import { TiptapEditorDirective } from 'ngx-tiptap';
17
17
  import { Link } from '@tiptap/extension-link';
18
18
  import { registerCustomProtocol } from 'linkifyjs';
19
19
  import { switchMap, debounceTime, distinctUntilChanged, filter } from 'rxjs/operators';
20
+ import * as i1$2 from '@angular/cdk/a11y';
21
+ import { A11yModule } from '@angular/cdk/a11y';
20
22
  import Cropper from 'cropperjs';
21
23
 
22
24
  /**
@@ -2421,14 +2423,14 @@ class EntityLookupComponent {
2421
2423
  return resolved;
2422
2424
  }
2423
2425
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EntityLookupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2424
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: EntityLookupComponent, isStandalone: true, selector: "fly-entity-lookup", inputs: { descriptors: { classPropertyName: "descriptors", publicName: "descriptors", isSignal: true, isRequired: true, transformFunction: null }, initialEntity: { classPropertyName: "initialEntity", publicName: "initialEntity", isSignal: true, isRequired: false, transformFunction: null }, initialQuery: { classPropertyName: "initialQuery", publicName: "initialQuery", isSignal: true, isRequired: false, transformFunction: null }, listboxId: { classPropertyName: "listboxId", publicName: "listboxId", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pick: "pick", entityLinkSelected: "entityLinkSelected", dismiss: "dismiss" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)", "document:keydown.escape": "onDocumentEscape()" }, properties: { "class.fly-entity-lookup--down": "placement() === 'down'", "class.fly-entity-lookup--above": "placement() === 'above'" } }, viewQueries: [{ propertyName: "searchEl", first: true, predicate: ["searchRef"], descendants: true }], ngImport: i0, template: "<div class=\"fly-entity-lookup\" role=\"dialog\" [attr.aria-label]=\"'agent.lookup.dialog_aria' | translate\">\r\n @if (descriptors().length === 0) {\r\n <div class=\"fly-entity-lookup__empty\" role=\"status\">\r\n {{ 'agent.lookup.no_entities' | translate }}\r\n </div>\r\n } @else {\r\n <div class=\"fly-entity-lookup__search\" role=\"combobox\" aria-haspopup=\"listbox\" aria-expanded=\"true\"\r\n [attr.aria-controls]=\"listboxId()\">\r\n @if (stage() === 'search' && showBack()) {\r\n <!-- Breadcrumb back to the entity picker (also reachable via Backspace\r\n on an empty query). Shows the chosen entity so the user always\r\n knows what they're searching within. -->\r\n <button\r\n type=\"button\"\r\n class=\"fly-entity-lookup__crumb\"\r\n (click)=\"goBackToEntity()\"\r\n [attr.aria-label]=\"'agent.lookup.back_aria' | translate\">\r\n <i class=\"pi pi-angle-left fly-entity-lookup__crumb-back\" aria-hidden=\"true\"></i>\r\n @if (activeDescriptor()?.icon; as ic) {\r\n <i class=\"pi {{ ic }}\" aria-hidden=\"true\"></i>\r\n }\r\n <span>{{ activeEntityLabel() }}</span>\r\n </button>\r\n } @else {\r\n <i class=\"pi pi-search fly-entity-lookup__search-icon\" aria-hidden=\"true\"></i>\r\n }\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-entity-lookup__search-input\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onQueryInput($event)\"\r\n (keydown)=\"onKeydown($event)\"\r\n [attr.aria-activedescendant]=\"activeDescendant()\"\r\n [attr.aria-controls]=\"listboxId()\"\r\n [placeholder]=\"searchPlaceholderKey() | translate\" />\r\n </div>\r\n\r\n <div [id]=\"listboxId()\" class=\"fly-entity-lookup__results\" role=\"listbox\"\r\n [attr.aria-label]=\"(stage() === 'entity' ? 'agent.lookup.entities_aria' : 'agent.lookup.results_aria') | translate\">\r\n @if (stage() === 'entity') {\r\n <!-- Stage 1: entity autocomplete. -->\r\n @if (filteredEntities().length === 0) {\r\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.no_results' | translate }}</div>\r\n } @else {\r\n @for (desc of filteredEntities(); track desc.entity; let i = $index) {\r\n <button\r\n type=\"button\"\r\n role=\"option\"\r\n class=\"fly-entity-lookup__opt fly-entity-lookup__opt--entity\"\r\n [id]=\"optionId(i)\"\r\n [attr.aria-selected]=\"i === activeIndex()\"\r\n [class.is-active]=\"i === activeIndex()\"\r\n (click)=\"onSelectEntity(desc.entity)\"\r\n (mouseenter)=\"onRowHover(i)\">\r\n <span class=\"fly-entity-lookup__opt-label\">\r\n @if (desc.icon) {\r\n <i class=\"pi {{ desc.icon }}\" aria-hidden=\"true\"></i>\r\n }\r\n {{ entityLabel(desc) }}\r\n </span>\r\n @if (appLabel(desc); as app) {\r\n <span class=\"fly-entity-lookup__opt-app-badge\" [title]=\"app\">{{ app }}</span>\r\n }\r\n <i class=\"pi pi-angle-right fly-entity-lookup__opt-chevron\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n }\r\n } @else {\r\n <!-- Stage 2: result typeahead within the chosen entity. -->\r\n @if (loading()) {\r\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.searching' | translate }}</div>\r\n } @else if (errorKey(); as err) {\r\n <div class=\"fly-entity-lookup__status fly-entity-lookup__status--error\" role=\"alert\">{{ err | translate }}</div>\r\n } @else if (results().length === 0) {\r\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.no_results' | translate }}</div>\r\n } @else {\r\n @for (row of results(); track row.id; let i = $index) {\r\n <button\r\n type=\"button\"\r\n role=\"option\"\r\n class=\"fly-entity-lookup__opt\"\r\n [id]=\"optionId(i)\"\r\n [attr.aria-selected]=\"i === activeIndex()\"\r\n [class.is-active]=\"i === activeIndex()\"\r\n (click)=\"onRowClick(row)\"\r\n (mouseenter)=\"onRowHover(i)\">\r\n <span class=\"fly-entity-lookup__opt-label\" [title]=\"row.label\">{{ row.label }}</span>\r\n @if (row.secondary) {\r\n <span class=\"fly-entity-lookup__opt-secondary\">{{ row.secondary }}</span>\r\n }\r\n @if (rowAppLabel(row); as rowApp) {\r\n <!-- Source app of this individual row (e.g. \"Circles\" for a\r\n Help-Center article seeded by Circles). Rendered before the\r\n descriptor tag so the per-row signal sits closer to the\r\n title; suppressed when it would duplicate the descriptor\r\n label. -->\r\n <span class=\"fly-entity-lookup__opt-app-tag fly-entity-lookup__opt-app-tag--source\"\r\n [title]=\"rowApp\">{{ rowApp }}</span>\r\n }\r\n @if (activeAppLabel(); as app) {\r\n <span class=\"fly-entity-lookup__opt-app-tag\" [title]=\"app\">{{ app }}</span>\r\n }\r\n </button>\r\n }\r\n }\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;position:relative;z-index:6}:host(.fly-entity-lookup--down){position:static}:host(.fly-entity-lookup--down) .fly-entity-lookup{inset-block-end:auto;inset-block-start:100%;inset-inline:auto;inset-inline-end:0;margin-block-end:0;margin-block-start:6px;min-inline-size:320px;max-inline-size:min(380px,90vw);z-index:1000}:host(.fly-entity-lookup--above){position:static}:host(.fly-entity-lookup--above) .fly-entity-lookup{inset-block-start:auto;inset-block-end:100%;inset-inline:0;margin-block-start:0;margin-block-end:6px;z-index:1000}.fly-entity-lookup{position:absolute;inset-block-end:100%;inset-inline:12px;margin-block-end:6px;background:var(--surface-card, rgba(28, 28, 30, .96));backdrop-filter:blur(24px) saturate(180%);-webkit-backdrop-filter:blur(24px) saturate(180%);border:1px solid var(--surface-border, rgba(255, 255, 255, .1));border-radius:12px;box-shadow:0 10px 24px #0000002e}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.fly-entity-lookup{background:#1c1c1efa}}.fly-entity-lookup{padding-block:6px;display:flex;flex-direction:column;gap:6px}.fly-entity-lookup__empty{padding-block:10px;padding-inline:14px;color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:12px;line-height:1.3}.fly-entity-lookup__crumb{display:inline-flex;align-items:center;gap:5px;flex-shrink:0;max-inline-size:45%;padding-block:2px;padding-inline:7px;border-radius:6px;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));background:var(--surface-hover, rgba(255, 255, 255, .06));color:var(--text-color-secondary, rgba(255, 255, 255, .75));font-size:11px;font-family:inherit;line-height:1.2;cursor:pointer;transition:background .12s ease,color .12s ease}.fly-entity-lookup__crumb i.pi{font-size:12px}.fly-entity-lookup__crumb .fly-entity-lookup__crumb-back{opacity:.75}.fly-entity-lookup__crumb span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__crumb:hover,.fly-entity-lookup__crumb:focus-visible{background:var(--surface-active, rgba(255, 255, 255, .1));color:inherit;outline:none}.fly-entity-lookup__crumb:focus-visible{outline:2px solid var(--primary-color, #5b8cff);outline-offset:1px}[dir=rtl] .fly-entity-lookup__crumb-back{transform:scaleX(-1)}.fly-entity-lookup__search{display:flex;align-items:center;gap:8px;margin-inline:10px;padding-block:6px;padding-inline:10px;border-radius:8px;background:var(--surface-hover, rgba(255, 255, 255, .06));border:1px solid var(--surface-border, rgba(255, 255, 255, .1))}.fly-entity-lookup__search-icon{color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:13px}.fly-entity-lookup__search-input{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-size:13px;font-family:inherit}.fly-entity-lookup__search-input::placeholder{color:var(--text-color-secondary, rgba(255, 255, 255, .4))}.fly-entity-lookup__results{max-block-size:240px;overflow-y:auto;display:flex;flex-direction:column}.fly-entity-lookup__status{padding-block:10px;padding-inline:14px;color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:12px;line-height:1.3}.fly-entity-lookup__status--error{color:var(--red-400, #f87171)}.fly-entity-lookup__opt{display:flex;align-items:center;gap:8px;padding-block:6px;padding-inline:14px;background:transparent;border:none;text-align:start;color:inherit;font-size:13px;font-family:inherit;cursor:pointer;transition:background .12s ease}.fly-entity-lookup__opt.is-active,.fly-entity-lookup__opt:focus-visible{background:var(--surface-hover, rgba(255, 255, 255, .08));outline:none}.fly-entity-lookup__opt-label{flex:1 1 auto;min-inline-size:0;display:inline-flex;align-items:center;gap:7px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-label i.pi{font-size:13px;opacity:.85;flex-shrink:0}.fly-entity-lookup__opt-secondary{flex-shrink:0;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-color-secondary, rgba(255, 255, 255, .5));white-space:nowrap}.fly-entity-lookup__opt-app-badge{flex-shrink:0;padding-block:1px;padding-inline:7px;border-radius:999px;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));background:var(--surface-hover, rgba(255, 255, 255, .05));color:var(--text-color-secondary, rgba(255, 255, 255, .65));font-size:10.5px;line-height:1.5;letter-spacing:.02em;white-space:nowrap;max-inline-size:110px;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-app-tag{flex-shrink:0;font-size:10.5px;color:var(--text-color-secondary, rgba(255, 255, 255, .4));white-space:nowrap;max-inline-size:110px;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-app-tag--source{color:var(--text-color-secondary, rgba(255, 255, 255, .65));font-weight:500}.fly-entity-lookup__opt-chevron{flex-shrink:0;font-size:12px;opacity:.4}.fly-entity-lookup__opt--entity.is-active .fly-entity-lookup__opt-chevron,.fly-entity-lookup__opt--entity:hover .fly-entity-lookup__opt-chevron{opacity:.75}[dir=rtl] .fly-entity-lookup__opt-chevron{transform:scaleX(-1)}@media(prefers-reduced-motion:reduce){.fly-entity-lookup__crumb,.fly-entity-lookup__opt{transition:none}}@media(forced-colors:active){.fly-entity-lookup{border-color:CanvasText}.fly-entity-lookup__opt.is-active{outline:1px solid Highlight;outline-offset:-1px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2426
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: EntityLookupComponent, isStandalone: true, selector: "fly-entity-lookup", inputs: { descriptors: { classPropertyName: "descriptors", publicName: "descriptors", isSignal: true, isRequired: true, transformFunction: null }, initialEntity: { classPropertyName: "initialEntity", publicName: "initialEntity", isSignal: true, isRequired: false, transformFunction: null }, initialQuery: { classPropertyName: "initialQuery", publicName: "initialQuery", isSignal: true, isRequired: false, transformFunction: null }, listboxId: { classPropertyName: "listboxId", publicName: "listboxId", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pick: "pick", entityLinkSelected: "entityLinkSelected", dismiss: "dismiss" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)", "document:keydown.escape": "onDocumentEscape()" }, properties: { "class.fly-entity-lookup--down": "placement() === 'down'", "class.fly-entity-lookup--above": "placement() === 'above'" } }, viewQueries: [{ propertyName: "searchEl", first: true, predicate: ["searchRef"], descendants: true }], ngImport: i0, template: "<div class=\"fly-entity-lookup\" role=\"dialog\" [attr.aria-label]=\"'agent.lookup.dialog_aria' | translate\">\n @if (descriptors().length === 0) {\n <div class=\"fly-entity-lookup__empty\" role=\"status\">\n {{ 'agent.lookup.no_entities' | translate }}\n </div>\n } @else {\n <div class=\"fly-entity-lookup__search\" role=\"combobox\" aria-haspopup=\"listbox\" aria-expanded=\"true\"\n [attr.aria-controls]=\"listboxId()\">\n @if (stage() === 'search' && showBack()) {\n <!-- Breadcrumb back to the entity picker (also reachable via Backspace\n on an empty query). Shows the chosen entity so the user always\n knows what they're searching within. -->\n <button\n type=\"button\"\n class=\"fly-entity-lookup__crumb\"\n (click)=\"goBackToEntity()\"\n [attr.aria-label]=\"'agent.lookup.back_aria' | translate\">\n <i class=\"pi pi-angle-left fly-entity-lookup__crumb-back\" aria-hidden=\"true\"></i>\n @if (activeDescriptor()?.icon; as ic) {\n <i class=\"pi {{ ic }}\" aria-hidden=\"true\"></i>\n }\n <span>{{ activeEntityLabel() }}</span>\n </button>\n } @else {\n <i class=\"pi pi-search fly-entity-lookup__search-icon\" aria-hidden=\"true\"></i>\n }\n <input\n #searchRef\n type=\"text\"\n class=\"fly-entity-lookup__search-input\"\n [ngModel]=\"query()\"\n (ngModelChange)=\"onQueryInput($event)\"\n (keydown)=\"onKeydown($event)\"\n [attr.aria-activedescendant]=\"activeDescendant()\"\n [attr.aria-controls]=\"listboxId()\"\n [placeholder]=\"searchPlaceholderKey() | translate\" />\n </div>\n\n <div [id]=\"listboxId()\" class=\"fly-entity-lookup__results\" role=\"listbox\"\n [attr.aria-label]=\"(stage() === 'entity' ? 'agent.lookup.entities_aria' : 'agent.lookup.results_aria') | translate\">\n @if (stage() === 'entity') {\n <!-- Stage 1: entity autocomplete. -->\n @if (filteredEntities().length === 0) {\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.no_results' | translate }}</div>\n } @else {\n @for (desc of filteredEntities(); track desc.entity; let i = $index) {\n <button\n type=\"button\"\n role=\"option\"\n class=\"fly-entity-lookup__opt fly-entity-lookup__opt--entity\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"i === activeIndex()\"\n [class.is-active]=\"i === activeIndex()\"\n (click)=\"onSelectEntity(desc.entity)\"\n (mouseenter)=\"onRowHover(i)\">\n <span class=\"fly-entity-lookup__opt-label\">\n @if (desc.icon) {\n <i class=\"pi {{ desc.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ entityLabel(desc) }}\n </span>\n @if (appLabel(desc); as app) {\n <span class=\"fly-entity-lookup__opt-app-badge\" [title]=\"app\">{{ app }}</span>\n }\n <i class=\"pi pi-angle-right fly-entity-lookup__opt-chevron\" aria-hidden=\"true\"></i>\n </button>\n }\n }\n } @else {\n <!-- Stage 2: result typeahead within the chosen entity. -->\n @if (loading()) {\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.searching' | translate }}</div>\n } @else if (errorKey(); as err) {\n <div class=\"fly-entity-lookup__status fly-entity-lookup__status--error\" role=\"alert\">{{ err | translate }}</div>\n } @else if (results().length === 0) {\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.no_results' | translate }}</div>\n } @else {\n @for (row of results(); track row.id; let i = $index) {\n <button\n type=\"button\"\n role=\"option\"\n class=\"fly-entity-lookup__opt\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"i === activeIndex()\"\n [class.is-active]=\"i === activeIndex()\"\n (click)=\"onRowClick(row)\"\n (mouseenter)=\"onRowHover(i)\">\n <span class=\"fly-entity-lookup__opt-label\" [title]=\"row.label\">{{ row.label }}</span>\n @if (row.secondary) {\n <span class=\"fly-entity-lookup__opt-secondary\">{{ row.secondary }}</span>\n }\n @if (rowAppLabel(row); as rowApp) {\n <!-- Source app of this individual row (e.g. \"Circles\" for a\n Help-Center article seeded by Circles). Rendered before the\n descriptor tag so the per-row signal sits closer to the\n title; suppressed when it would duplicate the descriptor\n label. -->\n <span class=\"fly-entity-lookup__opt-app-tag fly-entity-lookup__opt-app-tag--source\"\n [title]=\"rowApp\">{{ rowApp }}</span>\n }\n @if (activeAppLabel(); as app) {\n <span class=\"fly-entity-lookup__opt-app-tag\" [title]=\"app\">{{ app }}</span>\n }\n </button>\n }\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;position:relative;z-index:6}:host(.fly-entity-lookup--down){position:static}:host(.fly-entity-lookup--down) .fly-entity-lookup{inset-block-end:auto;inset-block-start:100%;inset-inline:auto;inset-inline-end:0;margin-block-end:0;margin-block-start:6px;min-inline-size:320px;max-inline-size:min(380px,90vw);z-index:1000}:host(.fly-entity-lookup--above){position:static}:host(.fly-entity-lookup--above) .fly-entity-lookup{inset-block-start:auto;inset-block-end:100%;inset-inline:0;margin-block-start:0;margin-block-end:6px;z-index:1000}.fly-entity-lookup{position:absolute;inset-block-end:100%;inset-inline:12px;margin-block-end:6px;background:var(--surface-card, rgba(28, 28, 30, .96));backdrop-filter:blur(24px) saturate(180%);-webkit-backdrop-filter:blur(24px) saturate(180%);border:1px solid var(--surface-border, rgba(255, 255, 255, .1));border-radius:12px;box-shadow:0 10px 24px #0000002e}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.fly-entity-lookup{background:#1c1c1efa}}.fly-entity-lookup{padding-block:6px;display:flex;flex-direction:column;gap:6px}.fly-entity-lookup__empty{padding-block:10px;padding-inline:14px;color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:12px;line-height:1.3}.fly-entity-lookup__crumb{display:inline-flex;align-items:center;gap:5px;flex-shrink:0;max-inline-size:45%;padding-block:2px;padding-inline:7px;border-radius:6px;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));background:var(--surface-hover, rgba(255, 255, 255, .06));color:var(--text-color-secondary, rgba(255, 255, 255, .75));font-size:11px;font-family:inherit;line-height:1.2;cursor:pointer;transition:background .12s ease,color .12s ease}.fly-entity-lookup__crumb i.pi{font-size:12px}.fly-entity-lookup__crumb .fly-entity-lookup__crumb-back{opacity:.75}.fly-entity-lookup__crumb span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__crumb:hover,.fly-entity-lookup__crumb:focus-visible{background:var(--surface-active, rgba(255, 255, 255, .1));color:inherit;outline:none}.fly-entity-lookup__crumb:focus-visible{outline:2px solid var(--primary-color, #5b8cff);outline-offset:1px}[dir=rtl] .fly-entity-lookup__crumb-back{transform:scaleX(-1)}.fly-entity-lookup__search{display:flex;align-items:center;gap:8px;margin-inline:10px;padding-block:6px;padding-inline:10px;border-radius:8px;background:var(--surface-hover, rgba(255, 255, 255, .06));border:1px solid var(--surface-border, rgba(255, 255, 255, .1))}.fly-entity-lookup__search-icon{color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:13px}.fly-entity-lookup__search-input{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-size:13px;font-family:inherit}.fly-entity-lookup__search-input::placeholder{color:var(--text-color-secondary, rgba(255, 255, 255, .4))}.fly-entity-lookup__results{max-block-size:240px;overflow-y:auto;display:flex;flex-direction:column}.fly-entity-lookup__status{padding-block:10px;padding-inline:14px;color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:12px;line-height:1.3}.fly-entity-lookup__status--error{color:var(--red-400, #f87171)}.fly-entity-lookup__opt{display:flex;align-items:center;gap:8px;padding-block:6px;padding-inline:14px;background:transparent;border:none;text-align:start;color:inherit;font-size:13px;font-family:inherit;cursor:pointer;transition:background .12s ease}.fly-entity-lookup__opt.is-active,.fly-entity-lookup__opt:focus-visible{background:var(--surface-hover, rgba(255, 255, 255, .08));outline:none}.fly-entity-lookup__opt-label{flex:1 1 auto;min-inline-size:0;display:inline-flex;align-items:center;gap:7px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-label i.pi{font-size:13px;opacity:.85;flex-shrink:0}.fly-entity-lookup__opt-secondary{flex-shrink:0;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-color-secondary, rgba(255, 255, 255, .5));white-space:nowrap}.fly-entity-lookup__opt-app-badge{flex-shrink:0;padding-block:1px;padding-inline:7px;border-radius:999px;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));background:var(--surface-hover, rgba(255, 255, 255, .05));color:var(--text-color-secondary, rgba(255, 255, 255, .65));font-size:10.5px;line-height:1.5;letter-spacing:.02em;white-space:nowrap;max-inline-size:110px;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-app-tag{flex-shrink:0;font-size:10.5px;color:var(--text-color-secondary, rgba(255, 255, 255, .4));white-space:nowrap;max-inline-size:110px;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-app-tag--source{color:var(--text-color-secondary, rgba(255, 255, 255, .65));font-weight:500}.fly-entity-lookup__opt-chevron{flex-shrink:0;font-size:12px;opacity:.4}.fly-entity-lookup__opt--entity.is-active .fly-entity-lookup__opt-chevron,.fly-entity-lookup__opt--entity:hover .fly-entity-lookup__opt-chevron{opacity:.75}[dir=rtl] .fly-entity-lookup__opt-chevron{transform:scaleX(-1)}@media(prefers-reduced-motion:reduce){.fly-entity-lookup__crumb,.fly-entity-lookup__opt{transition:none}}@media(forced-colors:active){.fly-entity-lookup{border-color:CanvasText}.fly-entity-lookup__opt.is-active{outline:1px solid Highlight;outline-offset:-1px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2425
2427
  }
2426
2428
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EntityLookupComponent, decorators: [{
2427
2429
  type: Component,
2428
2430
  args: [{ selector: 'fly-entity-lookup', standalone: true, imports: [CommonModule, FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2429
2431
  '[class.fly-entity-lookup--down]': "placement() === 'down'",
2430
2432
  '[class.fly-entity-lookup--above]': "placement() === 'above'",
2431
- }, template: "<div class=\"fly-entity-lookup\" role=\"dialog\" [attr.aria-label]=\"'agent.lookup.dialog_aria' | translate\">\r\n @if (descriptors().length === 0) {\r\n <div class=\"fly-entity-lookup__empty\" role=\"status\">\r\n {{ 'agent.lookup.no_entities' | translate }}\r\n </div>\r\n } @else {\r\n <div class=\"fly-entity-lookup__search\" role=\"combobox\" aria-haspopup=\"listbox\" aria-expanded=\"true\"\r\n [attr.aria-controls]=\"listboxId()\">\r\n @if (stage() === 'search' && showBack()) {\r\n <!-- Breadcrumb back to the entity picker (also reachable via Backspace\r\n on an empty query). Shows the chosen entity so the user always\r\n knows what they're searching within. -->\r\n <button\r\n type=\"button\"\r\n class=\"fly-entity-lookup__crumb\"\r\n (click)=\"goBackToEntity()\"\r\n [attr.aria-label]=\"'agent.lookup.back_aria' | translate\">\r\n <i class=\"pi pi-angle-left fly-entity-lookup__crumb-back\" aria-hidden=\"true\"></i>\r\n @if (activeDescriptor()?.icon; as ic) {\r\n <i class=\"pi {{ ic }}\" aria-hidden=\"true\"></i>\r\n }\r\n <span>{{ activeEntityLabel() }}</span>\r\n </button>\r\n } @else {\r\n <i class=\"pi pi-search fly-entity-lookup__search-icon\" aria-hidden=\"true\"></i>\r\n }\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-entity-lookup__search-input\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onQueryInput($event)\"\r\n (keydown)=\"onKeydown($event)\"\r\n [attr.aria-activedescendant]=\"activeDescendant()\"\r\n [attr.aria-controls]=\"listboxId()\"\r\n [placeholder]=\"searchPlaceholderKey() | translate\" />\r\n </div>\r\n\r\n <div [id]=\"listboxId()\" class=\"fly-entity-lookup__results\" role=\"listbox\"\r\n [attr.aria-label]=\"(stage() === 'entity' ? 'agent.lookup.entities_aria' : 'agent.lookup.results_aria') | translate\">\r\n @if (stage() === 'entity') {\r\n <!-- Stage 1: entity autocomplete. -->\r\n @if (filteredEntities().length === 0) {\r\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.no_results' | translate }}</div>\r\n } @else {\r\n @for (desc of filteredEntities(); track desc.entity; let i = $index) {\r\n <button\r\n type=\"button\"\r\n role=\"option\"\r\n class=\"fly-entity-lookup__opt fly-entity-lookup__opt--entity\"\r\n [id]=\"optionId(i)\"\r\n [attr.aria-selected]=\"i === activeIndex()\"\r\n [class.is-active]=\"i === activeIndex()\"\r\n (click)=\"onSelectEntity(desc.entity)\"\r\n (mouseenter)=\"onRowHover(i)\">\r\n <span class=\"fly-entity-lookup__opt-label\">\r\n @if (desc.icon) {\r\n <i class=\"pi {{ desc.icon }}\" aria-hidden=\"true\"></i>\r\n }\r\n {{ entityLabel(desc) }}\r\n </span>\r\n @if (appLabel(desc); as app) {\r\n <span class=\"fly-entity-lookup__opt-app-badge\" [title]=\"app\">{{ app }}</span>\r\n }\r\n <i class=\"pi pi-angle-right fly-entity-lookup__opt-chevron\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n }\r\n } @else {\r\n <!-- Stage 2: result typeahead within the chosen entity. -->\r\n @if (loading()) {\r\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.searching' | translate }}</div>\r\n } @else if (errorKey(); as err) {\r\n <div class=\"fly-entity-lookup__status fly-entity-lookup__status--error\" role=\"alert\">{{ err | translate }}</div>\r\n } @else if (results().length === 0) {\r\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.no_results' | translate }}</div>\r\n } @else {\r\n @for (row of results(); track row.id; let i = $index) {\r\n <button\r\n type=\"button\"\r\n role=\"option\"\r\n class=\"fly-entity-lookup__opt\"\r\n [id]=\"optionId(i)\"\r\n [attr.aria-selected]=\"i === activeIndex()\"\r\n [class.is-active]=\"i === activeIndex()\"\r\n (click)=\"onRowClick(row)\"\r\n (mouseenter)=\"onRowHover(i)\">\r\n <span class=\"fly-entity-lookup__opt-label\" [title]=\"row.label\">{{ row.label }}</span>\r\n @if (row.secondary) {\r\n <span class=\"fly-entity-lookup__opt-secondary\">{{ row.secondary }}</span>\r\n }\r\n @if (rowAppLabel(row); as rowApp) {\r\n <!-- Source app of this individual row (e.g. \"Circles\" for a\r\n Help-Center article seeded by Circles). Rendered before the\r\n descriptor tag so the per-row signal sits closer to the\r\n title; suppressed when it would duplicate the descriptor\r\n label. -->\r\n <span class=\"fly-entity-lookup__opt-app-tag fly-entity-lookup__opt-app-tag--source\"\r\n [title]=\"rowApp\">{{ rowApp }}</span>\r\n }\r\n @if (activeAppLabel(); as app) {\r\n <span class=\"fly-entity-lookup__opt-app-tag\" [title]=\"app\">{{ app }}</span>\r\n }\r\n </button>\r\n }\r\n }\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;position:relative;z-index:6}:host(.fly-entity-lookup--down){position:static}:host(.fly-entity-lookup--down) .fly-entity-lookup{inset-block-end:auto;inset-block-start:100%;inset-inline:auto;inset-inline-end:0;margin-block-end:0;margin-block-start:6px;min-inline-size:320px;max-inline-size:min(380px,90vw);z-index:1000}:host(.fly-entity-lookup--above){position:static}:host(.fly-entity-lookup--above) .fly-entity-lookup{inset-block-start:auto;inset-block-end:100%;inset-inline:0;margin-block-start:0;margin-block-end:6px;z-index:1000}.fly-entity-lookup{position:absolute;inset-block-end:100%;inset-inline:12px;margin-block-end:6px;background:var(--surface-card, rgba(28, 28, 30, .96));backdrop-filter:blur(24px) saturate(180%);-webkit-backdrop-filter:blur(24px) saturate(180%);border:1px solid var(--surface-border, rgba(255, 255, 255, .1));border-radius:12px;box-shadow:0 10px 24px #0000002e}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.fly-entity-lookup{background:#1c1c1efa}}.fly-entity-lookup{padding-block:6px;display:flex;flex-direction:column;gap:6px}.fly-entity-lookup__empty{padding-block:10px;padding-inline:14px;color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:12px;line-height:1.3}.fly-entity-lookup__crumb{display:inline-flex;align-items:center;gap:5px;flex-shrink:0;max-inline-size:45%;padding-block:2px;padding-inline:7px;border-radius:6px;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));background:var(--surface-hover, rgba(255, 255, 255, .06));color:var(--text-color-secondary, rgba(255, 255, 255, .75));font-size:11px;font-family:inherit;line-height:1.2;cursor:pointer;transition:background .12s ease,color .12s ease}.fly-entity-lookup__crumb i.pi{font-size:12px}.fly-entity-lookup__crumb .fly-entity-lookup__crumb-back{opacity:.75}.fly-entity-lookup__crumb span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__crumb:hover,.fly-entity-lookup__crumb:focus-visible{background:var(--surface-active, rgba(255, 255, 255, .1));color:inherit;outline:none}.fly-entity-lookup__crumb:focus-visible{outline:2px solid var(--primary-color, #5b8cff);outline-offset:1px}[dir=rtl] .fly-entity-lookup__crumb-back{transform:scaleX(-1)}.fly-entity-lookup__search{display:flex;align-items:center;gap:8px;margin-inline:10px;padding-block:6px;padding-inline:10px;border-radius:8px;background:var(--surface-hover, rgba(255, 255, 255, .06));border:1px solid var(--surface-border, rgba(255, 255, 255, .1))}.fly-entity-lookup__search-icon{color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:13px}.fly-entity-lookup__search-input{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-size:13px;font-family:inherit}.fly-entity-lookup__search-input::placeholder{color:var(--text-color-secondary, rgba(255, 255, 255, .4))}.fly-entity-lookup__results{max-block-size:240px;overflow-y:auto;display:flex;flex-direction:column}.fly-entity-lookup__status{padding-block:10px;padding-inline:14px;color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:12px;line-height:1.3}.fly-entity-lookup__status--error{color:var(--red-400, #f87171)}.fly-entity-lookup__opt{display:flex;align-items:center;gap:8px;padding-block:6px;padding-inline:14px;background:transparent;border:none;text-align:start;color:inherit;font-size:13px;font-family:inherit;cursor:pointer;transition:background .12s ease}.fly-entity-lookup__opt.is-active,.fly-entity-lookup__opt:focus-visible{background:var(--surface-hover, rgba(255, 255, 255, .08));outline:none}.fly-entity-lookup__opt-label{flex:1 1 auto;min-inline-size:0;display:inline-flex;align-items:center;gap:7px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-label i.pi{font-size:13px;opacity:.85;flex-shrink:0}.fly-entity-lookup__opt-secondary{flex-shrink:0;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-color-secondary, rgba(255, 255, 255, .5));white-space:nowrap}.fly-entity-lookup__opt-app-badge{flex-shrink:0;padding-block:1px;padding-inline:7px;border-radius:999px;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));background:var(--surface-hover, rgba(255, 255, 255, .05));color:var(--text-color-secondary, rgba(255, 255, 255, .65));font-size:10.5px;line-height:1.5;letter-spacing:.02em;white-space:nowrap;max-inline-size:110px;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-app-tag{flex-shrink:0;font-size:10.5px;color:var(--text-color-secondary, rgba(255, 255, 255, .4));white-space:nowrap;max-inline-size:110px;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-app-tag--source{color:var(--text-color-secondary, rgba(255, 255, 255, .65));font-weight:500}.fly-entity-lookup__opt-chevron{flex-shrink:0;font-size:12px;opacity:.4}.fly-entity-lookup__opt--entity.is-active .fly-entity-lookup__opt-chevron,.fly-entity-lookup__opt--entity:hover .fly-entity-lookup__opt-chevron{opacity:.75}[dir=rtl] .fly-entity-lookup__opt-chevron{transform:scaleX(-1)}@media(prefers-reduced-motion:reduce){.fly-entity-lookup__crumb,.fly-entity-lookup__opt{transition:none}}@media(forced-colors:active){.fly-entity-lookup{border-color:CanvasText}.fly-entity-lookup__opt.is-active{outline:1px solid Highlight;outline-offset:-1px}}\n"] }]
2433
+ }, template: "<div class=\"fly-entity-lookup\" role=\"dialog\" [attr.aria-label]=\"'agent.lookup.dialog_aria' | translate\">\n @if (descriptors().length === 0) {\n <div class=\"fly-entity-lookup__empty\" role=\"status\">\n {{ 'agent.lookup.no_entities' | translate }}\n </div>\n } @else {\n <div class=\"fly-entity-lookup__search\" role=\"combobox\" aria-haspopup=\"listbox\" aria-expanded=\"true\"\n [attr.aria-controls]=\"listboxId()\">\n @if (stage() === 'search' && showBack()) {\n <!-- Breadcrumb back to the entity picker (also reachable via Backspace\n on an empty query). Shows the chosen entity so the user always\n knows what they're searching within. -->\n <button\n type=\"button\"\n class=\"fly-entity-lookup__crumb\"\n (click)=\"goBackToEntity()\"\n [attr.aria-label]=\"'agent.lookup.back_aria' | translate\">\n <i class=\"pi pi-angle-left fly-entity-lookup__crumb-back\" aria-hidden=\"true\"></i>\n @if (activeDescriptor()?.icon; as ic) {\n <i class=\"pi {{ ic }}\" aria-hidden=\"true\"></i>\n }\n <span>{{ activeEntityLabel() }}</span>\n </button>\n } @else {\n <i class=\"pi pi-search fly-entity-lookup__search-icon\" aria-hidden=\"true\"></i>\n }\n <input\n #searchRef\n type=\"text\"\n class=\"fly-entity-lookup__search-input\"\n [ngModel]=\"query()\"\n (ngModelChange)=\"onQueryInput($event)\"\n (keydown)=\"onKeydown($event)\"\n [attr.aria-activedescendant]=\"activeDescendant()\"\n [attr.aria-controls]=\"listboxId()\"\n [placeholder]=\"searchPlaceholderKey() | translate\" />\n </div>\n\n <div [id]=\"listboxId()\" class=\"fly-entity-lookup__results\" role=\"listbox\"\n [attr.aria-label]=\"(stage() === 'entity' ? 'agent.lookup.entities_aria' : 'agent.lookup.results_aria') | translate\">\n @if (stage() === 'entity') {\n <!-- Stage 1: entity autocomplete. -->\n @if (filteredEntities().length === 0) {\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.no_results' | translate }}</div>\n } @else {\n @for (desc of filteredEntities(); track desc.entity; let i = $index) {\n <button\n type=\"button\"\n role=\"option\"\n class=\"fly-entity-lookup__opt fly-entity-lookup__opt--entity\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"i === activeIndex()\"\n [class.is-active]=\"i === activeIndex()\"\n (click)=\"onSelectEntity(desc.entity)\"\n (mouseenter)=\"onRowHover(i)\">\n <span class=\"fly-entity-lookup__opt-label\">\n @if (desc.icon) {\n <i class=\"pi {{ desc.icon }}\" aria-hidden=\"true\"></i>\n }\n {{ entityLabel(desc) }}\n </span>\n @if (appLabel(desc); as app) {\n <span class=\"fly-entity-lookup__opt-app-badge\" [title]=\"app\">{{ app }}</span>\n }\n <i class=\"pi pi-angle-right fly-entity-lookup__opt-chevron\" aria-hidden=\"true\"></i>\n </button>\n }\n }\n } @else {\n <!-- Stage 2: result typeahead within the chosen entity. -->\n @if (loading()) {\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.searching' | translate }}</div>\n } @else if (errorKey(); as err) {\n <div class=\"fly-entity-lookup__status fly-entity-lookup__status--error\" role=\"alert\">{{ err | translate }}</div>\n } @else if (results().length === 0) {\n <div class=\"fly-entity-lookup__status\" role=\"status\">{{ 'agent.lookup.no_results' | translate }}</div>\n } @else {\n @for (row of results(); track row.id; let i = $index) {\n <button\n type=\"button\"\n role=\"option\"\n class=\"fly-entity-lookup__opt\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"i === activeIndex()\"\n [class.is-active]=\"i === activeIndex()\"\n (click)=\"onRowClick(row)\"\n (mouseenter)=\"onRowHover(i)\">\n <span class=\"fly-entity-lookup__opt-label\" [title]=\"row.label\">{{ row.label }}</span>\n @if (row.secondary) {\n <span class=\"fly-entity-lookup__opt-secondary\">{{ row.secondary }}</span>\n }\n @if (rowAppLabel(row); as rowApp) {\n <!-- Source app of this individual row (e.g. \"Circles\" for a\n Help-Center article seeded by Circles). Rendered before the\n descriptor tag so the per-row signal sits closer to the\n title; suppressed when it would duplicate the descriptor\n label. -->\n <span class=\"fly-entity-lookup__opt-app-tag fly-entity-lookup__opt-app-tag--source\"\n [title]=\"rowApp\">{{ rowApp }}</span>\n }\n @if (activeAppLabel(); as app) {\n <span class=\"fly-entity-lookup__opt-app-tag\" [title]=\"app\">{{ app }}</span>\n }\n </button>\n }\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;position:relative;z-index:6}:host(.fly-entity-lookup--down){position:static}:host(.fly-entity-lookup--down) .fly-entity-lookup{inset-block-end:auto;inset-block-start:100%;inset-inline:auto;inset-inline-end:0;margin-block-end:0;margin-block-start:6px;min-inline-size:320px;max-inline-size:min(380px,90vw);z-index:1000}:host(.fly-entity-lookup--above){position:static}:host(.fly-entity-lookup--above) .fly-entity-lookup{inset-block-start:auto;inset-block-end:100%;inset-inline:0;margin-block-start:0;margin-block-end:6px;z-index:1000}.fly-entity-lookup{position:absolute;inset-block-end:100%;inset-inline:12px;margin-block-end:6px;background:var(--surface-card, rgba(28, 28, 30, .96));backdrop-filter:blur(24px) saturate(180%);-webkit-backdrop-filter:blur(24px) saturate(180%);border:1px solid var(--surface-border, rgba(255, 255, 255, .1));border-radius:12px;box-shadow:0 10px 24px #0000002e}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.fly-entity-lookup{background:#1c1c1efa}}.fly-entity-lookup{padding-block:6px;display:flex;flex-direction:column;gap:6px}.fly-entity-lookup__empty{padding-block:10px;padding-inline:14px;color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:12px;line-height:1.3}.fly-entity-lookup__crumb{display:inline-flex;align-items:center;gap:5px;flex-shrink:0;max-inline-size:45%;padding-block:2px;padding-inline:7px;border-radius:6px;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));background:var(--surface-hover, rgba(255, 255, 255, .06));color:var(--text-color-secondary, rgba(255, 255, 255, .75));font-size:11px;font-family:inherit;line-height:1.2;cursor:pointer;transition:background .12s ease,color .12s ease}.fly-entity-lookup__crumb i.pi{font-size:12px}.fly-entity-lookup__crumb .fly-entity-lookup__crumb-back{opacity:.75}.fly-entity-lookup__crumb span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__crumb:hover,.fly-entity-lookup__crumb:focus-visible{background:var(--surface-active, rgba(255, 255, 255, .1));color:inherit;outline:none}.fly-entity-lookup__crumb:focus-visible{outline:2px solid var(--primary-color, #5b8cff);outline-offset:1px}[dir=rtl] .fly-entity-lookup__crumb-back{transform:scaleX(-1)}.fly-entity-lookup__search{display:flex;align-items:center;gap:8px;margin-inline:10px;padding-block:6px;padding-inline:10px;border-radius:8px;background:var(--surface-hover, rgba(255, 255, 255, .06));border:1px solid var(--surface-border, rgba(255, 255, 255, .1))}.fly-entity-lookup__search-icon{color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:13px}.fly-entity-lookup__search-input{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-size:13px;font-family:inherit}.fly-entity-lookup__search-input::placeholder{color:var(--text-color-secondary, rgba(255, 255, 255, .4))}.fly-entity-lookup__results{max-block-size:240px;overflow-y:auto;display:flex;flex-direction:column}.fly-entity-lookup__status{padding-block:10px;padding-inline:14px;color:var(--text-color-secondary, rgba(255, 255, 255, .5));font-size:12px;line-height:1.3}.fly-entity-lookup__status--error{color:var(--red-400, #f87171)}.fly-entity-lookup__opt{display:flex;align-items:center;gap:8px;padding-block:6px;padding-inline:14px;background:transparent;border:none;text-align:start;color:inherit;font-size:13px;font-family:inherit;cursor:pointer;transition:background .12s ease}.fly-entity-lookup__opt.is-active,.fly-entity-lookup__opt:focus-visible{background:var(--surface-hover, rgba(255, 255, 255, .08));outline:none}.fly-entity-lookup__opt-label{flex:1 1 auto;min-inline-size:0;display:inline-flex;align-items:center;gap:7px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-label i.pi{font-size:13px;opacity:.85;flex-shrink:0}.fly-entity-lookup__opt-secondary{flex-shrink:0;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-color-secondary, rgba(255, 255, 255, .5));white-space:nowrap}.fly-entity-lookup__opt-app-badge{flex-shrink:0;padding-block:1px;padding-inline:7px;border-radius:999px;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));background:var(--surface-hover, rgba(255, 255, 255, .05));color:var(--text-color-secondary, rgba(255, 255, 255, .65));font-size:10.5px;line-height:1.5;letter-spacing:.02em;white-space:nowrap;max-inline-size:110px;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-app-tag{flex-shrink:0;font-size:10.5px;color:var(--text-color-secondary, rgba(255, 255, 255, .4));white-space:nowrap;max-inline-size:110px;overflow:hidden;text-overflow:ellipsis}.fly-entity-lookup__opt-app-tag--source{color:var(--text-color-secondary, rgba(255, 255, 255, .65));font-weight:500}.fly-entity-lookup__opt-chevron{flex-shrink:0;font-size:12px;opacity:.4}.fly-entity-lookup__opt--entity.is-active .fly-entity-lookup__opt-chevron,.fly-entity-lookup__opt--entity:hover .fly-entity-lookup__opt-chevron{opacity:.75}[dir=rtl] .fly-entity-lookup__opt-chevron{transform:scaleX(-1)}@media(prefers-reduced-motion:reduce){.fly-entity-lookup__crumb,.fly-entity-lookup__opt{transition:none}}@media(forced-colors:active){.fly-entity-lookup{border-color:CanvasText}.fly-entity-lookup__opt.is-active{outline:1px solid Highlight;outline-offset:-1px}}\n"] }]
2432
2434
  }], ctorParameters: () => [], propDecorators: { descriptors: [{ type: i0.Input, args: [{ isSignal: true, alias: "descriptors", required: true }] }], initialEntity: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialEntity", required: false }] }], initialQuery: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialQuery", required: false }] }], listboxId: [{ type: i0.Input, args: [{ isSignal: true, alias: "listboxId", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], pick: [{ type: i0.Output, args: ["pick"] }], entityLinkSelected: [{ type: i0.Output, args: ["entityLinkSelected"] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }], searchEl: [{
2433
2435
  type: ViewChild,
2434
2436
  args: ['searchRef']
@@ -2789,13 +2791,13 @@ class FlyMarkdownEditorComponent {
2789
2791
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FlyMarkdownEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2790
2792
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: FlyMarkdownEditorComponent, isStandalone: true, selector: "fly-markdown-editor", inputs: { toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, enableEntityLink: { classPropertyName: "enableEntityLink", publicName: "enableEntityLink", isSignal: true, isRequired: false, transformFunction: null }, entityLinkPlacement: { classPropertyName: "entityLinkPlacement", publicName: "entityLinkPlacement", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitShortcut: "submitShortcut" }, providers: [
2791
2793
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => FlyMarkdownEditorComponent), multi: true },
2792
- ], ngImport: i0, template: "<div class=\"fly-md-editor\" [class.fly-md-editor--entity-above]=\"entityLinkPlacement() === 'above'\">\r\n <div class=\"fly-md-editor__toolbar\" role=\"toolbar\" [attr.aria-label]=\"('common.label.formatting_toolbar' | translate)\">\r\n @for (item of toolbarItems(); track $index) {\r\n @switch (item) {\r\n @case ('|') {\r\n <span class=\"fly-md-editor__divider\" aria-hidden=\"true\"></span>\r\n }\r\n @case ('link') {\r\n <div class=\"fly-md-editor__link-wrap\">\r\n <button type=\"button\" class=\"fly-md-editor__btn\" [class.is-active]=\"isActive('link')\"\r\n (click)=\"openLinkPopover()\"\r\n [title]=\"'common.label.link' | translate\" [attr.aria-label]=\"'common.label.link' | translate\">\r\n <i class=\"pi pi-link\" aria-hidden=\"true\"></i>\r\n </button>\r\n @if (showLinkPopover()) {\r\n <div class=\"fly-md-editor__link-popover\" role=\"dialog\" [attr.aria-label]=\"'common.label.link' | translate\">\r\n <input class=\"fly-md-editor__link-input\" type=\"url\"\r\n [value]=\"linkInputValue()\" (input)=\"onLinkInput($any($event.target).value)\"\r\n (keydown)=\"onLinkKeydown($event)\"\r\n [placeholder]=\"'common.label.https' | translate\"\r\n [attr.aria-label]=\"'common.label.link' | translate\" />\r\n <button type=\"button\" class=\"fly-md-editor__link-ok\" (click)=\"commitLink()\"\r\n [title]=\"'common.label.apply' | translate\"><i class=\"pi pi-check\" aria-hidden=\"true\"></i></button>\r\n <button type=\"button\" class=\"fly-md-editor__link-cancel\" (click)=\"cancelLink()\"\r\n [title]=\"'common.action.cancel' | translate\"><i class=\"pi pi-times\" aria-hidden=\"true\"></i></button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n @case ('entityLink') {\r\n <div class=\"fly-md-editor__entity-wrap\">\r\n <button type=\"button\" class=\"fly-md-editor__btn\" [class.is-active]=\"showEntityLookup()\"\r\n (click)=\"toggleEntityLookup()\" [attr.aria-expanded]=\"showEntityLookup()\"\r\n [title]=\"'common.label.insert_entity_link' | translate\" [attr.aria-label]=\"'common.label.insert_entity_link' | translate\">\r\n <i class=\"pi pi-bookmark\" aria-hidden=\"true\"></i>\r\n </button>\r\n @if (showEntityLookup()) {\r\n <fly-entity-lookup\r\n [placement]=\"entityLinkPlacement()\"\r\n [descriptors]=\"entityLookupDescriptors()\"\r\n (entityLinkSelected)=\"onEntityLinkSelected($event)\"\r\n (dismiss)=\"closeEntityLookup()\" />\r\n }\r\n </div>\r\n }\r\n @default {\r\n <button type=\"button\" class=\"fly-md-editor__btn\"\r\n [class.is-active]=\"isActive(item)\" [disabled]=\"disabled(item)\"\r\n (click)=\"run(item)\"\r\n [title]=\"(button(item)?.labelKey ?? '') | translate\"\r\n [attr.aria-label]=\"(button(item)?.labelKey ?? '') | translate\">\r\n @if (textLabel(item); as txt) {\r\n <span class=\"fly-md-editor__btn-text\">{{ txt }}</span>\r\n } @else {\r\n <i class=\"pi {{ button(item)?.icon }}\" aria-hidden=\"true\"></i>\r\n }\r\n </button>\r\n }\r\n }\r\n }\r\n </div>\r\n\r\n <div class=\"fly-md-editor__body\" tiptap [editor]=\"editor\"\r\n [attr.aria-label]=\"ariaLabel()\" [attr.data-placeholder]=\"placeholder()\"></div>\r\n</div>\r\n", styles: [":host{display:block}.fly-md-editor{display:flex;flex-direction:column;min-block-size:0;position:relative}.fly-md-editor--entity-above .fly-md-editor__entity-wrap{position:static}.fly-md-editor__toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:2px;padding-block:4px}.fly-md-editor__divider{inline-size:1px;block-size:18px;margin-inline:4px;background:var(--surface-border, rgba(255, 255, 255, .12))}.fly-md-editor__btn{min-inline-size:28px;block-size:28px;padding-inline:7px;border-radius:6px;border:1px solid transparent;background:transparent;color:var(--text-color-secondary, #6e6e73);font-size:12px;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.fly-md-editor__btn:hover:not(:disabled){background:var(--surface-hover, rgba(0, 0, 0, .05))}.fly-md-editor__btn.is-active{background:var(--primary-color-subtle, rgba(0, 113, 227, .12));color:var(--primary-color, #0071e3);border-color:var(--primary-color-border, rgba(0, 113, 227, .25))}.fly-md-editor__btn:disabled{opacity:.4;cursor:default}.fly-md-editor__btn i.pi{font-size:13px}.fly-md-editor__btn-text{font-weight:600;font-style:normal}@media(prefers-reduced-motion:reduce){.fly-md-editor__btn{transition:none}}.fly-md-editor__link-wrap,.fly-md-editor__entity-wrap{position:relative;display:inline-flex}.fly-md-editor__link-popover{position:absolute;inset-block-start:calc(100% + 4px);inset-inline-start:0;z-index:1000;display:flex;gap:4px;padding:4px;background:var(--surface-elevated, #fff);border:1px solid var(--surface-border, rgba(0, 0, 0, .12));border-radius:6px;box-shadow:0 4px 12px #0000001f}.fly-md-editor__link-input{inline-size:200px;padding:4px 6px;font-size:12px;border:1px solid var(--surface-border, rgba(0, 0, 0, .12));border-radius:4px;outline:none;background:transparent;color:inherit}.fly-md-editor__link-input:focus{border-color:var(--primary-color, #0071e3)}.fly-md-editor__link-ok,.fly-md-editor__link-cancel{inline-size:24px;block-size:24px;border-radius:4px;border:none;background:transparent;cursor:pointer;color:var(--text-color-secondary, #6e6e73)}.fly-md-editor__link-ok:hover,.fly-md-editor__link-cancel:hover{background:var(--surface-hover, rgba(0, 0, 0, .06))}.fly-md-editor__body{flex:1;min-block-size:56px;overflow-y:auto;padding:8px 4px;font-size:13px;line-height:1.55;color:var(--text-color, inherit);cursor:text}.fly-md-editor__body:focus-within{outline:none}::ng-deep .fly-md-editor__prosemirror{outline:none}::ng-deep .fly-md-editor__prosemirror>*{margin-block:0 .5em}::ng-deep .fly-md-editor__prosemirror>:last-child{margin-block-end:0}::ng-deep .fly-md-editor__prosemirror h1{font-size:1.4em;font-weight:700}::ng-deep .fly-md-editor__prosemirror h2{font-size:1.2em;font-weight:700}::ng-deep .fly-md-editor__prosemirror h3{font-size:1.05em;font-weight:700}::ng-deep .fly-md-editor__prosemirror ul,::ng-deep .fly-md-editor__prosemirror ol{padding-inline-start:1.4em}::ng-deep .fly-md-editor__prosemirror a{color:var(--primary-color, #0071e3);text-decoration:underline;cursor:pointer}::ng-deep .fly-md-editor__prosemirror code{background:var(--surface-hover, rgba(0, 0, 0, .06));padding:1px 4px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.95em}::ng-deep .fly-md-editor__prosemirror pre{background:var(--surface-hover, rgba(0, 0, 0, .06));border-radius:6px;padding:8px 10px;overflow-x:auto}::ng-deep .fly-md-editor__prosemirror pre code{background:transparent;padding:0}::ng-deep .fly-md-editor__prosemirror blockquote{margin-inline:0;padding-inline-start:10px;border-inline-start:3px solid var(--surface-border, rgba(0, 0, 0, .15));color:var(--text-color-secondary, #6e6e73)}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList]{list-style:none;padding-inline-start:.2em}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList] li{display:flex;align-items:flex-start;gap:6px}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList] li>label{margin-block-start:.15em}::ng-deep .fly-md-editor__prosemirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:var(--text-color-secondary, rgba(0, 0, 0, .4));float:inline-start;pointer-events:none;block-size:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: TiptapEditorDirective, selector: "tiptap[editor], [tiptap][editor], tiptap-editor[editor], [tiptapEditor][editor]", inputs: ["editor", "outputFormat"] }, { kind: "component", type: EntityLookupComponent, selector: "fly-entity-lookup", inputs: ["descriptors", "initialEntity", "initialQuery", "listboxId", "placement"], outputs: ["pick", "entityLinkSelected", "dismiss"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2794
+ ], ngImport: i0, template: "<div class=\"fly-md-editor\" [class.fly-md-editor--entity-above]=\"entityLinkPlacement() === 'above'\">\n <div class=\"fly-md-editor__toolbar\" role=\"toolbar\" [attr.aria-label]=\"('common.label.formatting_toolbar' | translate)\">\n @for (item of toolbarItems(); track $index) {\n @switch (item) {\n @case ('|') {\n <span class=\"fly-md-editor__divider\" aria-hidden=\"true\"></span>\n }\n @case ('link') {\n <div class=\"fly-md-editor__link-wrap\">\n <button type=\"button\" class=\"fly-md-editor__btn\" [class.is-active]=\"isActive('link')\"\n (click)=\"openLinkPopover()\"\n [title]=\"'common.label.link' | translate\" [attr.aria-label]=\"'common.label.link' | translate\">\n <i class=\"pi pi-link\" aria-hidden=\"true\"></i>\n </button>\n @if (showLinkPopover()) {\n <div class=\"fly-md-editor__link-popover\" role=\"dialog\" [attr.aria-label]=\"'common.label.link' | translate\">\n <input class=\"fly-md-editor__link-input\" type=\"url\"\n [value]=\"linkInputValue()\" (input)=\"onLinkInput($any($event.target).value)\"\n (keydown)=\"onLinkKeydown($event)\"\n [placeholder]=\"'common.label.https' | translate\"\n [attr.aria-label]=\"'common.label.link' | translate\" />\n <button type=\"button\" class=\"fly-md-editor__link-ok\" (click)=\"commitLink()\"\n [title]=\"'common.label.apply' | translate\"><i class=\"pi pi-check\" aria-hidden=\"true\"></i></button>\n <button type=\"button\" class=\"fly-md-editor__link-cancel\" (click)=\"cancelLink()\"\n [title]=\"'common.action.cancel' | translate\"><i class=\"pi pi-times\" aria-hidden=\"true\"></i></button>\n </div>\n }\n </div>\n }\n @case ('entityLink') {\n <div class=\"fly-md-editor__entity-wrap\">\n <button type=\"button\" class=\"fly-md-editor__btn\" [class.is-active]=\"showEntityLookup()\"\n (click)=\"toggleEntityLookup()\" [attr.aria-expanded]=\"showEntityLookup()\"\n [title]=\"'common.label.insert_entity_link' | translate\" [attr.aria-label]=\"'common.label.insert_entity_link' | translate\">\n <i class=\"pi pi-bookmark\" aria-hidden=\"true\"></i>\n </button>\n @if (showEntityLookup()) {\n <fly-entity-lookup\n [placement]=\"entityLinkPlacement()\"\n [descriptors]=\"entityLookupDescriptors()\"\n (entityLinkSelected)=\"onEntityLinkSelected($event)\"\n (dismiss)=\"closeEntityLookup()\" />\n }\n </div>\n }\n @default {\n <button type=\"button\" class=\"fly-md-editor__btn\"\n [class.is-active]=\"isActive(item)\" [disabled]=\"disabled(item)\"\n (click)=\"run(item)\"\n [title]=\"(button(item)?.labelKey ?? '') | translate\"\n [attr.aria-label]=\"(button(item)?.labelKey ?? '') | translate\">\n @if (textLabel(item); as txt) {\n <span class=\"fly-md-editor__btn-text\">{{ txt }}</span>\n } @else {\n <i class=\"pi {{ button(item)?.icon }}\" aria-hidden=\"true\"></i>\n }\n </button>\n }\n }\n }\n </div>\n\n <div class=\"fly-md-editor__body\" tiptap [editor]=\"editor\"\n [attr.aria-label]=\"ariaLabel()\" [attr.data-placeholder]=\"placeholder()\"></div>\n</div>\n", styles: [":host{display:block}.fly-md-editor{display:flex;flex-direction:column;min-block-size:0;position:relative}.fly-md-editor--entity-above .fly-md-editor__entity-wrap{position:static}.fly-md-editor__toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:2px;padding-block:4px}.fly-md-editor__divider{inline-size:1px;block-size:18px;margin-inline:4px;background:var(--surface-border, rgba(255, 255, 255, .12))}.fly-md-editor__btn{min-inline-size:28px;block-size:28px;padding-inline:7px;border-radius:6px;border:1px solid transparent;background:transparent;color:var(--text-color-secondary, #6e6e73);font-size:12px;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.fly-md-editor__btn:hover:not(:disabled){background:var(--surface-hover, rgba(0, 0, 0, .05))}.fly-md-editor__btn.is-active{background:var(--primary-color-subtle, rgba(0, 113, 227, .12));color:var(--primary-color, #0071e3);border-color:var(--primary-color-border, rgba(0, 113, 227, .25))}.fly-md-editor__btn:disabled{opacity:.4;cursor:default}.fly-md-editor__btn i.pi{font-size:13px}.fly-md-editor__btn-text{font-weight:600;font-style:normal}@media(prefers-reduced-motion:reduce){.fly-md-editor__btn{transition:none}}.fly-md-editor__link-wrap,.fly-md-editor__entity-wrap{position:relative;display:inline-flex}.fly-md-editor__link-popover{position:absolute;inset-block-start:calc(100% + 4px);inset-inline-start:0;z-index:1000;display:flex;gap:4px;padding:4px;background:var(--surface-elevated, #fff);border:1px solid var(--surface-border, rgba(0, 0, 0, .12));border-radius:6px;box-shadow:0 4px 12px #0000001f}.fly-md-editor__link-input{inline-size:200px;padding:4px 6px;font-size:12px;border:1px solid var(--surface-border, rgba(0, 0, 0, .12));border-radius:4px;outline:none;background:transparent;color:inherit}.fly-md-editor__link-input:focus{border-color:var(--primary-color, #0071e3)}.fly-md-editor__link-ok,.fly-md-editor__link-cancel{inline-size:24px;block-size:24px;border-radius:4px;border:none;background:transparent;cursor:pointer;color:var(--text-color-secondary, #6e6e73)}.fly-md-editor__link-ok:hover,.fly-md-editor__link-cancel:hover{background:var(--surface-hover, rgba(0, 0, 0, .06))}.fly-md-editor__body{flex:1;min-block-size:56px;overflow-y:auto;padding:8px 4px;font-size:13px;line-height:1.55;color:var(--text-color, inherit);cursor:text}.fly-md-editor__body:focus-within{outline:none}::ng-deep .fly-md-editor__prosemirror{outline:none}::ng-deep .fly-md-editor__prosemirror>*{margin-block:0 .5em}::ng-deep .fly-md-editor__prosemirror>:last-child{margin-block-end:0}::ng-deep .fly-md-editor__prosemirror h1{font-size:1.4em;font-weight:700}::ng-deep .fly-md-editor__prosemirror h2{font-size:1.2em;font-weight:700}::ng-deep .fly-md-editor__prosemirror h3{font-size:1.05em;font-weight:700}::ng-deep .fly-md-editor__prosemirror ul,::ng-deep .fly-md-editor__prosemirror ol{padding-inline-start:1.4em}::ng-deep .fly-md-editor__prosemirror a{color:var(--primary-color, #0071e3);text-decoration:underline;cursor:pointer}::ng-deep .fly-md-editor__prosemirror code{background:var(--surface-hover, rgba(0, 0, 0, .06));padding:1px 4px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.95em}::ng-deep .fly-md-editor__prosemirror pre{background:var(--surface-hover, rgba(0, 0, 0, .06));border-radius:6px;padding:8px 10px;overflow-x:auto}::ng-deep .fly-md-editor__prosemirror pre code{background:transparent;padding:0}::ng-deep .fly-md-editor__prosemirror blockquote{margin-inline:0;padding-inline-start:10px;border-inline-start:3px solid var(--surface-border, rgba(0, 0, 0, .15));color:var(--text-color-secondary, #6e6e73)}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList]{list-style:none;padding-inline-start:.2em}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList] li{display:flex;align-items:flex-start;gap:6px}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList] li>label{margin-block-start:.15em}::ng-deep .fly-md-editor__prosemirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:var(--text-color-secondary, rgba(0, 0, 0, .4));float:inline-start;pointer-events:none;block-size:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: TiptapEditorDirective, selector: "tiptap[editor], [tiptap][editor], tiptap-editor[editor], [tiptapEditor][editor]", inputs: ["editor", "outputFormat"] }, { kind: "component", type: EntityLookupComponent, selector: "fly-entity-lookup", inputs: ["descriptors", "initialEntity", "initialQuery", "listboxId", "placement"], outputs: ["pick", "entityLinkSelected", "dismiss"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2793
2795
  }
2794
2796
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FlyMarkdownEditorComponent, decorators: [{
2795
2797
  type: Component,
2796
2798
  args: [{ selector: 'fly-markdown-editor', standalone: true, imports: [CommonModule, FormsModule, TiptapEditorDirective, TranslatePipe, EntityLookupComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
2797
2799
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => FlyMarkdownEditorComponent), multi: true },
2798
- ], template: "<div class=\"fly-md-editor\" [class.fly-md-editor--entity-above]=\"entityLinkPlacement() === 'above'\">\r\n <div class=\"fly-md-editor__toolbar\" role=\"toolbar\" [attr.aria-label]=\"('common.label.formatting_toolbar' | translate)\">\r\n @for (item of toolbarItems(); track $index) {\r\n @switch (item) {\r\n @case ('|') {\r\n <span class=\"fly-md-editor__divider\" aria-hidden=\"true\"></span>\r\n }\r\n @case ('link') {\r\n <div class=\"fly-md-editor__link-wrap\">\r\n <button type=\"button\" class=\"fly-md-editor__btn\" [class.is-active]=\"isActive('link')\"\r\n (click)=\"openLinkPopover()\"\r\n [title]=\"'common.label.link' | translate\" [attr.aria-label]=\"'common.label.link' | translate\">\r\n <i class=\"pi pi-link\" aria-hidden=\"true\"></i>\r\n </button>\r\n @if (showLinkPopover()) {\r\n <div class=\"fly-md-editor__link-popover\" role=\"dialog\" [attr.aria-label]=\"'common.label.link' | translate\">\r\n <input class=\"fly-md-editor__link-input\" type=\"url\"\r\n [value]=\"linkInputValue()\" (input)=\"onLinkInput($any($event.target).value)\"\r\n (keydown)=\"onLinkKeydown($event)\"\r\n [placeholder]=\"'common.label.https' | translate\"\r\n [attr.aria-label]=\"'common.label.link' | translate\" />\r\n <button type=\"button\" class=\"fly-md-editor__link-ok\" (click)=\"commitLink()\"\r\n [title]=\"'common.label.apply' | translate\"><i class=\"pi pi-check\" aria-hidden=\"true\"></i></button>\r\n <button type=\"button\" class=\"fly-md-editor__link-cancel\" (click)=\"cancelLink()\"\r\n [title]=\"'common.action.cancel' | translate\"><i class=\"pi pi-times\" aria-hidden=\"true\"></i></button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n @case ('entityLink') {\r\n <div class=\"fly-md-editor__entity-wrap\">\r\n <button type=\"button\" class=\"fly-md-editor__btn\" [class.is-active]=\"showEntityLookup()\"\r\n (click)=\"toggleEntityLookup()\" [attr.aria-expanded]=\"showEntityLookup()\"\r\n [title]=\"'common.label.insert_entity_link' | translate\" [attr.aria-label]=\"'common.label.insert_entity_link' | translate\">\r\n <i class=\"pi pi-bookmark\" aria-hidden=\"true\"></i>\r\n </button>\r\n @if (showEntityLookup()) {\r\n <fly-entity-lookup\r\n [placement]=\"entityLinkPlacement()\"\r\n [descriptors]=\"entityLookupDescriptors()\"\r\n (entityLinkSelected)=\"onEntityLinkSelected($event)\"\r\n (dismiss)=\"closeEntityLookup()\" />\r\n }\r\n </div>\r\n }\r\n @default {\r\n <button type=\"button\" class=\"fly-md-editor__btn\"\r\n [class.is-active]=\"isActive(item)\" [disabled]=\"disabled(item)\"\r\n (click)=\"run(item)\"\r\n [title]=\"(button(item)?.labelKey ?? '') | translate\"\r\n [attr.aria-label]=\"(button(item)?.labelKey ?? '') | translate\">\r\n @if (textLabel(item); as txt) {\r\n <span class=\"fly-md-editor__btn-text\">{{ txt }}</span>\r\n } @else {\r\n <i class=\"pi {{ button(item)?.icon }}\" aria-hidden=\"true\"></i>\r\n }\r\n </button>\r\n }\r\n }\r\n }\r\n </div>\r\n\r\n <div class=\"fly-md-editor__body\" tiptap [editor]=\"editor\"\r\n [attr.aria-label]=\"ariaLabel()\" [attr.data-placeholder]=\"placeholder()\"></div>\r\n</div>\r\n", styles: [":host{display:block}.fly-md-editor{display:flex;flex-direction:column;min-block-size:0;position:relative}.fly-md-editor--entity-above .fly-md-editor__entity-wrap{position:static}.fly-md-editor__toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:2px;padding-block:4px}.fly-md-editor__divider{inline-size:1px;block-size:18px;margin-inline:4px;background:var(--surface-border, rgba(255, 255, 255, .12))}.fly-md-editor__btn{min-inline-size:28px;block-size:28px;padding-inline:7px;border-radius:6px;border:1px solid transparent;background:transparent;color:var(--text-color-secondary, #6e6e73);font-size:12px;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.fly-md-editor__btn:hover:not(:disabled){background:var(--surface-hover, rgba(0, 0, 0, .05))}.fly-md-editor__btn.is-active{background:var(--primary-color-subtle, rgba(0, 113, 227, .12));color:var(--primary-color, #0071e3);border-color:var(--primary-color-border, rgba(0, 113, 227, .25))}.fly-md-editor__btn:disabled{opacity:.4;cursor:default}.fly-md-editor__btn i.pi{font-size:13px}.fly-md-editor__btn-text{font-weight:600;font-style:normal}@media(prefers-reduced-motion:reduce){.fly-md-editor__btn{transition:none}}.fly-md-editor__link-wrap,.fly-md-editor__entity-wrap{position:relative;display:inline-flex}.fly-md-editor__link-popover{position:absolute;inset-block-start:calc(100% + 4px);inset-inline-start:0;z-index:1000;display:flex;gap:4px;padding:4px;background:var(--surface-elevated, #fff);border:1px solid var(--surface-border, rgba(0, 0, 0, .12));border-radius:6px;box-shadow:0 4px 12px #0000001f}.fly-md-editor__link-input{inline-size:200px;padding:4px 6px;font-size:12px;border:1px solid var(--surface-border, rgba(0, 0, 0, .12));border-radius:4px;outline:none;background:transparent;color:inherit}.fly-md-editor__link-input:focus{border-color:var(--primary-color, #0071e3)}.fly-md-editor__link-ok,.fly-md-editor__link-cancel{inline-size:24px;block-size:24px;border-radius:4px;border:none;background:transparent;cursor:pointer;color:var(--text-color-secondary, #6e6e73)}.fly-md-editor__link-ok:hover,.fly-md-editor__link-cancel:hover{background:var(--surface-hover, rgba(0, 0, 0, .06))}.fly-md-editor__body{flex:1;min-block-size:56px;overflow-y:auto;padding:8px 4px;font-size:13px;line-height:1.55;color:var(--text-color, inherit);cursor:text}.fly-md-editor__body:focus-within{outline:none}::ng-deep .fly-md-editor__prosemirror{outline:none}::ng-deep .fly-md-editor__prosemirror>*{margin-block:0 .5em}::ng-deep .fly-md-editor__prosemirror>:last-child{margin-block-end:0}::ng-deep .fly-md-editor__prosemirror h1{font-size:1.4em;font-weight:700}::ng-deep .fly-md-editor__prosemirror h2{font-size:1.2em;font-weight:700}::ng-deep .fly-md-editor__prosemirror h3{font-size:1.05em;font-weight:700}::ng-deep .fly-md-editor__prosemirror ul,::ng-deep .fly-md-editor__prosemirror ol{padding-inline-start:1.4em}::ng-deep .fly-md-editor__prosemirror a{color:var(--primary-color, #0071e3);text-decoration:underline;cursor:pointer}::ng-deep .fly-md-editor__prosemirror code{background:var(--surface-hover, rgba(0, 0, 0, .06));padding:1px 4px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.95em}::ng-deep .fly-md-editor__prosemirror pre{background:var(--surface-hover, rgba(0, 0, 0, .06));border-radius:6px;padding:8px 10px;overflow-x:auto}::ng-deep .fly-md-editor__prosemirror pre code{background:transparent;padding:0}::ng-deep .fly-md-editor__prosemirror blockquote{margin-inline:0;padding-inline-start:10px;border-inline-start:3px solid var(--surface-border, rgba(0, 0, 0, .15));color:var(--text-color-secondary, #6e6e73)}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList]{list-style:none;padding-inline-start:.2em}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList] li{display:flex;align-items:flex-start;gap:6px}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList] li>label{margin-block-start:.15em}::ng-deep .fly-md-editor__prosemirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:var(--text-color-secondary, rgba(0, 0, 0, .4));float:inline-start;pointer-events:none;block-size:0}\n"] }]
2800
+ ], template: "<div class=\"fly-md-editor\" [class.fly-md-editor--entity-above]=\"entityLinkPlacement() === 'above'\">\n <div class=\"fly-md-editor__toolbar\" role=\"toolbar\" [attr.aria-label]=\"('common.label.formatting_toolbar' | translate)\">\n @for (item of toolbarItems(); track $index) {\n @switch (item) {\n @case ('|') {\n <span class=\"fly-md-editor__divider\" aria-hidden=\"true\"></span>\n }\n @case ('link') {\n <div class=\"fly-md-editor__link-wrap\">\n <button type=\"button\" class=\"fly-md-editor__btn\" [class.is-active]=\"isActive('link')\"\n (click)=\"openLinkPopover()\"\n [title]=\"'common.label.link' | translate\" [attr.aria-label]=\"'common.label.link' | translate\">\n <i class=\"pi pi-link\" aria-hidden=\"true\"></i>\n </button>\n @if (showLinkPopover()) {\n <div class=\"fly-md-editor__link-popover\" role=\"dialog\" [attr.aria-label]=\"'common.label.link' | translate\">\n <input class=\"fly-md-editor__link-input\" type=\"url\"\n [value]=\"linkInputValue()\" (input)=\"onLinkInput($any($event.target).value)\"\n (keydown)=\"onLinkKeydown($event)\"\n [placeholder]=\"'common.label.https' | translate\"\n [attr.aria-label]=\"'common.label.link' | translate\" />\n <button type=\"button\" class=\"fly-md-editor__link-ok\" (click)=\"commitLink()\"\n [title]=\"'common.label.apply' | translate\"><i class=\"pi pi-check\" aria-hidden=\"true\"></i></button>\n <button type=\"button\" class=\"fly-md-editor__link-cancel\" (click)=\"cancelLink()\"\n [title]=\"'common.action.cancel' | translate\"><i class=\"pi pi-times\" aria-hidden=\"true\"></i></button>\n </div>\n }\n </div>\n }\n @case ('entityLink') {\n <div class=\"fly-md-editor__entity-wrap\">\n <button type=\"button\" class=\"fly-md-editor__btn\" [class.is-active]=\"showEntityLookup()\"\n (click)=\"toggleEntityLookup()\" [attr.aria-expanded]=\"showEntityLookup()\"\n [title]=\"'common.label.insert_entity_link' | translate\" [attr.aria-label]=\"'common.label.insert_entity_link' | translate\">\n <i class=\"pi pi-bookmark\" aria-hidden=\"true\"></i>\n </button>\n @if (showEntityLookup()) {\n <fly-entity-lookup\n [placement]=\"entityLinkPlacement()\"\n [descriptors]=\"entityLookupDescriptors()\"\n (entityLinkSelected)=\"onEntityLinkSelected($event)\"\n (dismiss)=\"closeEntityLookup()\" />\n }\n </div>\n }\n @default {\n <button type=\"button\" class=\"fly-md-editor__btn\"\n [class.is-active]=\"isActive(item)\" [disabled]=\"disabled(item)\"\n (click)=\"run(item)\"\n [title]=\"(button(item)?.labelKey ?? '') | translate\"\n [attr.aria-label]=\"(button(item)?.labelKey ?? '') | translate\">\n @if (textLabel(item); as txt) {\n <span class=\"fly-md-editor__btn-text\">{{ txt }}</span>\n } @else {\n <i class=\"pi {{ button(item)?.icon }}\" aria-hidden=\"true\"></i>\n }\n </button>\n }\n }\n }\n </div>\n\n <div class=\"fly-md-editor__body\" tiptap [editor]=\"editor\"\n [attr.aria-label]=\"ariaLabel()\" [attr.data-placeholder]=\"placeholder()\"></div>\n</div>\n", styles: [":host{display:block}.fly-md-editor{display:flex;flex-direction:column;min-block-size:0;position:relative}.fly-md-editor--entity-above .fly-md-editor__entity-wrap{position:static}.fly-md-editor__toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:2px;padding-block:4px}.fly-md-editor__divider{inline-size:1px;block-size:18px;margin-inline:4px;background:var(--surface-border, rgba(255, 255, 255, .12))}.fly-md-editor__btn{min-inline-size:28px;block-size:28px;padding-inline:7px;border-radius:6px;border:1px solid transparent;background:transparent;color:var(--text-color-secondary, #6e6e73);font-size:12px;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}.fly-md-editor__btn:hover:not(:disabled){background:var(--surface-hover, rgba(0, 0, 0, .05))}.fly-md-editor__btn.is-active{background:var(--primary-color-subtle, rgba(0, 113, 227, .12));color:var(--primary-color, #0071e3);border-color:var(--primary-color-border, rgba(0, 113, 227, .25))}.fly-md-editor__btn:disabled{opacity:.4;cursor:default}.fly-md-editor__btn i.pi{font-size:13px}.fly-md-editor__btn-text{font-weight:600;font-style:normal}@media(prefers-reduced-motion:reduce){.fly-md-editor__btn{transition:none}}.fly-md-editor__link-wrap,.fly-md-editor__entity-wrap{position:relative;display:inline-flex}.fly-md-editor__link-popover{position:absolute;inset-block-start:calc(100% + 4px);inset-inline-start:0;z-index:1000;display:flex;gap:4px;padding:4px;background:var(--surface-elevated, #fff);border:1px solid var(--surface-border, rgba(0, 0, 0, .12));border-radius:6px;box-shadow:0 4px 12px #0000001f}.fly-md-editor__link-input{inline-size:200px;padding:4px 6px;font-size:12px;border:1px solid var(--surface-border, rgba(0, 0, 0, .12));border-radius:4px;outline:none;background:transparent;color:inherit}.fly-md-editor__link-input:focus{border-color:var(--primary-color, #0071e3)}.fly-md-editor__link-ok,.fly-md-editor__link-cancel{inline-size:24px;block-size:24px;border-radius:4px;border:none;background:transparent;cursor:pointer;color:var(--text-color-secondary, #6e6e73)}.fly-md-editor__link-ok:hover,.fly-md-editor__link-cancel:hover{background:var(--surface-hover, rgba(0, 0, 0, .06))}.fly-md-editor__body{flex:1;min-block-size:56px;overflow-y:auto;padding:8px 4px;font-size:13px;line-height:1.55;color:var(--text-color, inherit);cursor:text}.fly-md-editor__body:focus-within{outline:none}::ng-deep .fly-md-editor__prosemirror{outline:none}::ng-deep .fly-md-editor__prosemirror>*{margin-block:0 .5em}::ng-deep .fly-md-editor__prosemirror>:last-child{margin-block-end:0}::ng-deep .fly-md-editor__prosemirror h1{font-size:1.4em;font-weight:700}::ng-deep .fly-md-editor__prosemirror h2{font-size:1.2em;font-weight:700}::ng-deep .fly-md-editor__prosemirror h3{font-size:1.05em;font-weight:700}::ng-deep .fly-md-editor__prosemirror ul,::ng-deep .fly-md-editor__prosemirror ol{padding-inline-start:1.4em}::ng-deep .fly-md-editor__prosemirror a{color:var(--primary-color, #0071e3);text-decoration:underline;cursor:pointer}::ng-deep .fly-md-editor__prosemirror code{background:var(--surface-hover, rgba(0, 0, 0, .06));padding:1px 4px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.95em}::ng-deep .fly-md-editor__prosemirror pre{background:var(--surface-hover, rgba(0, 0, 0, .06));border-radius:6px;padding:8px 10px;overflow-x:auto}::ng-deep .fly-md-editor__prosemirror pre code{background:transparent;padding:0}::ng-deep .fly-md-editor__prosemirror blockquote{margin-inline:0;padding-inline-start:10px;border-inline-start:3px solid var(--surface-border, rgba(0, 0, 0, .15));color:var(--text-color-secondary, #6e6e73)}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList]{list-style:none;padding-inline-start:.2em}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList] li{display:flex;align-items:flex-start;gap:6px}::ng-deep .fly-md-editor__prosemirror ul[data-type=taskList] li>label{margin-block-start:.15em}::ng-deep .fly-md-editor__prosemirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:var(--text-color-secondary, rgba(0, 0, 0, .4));float:inline-start;pointer-events:none;block-size:0}\n"] }]
2799
2801
  }], ctorParameters: () => [], propDecorators: { toolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbar", required: false }] }], enableEntityLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableEntityLink", required: false }] }], entityLinkPlacement: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityLinkPlacement", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], submitShortcut: [{ type: i0.Output, args: ["submitShortcut"] }] } });
2800
2802
 
2801
2803
  class ContextMenuComponent {
@@ -3125,11 +3127,11 @@ class MessageBoxComponent {
3125
3127
  this.previouslyFocused = null;
3126
3128
  }
3127
3129
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3128
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessageBoxComponent, isStandalone: true, selector: "fly-message-box", host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "@if (service.visible()) {\r\n <div\r\n class=\"mb-backdrop\"\r\n (click)=\"onBackdropClick()\"\r\n role=\"presentation\">\r\n <div\r\n class=\"mb-dialog\"\r\n [class.mb-info]=\"service.icon() === MessageBoxIcon.Information\"\r\n [class.mb-warning]=\"service.icon() === MessageBoxIcon.Warning\"\r\n [class.mb-danger]=\"service.icon() === MessageBoxIcon.Error\"\r\n [class.mb-question]=\"service.icon() === MessageBoxIcon.Question\"\r\n (click)=\"$event.stopPropagation()\"\r\n role=\"alertdialog\"\r\n aria-modal=\"true\"\r\n aria-labelledby=\"mb-title\"\r\n [attr.aria-describedby]=\"ariaDescribedBy()\">\r\n\r\n @if (iconClass()) {\r\n <div class=\"mb-icon-wrap\">\r\n <i [class]=\"iconClass() + ' mb-icon'\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n\r\n <div class=\"mb-title\" id=\"mb-title\">{{ service.title() }}</div>\r\n <div class=\"mb-message\" id=\"mb-message\">{{ service.message() }}</div>\r\n\r\n @if (dontAskAgainConfig(); as daa) {\r\n <label class=\"mb-dont-ask-again\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"dontAskAgainChecked()\"\r\n (change)=\"onDontAskAgainToggle($event)\" />\r\n <span id=\"mb-dont-ask\">{{ daa.labelKey | translate }}</span>\r\n </label>\r\n }\r\n\r\n <div class=\"mb-actions\">\r\n @for (btn of service.buttons(); track btn.result) {\r\n <button\r\n type=\"button\"\r\n class=\"vos-btn sm mb-btn\"\r\n [class.mb-btn--primary]=\"btn.variant === 'primary'\"\r\n [class.mb-btn--danger]=\"btn.variant === 'danger'\"\r\n (click)=\"onButtonClick(btn.result)\">\r\n {{ btn.label }}\r\n </button>\r\n }\r\n </div>\r\n\r\n </div>\r\n </div>\r\n}\r\n", styles: [".mb-backdrop{position:absolute;inset:0;z-index:5100;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);animation:mbFadeIn .15s ease both}@keyframes mbFadeIn{0%{opacity:0}to{opacity:1}}.mb-dialog{background:var(--surface-card, rgba(30, 30, 30, .98));border:1px solid var(--surface-border);border-radius:16px;padding:28px 28px 20px;width:400px;max-width:90%;display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;box-shadow:0 20px 60px #0006;animation:mbScaleIn .2s cubic-bezier(.22,1,.36,1) both}@keyframes mbScaleIn{0%{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}.mb-icon-wrap{width:52px;height:52px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin-bottom:6px}.mb-icon{font-size:24px}.mb-info .mb-icon-wrap{background:#3b82f61f}.mb-info .mb-icon{color:#3b82f6}.mb-warning .mb-icon-wrap{background:#f59e0b1f}.mb-warning .mb-icon{color:#f59e0b}.mb-danger .mb-icon-wrap{background:#ef44441f}.mb-danger .mb-icon{color:#ef4444}.mb-question .mb-icon-wrap{background:#8b5cf61f}.mb-question .mb-icon{color:#8b5cf6}.mb-title{font-size:15px;font-weight:700;color:var(--text-color)}.mb-message{font-size:13px;color:var(--text-color-secondary);line-height:1.55;max-width:340px;white-space:pre-line}.mb-dont-ask-again{display:flex;align-items:center;gap:8px;margin-block-start:12px;font-size:12px;color:var(--text-color-secondary);cursor:pointer;align-self:flex-start;-webkit-user-select:none;user-select:none}.mb-dont-ask-again input[type=checkbox]{margin:0;cursor:pointer}.mb-dont-ask-again span{line-height:1.3}.mb-actions{display:flex;gap:10px;margin-top:16px;width:100%;justify-content:center;flex-wrap:wrap}.mb-btn{min-width:90px}.mb-btn--primary{background:var(--primary-color, #E8732A);color:#fff}.mb-btn--primary:hover{filter:brightness(1.1)}.mb-btn--danger{background:#ef4444;color:#fff}.mb-btn--danger:hover{background:#dc2626}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3130
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: MessageBoxComponent, isStandalone: true, selector: "fly-message-box", host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "@if (service.visible()) {\n <div\n class=\"mb-backdrop\"\n (click)=\"onBackdropClick()\"\n role=\"presentation\">\n <div\n class=\"mb-dialog\"\n [class.mb-info]=\"service.icon() === MessageBoxIcon.Information\"\n [class.mb-warning]=\"service.icon() === MessageBoxIcon.Warning\"\n [class.mb-danger]=\"service.icon() === MessageBoxIcon.Error\"\n [class.mb-question]=\"service.icon() === MessageBoxIcon.Question\"\n (click)=\"$event.stopPropagation()\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby=\"mb-title\"\n [attr.aria-describedby]=\"ariaDescribedBy()\">\n\n @if (iconClass()) {\n <div class=\"mb-icon-wrap\">\n <i [class]=\"iconClass() + ' mb-icon'\" aria-hidden=\"true\"></i>\n </div>\n }\n\n <div class=\"mb-title\" id=\"mb-title\">{{ service.title() }}</div>\n <div class=\"mb-message\" id=\"mb-message\">{{ service.message() }}</div>\n\n @if (dontAskAgainConfig(); as daa) {\n <label class=\"mb-dont-ask-again\">\n <input\n type=\"checkbox\"\n [checked]=\"dontAskAgainChecked()\"\n (change)=\"onDontAskAgainToggle($event)\" />\n <span id=\"mb-dont-ask\">{{ daa.labelKey | translate }}</span>\n </label>\n }\n\n <div class=\"mb-actions\">\n @for (btn of service.buttons(); track btn.result) {\n <button\n type=\"button\"\n class=\"vos-btn sm mb-btn\"\n [class.mb-btn--primary]=\"btn.variant === 'primary'\"\n [class.mb-btn--danger]=\"btn.variant === 'danger'\"\n (click)=\"onButtonClick(btn.result)\">\n {{ btn.label }}\n </button>\n }\n </div>\n\n </div>\n </div>\n}\n", styles: [".mb-backdrop{position:absolute;inset:0;z-index:5100;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);animation:mbFadeIn .15s ease both}@keyframes mbFadeIn{0%{opacity:0}to{opacity:1}}.mb-dialog{background:var(--surface-card, rgba(30, 30, 30, .98));border:1px solid var(--surface-border);border-radius:16px;padding:28px 28px 20px;width:400px;max-width:90%;display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;box-shadow:0 20px 60px #0006;animation:mbScaleIn .2s cubic-bezier(.22,1,.36,1) both}@keyframes mbScaleIn{0%{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}.mb-icon-wrap{width:52px;height:52px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin-bottom:6px}.mb-icon{font-size:24px}.mb-info .mb-icon-wrap{background:#3b82f61f}.mb-info .mb-icon{color:#3b82f6}.mb-warning .mb-icon-wrap{background:#f59e0b1f}.mb-warning .mb-icon{color:#f59e0b}.mb-danger .mb-icon-wrap{background:#ef44441f}.mb-danger .mb-icon{color:#ef4444}.mb-question .mb-icon-wrap{background:#8b5cf61f}.mb-question .mb-icon{color:#8b5cf6}.mb-title{font-size:15px;font-weight:700;color:var(--text-color)}.mb-message{font-size:13px;color:var(--text-color-secondary);line-height:1.55;max-width:340px;white-space:pre-line}.mb-dont-ask-again{display:flex;align-items:center;gap:8px;margin-block-start:12px;font-size:12px;color:var(--text-color-secondary);cursor:pointer;align-self:flex-start;-webkit-user-select:none;user-select:none}.mb-dont-ask-again input[type=checkbox]{margin:0;cursor:pointer}.mb-dont-ask-again span{line-height:1.3}.mb-actions{display:flex;gap:10px;margin-top:16px;width:100%;justify-content:center;flex-wrap:wrap}.mb-btn{min-width:90px}.mb-btn--primary{background:var(--primary-color, #E8732A);color:#fff}.mb-btn--primary:hover{filter:brightness(1.1)}.mb-btn--danger{background:#ef4444;color:#fff}.mb-btn--danger:hover{background:#dc2626}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3129
3131
  }
3130
3132
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageBoxComponent, decorators: [{
3131
3133
  type: Component,
3132
- args: [{ selector: 'fly-message-box', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (service.visible()) {\r\n <div\r\n class=\"mb-backdrop\"\r\n (click)=\"onBackdropClick()\"\r\n role=\"presentation\">\r\n <div\r\n class=\"mb-dialog\"\r\n [class.mb-info]=\"service.icon() === MessageBoxIcon.Information\"\r\n [class.mb-warning]=\"service.icon() === MessageBoxIcon.Warning\"\r\n [class.mb-danger]=\"service.icon() === MessageBoxIcon.Error\"\r\n [class.mb-question]=\"service.icon() === MessageBoxIcon.Question\"\r\n (click)=\"$event.stopPropagation()\"\r\n role=\"alertdialog\"\r\n aria-modal=\"true\"\r\n aria-labelledby=\"mb-title\"\r\n [attr.aria-describedby]=\"ariaDescribedBy()\">\r\n\r\n @if (iconClass()) {\r\n <div class=\"mb-icon-wrap\">\r\n <i [class]=\"iconClass() + ' mb-icon'\" aria-hidden=\"true\"></i>\r\n </div>\r\n }\r\n\r\n <div class=\"mb-title\" id=\"mb-title\">{{ service.title() }}</div>\r\n <div class=\"mb-message\" id=\"mb-message\">{{ service.message() }}</div>\r\n\r\n @if (dontAskAgainConfig(); as daa) {\r\n <label class=\"mb-dont-ask-again\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"dontAskAgainChecked()\"\r\n (change)=\"onDontAskAgainToggle($event)\" />\r\n <span id=\"mb-dont-ask\">{{ daa.labelKey | translate }}</span>\r\n </label>\r\n }\r\n\r\n <div class=\"mb-actions\">\r\n @for (btn of service.buttons(); track btn.result) {\r\n <button\r\n type=\"button\"\r\n class=\"vos-btn sm mb-btn\"\r\n [class.mb-btn--primary]=\"btn.variant === 'primary'\"\r\n [class.mb-btn--danger]=\"btn.variant === 'danger'\"\r\n (click)=\"onButtonClick(btn.result)\">\r\n {{ btn.label }}\r\n </button>\r\n }\r\n </div>\r\n\r\n </div>\r\n </div>\r\n}\r\n", styles: [".mb-backdrop{position:absolute;inset:0;z-index:5100;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);animation:mbFadeIn .15s ease both}@keyframes mbFadeIn{0%{opacity:0}to{opacity:1}}.mb-dialog{background:var(--surface-card, rgba(30, 30, 30, .98));border:1px solid var(--surface-border);border-radius:16px;padding:28px 28px 20px;width:400px;max-width:90%;display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;box-shadow:0 20px 60px #0006;animation:mbScaleIn .2s cubic-bezier(.22,1,.36,1) both}@keyframes mbScaleIn{0%{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}.mb-icon-wrap{width:52px;height:52px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin-bottom:6px}.mb-icon{font-size:24px}.mb-info .mb-icon-wrap{background:#3b82f61f}.mb-info .mb-icon{color:#3b82f6}.mb-warning .mb-icon-wrap{background:#f59e0b1f}.mb-warning .mb-icon{color:#f59e0b}.mb-danger .mb-icon-wrap{background:#ef44441f}.mb-danger .mb-icon{color:#ef4444}.mb-question .mb-icon-wrap{background:#8b5cf61f}.mb-question .mb-icon{color:#8b5cf6}.mb-title{font-size:15px;font-weight:700;color:var(--text-color)}.mb-message{font-size:13px;color:var(--text-color-secondary);line-height:1.55;max-width:340px;white-space:pre-line}.mb-dont-ask-again{display:flex;align-items:center;gap:8px;margin-block-start:12px;font-size:12px;color:var(--text-color-secondary);cursor:pointer;align-self:flex-start;-webkit-user-select:none;user-select:none}.mb-dont-ask-again input[type=checkbox]{margin:0;cursor:pointer}.mb-dont-ask-again span{line-height:1.3}.mb-actions{display:flex;gap:10px;margin-top:16px;width:100%;justify-content:center;flex-wrap:wrap}.mb-btn{min-width:90px}.mb-btn--primary{background:var(--primary-color, #E8732A);color:#fff}.mb-btn--primary:hover{filter:brightness(1.1)}.mb-btn--danger{background:#ef4444;color:#fff}.mb-btn--danger:hover{background:#dc2626}\n"] }]
3134
+ args: [{ selector: 'fly-message-box', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (service.visible()) {\n <div\n class=\"mb-backdrop\"\n (click)=\"onBackdropClick()\"\n role=\"presentation\">\n <div\n class=\"mb-dialog\"\n [class.mb-info]=\"service.icon() === MessageBoxIcon.Information\"\n [class.mb-warning]=\"service.icon() === MessageBoxIcon.Warning\"\n [class.mb-danger]=\"service.icon() === MessageBoxIcon.Error\"\n [class.mb-question]=\"service.icon() === MessageBoxIcon.Question\"\n (click)=\"$event.stopPropagation()\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby=\"mb-title\"\n [attr.aria-describedby]=\"ariaDescribedBy()\">\n\n @if (iconClass()) {\n <div class=\"mb-icon-wrap\">\n <i [class]=\"iconClass() + ' mb-icon'\" aria-hidden=\"true\"></i>\n </div>\n }\n\n <div class=\"mb-title\" id=\"mb-title\">{{ service.title() }}</div>\n <div class=\"mb-message\" id=\"mb-message\">{{ service.message() }}</div>\n\n @if (dontAskAgainConfig(); as daa) {\n <label class=\"mb-dont-ask-again\">\n <input\n type=\"checkbox\"\n [checked]=\"dontAskAgainChecked()\"\n (change)=\"onDontAskAgainToggle($event)\" />\n <span id=\"mb-dont-ask\">{{ daa.labelKey | translate }}</span>\n </label>\n }\n\n <div class=\"mb-actions\">\n @for (btn of service.buttons(); track btn.result) {\n <button\n type=\"button\"\n class=\"vos-btn sm mb-btn\"\n [class.mb-btn--primary]=\"btn.variant === 'primary'\"\n [class.mb-btn--danger]=\"btn.variant === 'danger'\"\n (click)=\"onButtonClick(btn.result)\">\n {{ btn.label }}\n </button>\n }\n </div>\n\n </div>\n </div>\n}\n", styles: [".mb-backdrop{position:absolute;inset:0;z-index:5100;background:#00000073;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);animation:mbFadeIn .15s ease both}@keyframes mbFadeIn{0%{opacity:0}to{opacity:1}}.mb-dialog{background:var(--surface-card, rgba(30, 30, 30, .98));border:1px solid var(--surface-border);border-radius:16px;padding:28px 28px 20px;width:400px;max-width:90%;display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;box-shadow:0 20px 60px #0006;animation:mbScaleIn .2s cubic-bezier(.22,1,.36,1) both}@keyframes mbScaleIn{0%{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}.mb-icon-wrap{width:52px;height:52px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin-bottom:6px}.mb-icon{font-size:24px}.mb-info .mb-icon-wrap{background:#3b82f61f}.mb-info .mb-icon{color:#3b82f6}.mb-warning .mb-icon-wrap{background:#f59e0b1f}.mb-warning .mb-icon{color:#f59e0b}.mb-danger .mb-icon-wrap{background:#ef44441f}.mb-danger .mb-icon{color:#ef4444}.mb-question .mb-icon-wrap{background:#8b5cf61f}.mb-question .mb-icon{color:#8b5cf6}.mb-title{font-size:15px;font-weight:700;color:var(--text-color)}.mb-message{font-size:13px;color:var(--text-color-secondary);line-height:1.55;max-width:340px;white-space:pre-line}.mb-dont-ask-again{display:flex;align-items:center;gap:8px;margin-block-start:12px;font-size:12px;color:var(--text-color-secondary);cursor:pointer;align-self:flex-start;-webkit-user-select:none;user-select:none}.mb-dont-ask-again input[type=checkbox]{margin:0;cursor:pointer}.mb-dont-ask-again span{line-height:1.3}.mb-actions{display:flex;gap:10px;margin-top:16px;width:100%;justify-content:center;flex-wrap:wrap}.mb-btn{min-width:90px}.mb-btn--primary{background:var(--primary-color, #E8732A);color:#fff}.mb-btn--primary:hover{filter:brightness(1.1)}.mb-btn--danger{background:#ef4444;color:#fff}.mb-btn--danger:hover{background:#dc2626}\n"] }]
3133
3135
  }], propDecorators: { onEscape: [{
3134
3136
  type: HostListener,
3135
3137
  args: ['document:keydown.escape']
@@ -3461,11 +3463,11 @@ class SharePanelComponent {
3461
3463
  }
3462
3464
  }
3463
3465
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SharePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3464
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: SharePanelComponent, isStandalone: true, selector: "fly-share-panel", inputs: { targetName: "targetName", titleKey: "titleKey", loadPermissions: "loadPermissions", searchUsers: "searchUsers", loadOuTree: "loadOuTree", loadChartOptions: "loadChartOptions", defaultChartSystemKey: "defaultChartSystemKey", defaultChartId: "defaultChartId", loadOuLabelMap: "loadOuLabelMap", grantToUser: "grantToUser", grantToOu: "grantToOu", updatePermission: "updatePermission", revokePermission: "revokePermission", showApplyToChildren: "showApplyToChildren", supportsDeny: "supportsDeny", permissionLevels: "permissionLevels", everyoneLabelKey: "everyoneLabelKey", loadRoleOus: "loadRoleOus" }, outputs: { close: "close" }, ngImport: i0, template: "<div class=\"fac-overlay\" (click)=\"close.emit()\">\r\n <div class=\"fac-panel\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"fac-header\">\r\n <h3>{{ titleKey | translate }}</h3>\r\n <span class=\"fac-target-name\">{{ targetName }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"fac-close\"\r\n (click)=\"close.emit()\"\r\n [attr.aria-label]=\"'files.share.close' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n\r\n <div class=\"fac-add-section\">\r\n <div class=\"fac-search-row\">\r\n <input\r\n type=\"text\"\r\n class=\"fac-input\"\r\n [(ngModel)]=\"searchQuery\"\r\n (input)=\"onSearchInput()\"\r\n [placeholder]=\"'files.share.search_placeholder' | translate\"\r\n [attr.aria-label]=\"'files.share.search_users' | translate\"\r\n />\r\n <select class=\"fac-select\" [(ngModel)]=\"newLevel\">\r\n @for (opt of levelOptions; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.labelKey | translate }}</option>\r\n }\r\n </select>\r\n </div>\r\n\r\n @if (searchResults().length > 0) {\r\n <div class=\"fac-search-results\">\r\n @for (result of searchResults(); track result.id) {\r\n <div class=\"fac-search-item\" (click)=\"onGrantToUser(result)\">\r\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\r\n <span>{{ result.firstName }} {{ result.lastName }}</span>\r\n <span class=\"fac-email\">{{ result.email }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (chartOptions().length > 0) {\r\n <div class=\"fac-chart-row\">\r\n <label for=\"fac-org-chart-select\" class=\"fac-section-label\">{{\r\n 'files.share.org_chart' | translate\r\n }}</label>\r\n <select\r\n id=\"fac-org-chart-select\"\r\n class=\"fac-select\"\r\n [ngModel]=\"selectedOrgChartId()\"\r\n (ngModelChange)=\"onOrgChartSelectChange($event)\">\r\n @for (opt of chartOptions(); track $index) {\r\n <option [ngValue]=\"opt.id\">{{ opt.name }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n\r\n @if (showOuPicker()) {\r\n <div class=\"fac-ou-section\">\r\n <div class=\"fac-section-label\">{{ 'files.share.share_with_ou' | translate }}</div>\r\n @for (ou of ouTree(); track ou.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fac-ou-item\"\r\n [style.padding-inline-start.px]=\"ouIndentStartPx(ou)\"\r\n (click)=\"onGrantToOu(ou)\"\r\n [attr.aria-label]=\"('files.share.share_with_ou_named' | translate) + ' ' + ou.displayName\"\r\n >\r\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\r\n <span dir=\"auto\">{{ ou.displayName }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n @if (loadRoleOus && roleOus().length > 0) {\r\n <div class=\"fac-role-section\">\r\n <div class=\"fac-section-label\">{{ 'files.share.share_with_role' | translate }}</div>\r\n <input\r\n type=\"text\"\r\n class=\"fac-input\"\r\n [(ngModel)]=\"roleSearchQuery\"\r\n [placeholder]=\"'files.share.role_search_placeholder' | translate\"\r\n [attr.aria-label]=\"'files.share.search_roles' | translate\"\r\n [hidden]=\"!showRolePicker()\" />\r\n @if (showRolePicker()) {\r\n <div class=\"fac-role-list\">\r\n @for (role of filteredRoles(); track role.ouId) {\r\n <button\r\n type=\"button\"\r\n class=\"fac-role-item\"\r\n (click)=\"onGrantToRole(role)\"\r\n [attr.aria-label]=\"('files.share.share_with_role_named' | translate) + ' ' + role.displayName\">\r\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\r\n <span dir=\"auto\">{{ role.displayName }}</span>\r\n <span class=\"fac-role-app\">{{ role.appId }}</span>\r\n </button>\r\n }\r\n @if (filteredRoles().length === 0) {\r\n <div class=\"fac-empty\">{{ 'files.share.no_roles_match' | translate }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"fac-toggle-row\">\r\n <button type=\"button\" class=\"fac-link\" (click)=\"showOuPicker.set(!showOuPicker())\">\r\n {{ showOuPicker() ? ('files.share.hide_ous' | translate) : ('files.share.show_ous' | translate) }}\r\n </button>\r\n @if (loadRoleOus && roleOus().length > 0) {\r\n <button type=\"button\" class=\"fac-link\" (click)=\"showRolePicker.set(!showRolePicker())\">\r\n {{ showRolePicker() ? ('files.share.hide_roles' | translate) : ('files.share.show_roles' | translate) }}\r\n </button>\r\n }\r\n @if (showApplyToChildren) {\r\n <label class=\"fac-checkbox-label\">\r\n <input type=\"checkbox\" [(ngModel)]=\"applyToChildren\" />\r\n {{ 'files.share.apply_children' | translate }}\r\n </label>\r\n }\r\n @if (supportsDeny) {\r\n <label class=\"fac-checkbox-label fac-deny-toggle\"\r\n [title]=\"'files.share.deny_help' | translate\">\r\n <input type=\"checkbox\" [(ngModel)]=\"addAsDeny\" />\r\n <i class=\"pi pi-ban\" aria-hidden=\"true\"></i>\r\n {{ 'files.share.add_as_deny' | translate }}\r\n </label>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fac-perms-section\">\r\n <div class=\"fac-section-label\">{{ 'files.share.current_permissions' | translate }}</div>\r\n @if (loading()) {\r\n <div class=\"fac-loading\"><i class=\"pi pi-spin pi-spinner\" aria-hidden=\"true\"></i></div>\r\n } @else if (permissions().length === 0) {\r\n <div class=\"fac-empty\">{{ 'files.share.no_permissions' | translate }}</div>\r\n } @else {\r\n @for (perm of permissions(); track perm.id) {\r\n <div class=\"fac-perm-row\" [class.fac-perm-row-deny]=\"perm.isDeny\">\r\n <div class=\"fac-perm-info\">\r\n <i [class]=\"getPermIcon(perm)\" aria-hidden=\"true\"></i>\r\n <span class=\"fac-perm-name\" dir=\"auto\">{{ getPermLabel(perm) }}</span>\r\n @if (perm.isDeny) {\r\n <span class=\"fac-badge deny\">{{ 'files.share.denied' | translate }}</span>\r\n }\r\n @if (perm.isInherited) {\r\n <span class=\"fac-badge inherited\">{{ 'files.share.inherited' | translate }}</span>\r\n }\r\n </div>\r\n <div class=\"fac-perm-actions\">\r\n @if (!perm.isDeny) {\r\n <select\r\n class=\"fac-select sm\"\r\n [ngModel]=\"perm.level\"\r\n (ngModelChange)=\"onUpdateLevel(perm, $event)\"\r\n [disabled]=\"perm.isInherited === true\"\r\n >\r\n @for (opt of levelOptions; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.labelKey | translate }}</option>\r\n }\r\n </select>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"fac-icon-btn danger\"\r\n (click)=\"onRevokePermission(perm)\"\r\n [disabled]=\"perm.isInherited === true\"\r\n [title]=\"'files.share.revoke' | translate\"\r\n >\r\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".fac-overlay{position:fixed;inset:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:2000;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.fac-panel{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:12px;width:600px;max-width:min(600px,96vw);max-height:85vh;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 16px 48px #0006}.fac-header{display:flex;align-items:center;gap:10px;padding:16px 20px;border-bottom:1px solid var(--surface-border)}.fac-header h3{margin:0;font-size:16px;font-weight:600}.fac-target-name{flex:1;font-size:13px;color:var(--text-color-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fac-close{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;font-size:16px;padding:4px}.fac-close:hover{color:var(--text-color)}.fac-add-section{padding:16px 20px;border-bottom:1px solid var(--surface-border)}.fac-search-row{display:flex;gap:8px}.fac-chart-row{display:flex;flex-direction:column;gap:6px;margin-top:12px}.fac-chart-row .fac-select{width:100%}.fac-input{flex:1;background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 12px;color:inherit;font-size:13px;outline:none}.fac-input:focus{border-color:var(--primary-color, #e8732a)}.fac-select{background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 10px;color:inherit;font-size:13px;outline:none}.fac-select.sm{padding:4px 8px;font-size:12px}.fac-search-results{margin-top:8px;max-height:150px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fac-search-item{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;font-size:13px}.fac-search-item:hover{background:var(--surface-hover)}.fac-search-item i{color:var(--text-color-secondary)}.fac-email{color:var(--text-color-secondary);font-size:12px;margin-inline-start:auto}.fac-ou-section{margin-top:10px;max-height:220px;overflow-y:auto}.fac-ou-item{display:flex;align-items:center;gap:8px;padding:6px 12px;padding-inline-start:12px;cursor:pointer;font-size:13px;border-radius:6px}.fac-ou-item:hover{background:var(--surface-hover)}.fac-ou-item i{color:var(--text-color-secondary)}.fac-section-label{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--text-color-secondary);letter-spacing:.5px;margin-bottom:8px}.fac-toggle-row{display:flex;align-items:center;justify-content:space-between;margin-top:10px}.fac-link{background:none;border:none;color:var(--primary-color, #e8732a);cursor:pointer;font-size:12px;padding:0}.fac-link:hover{text-decoration:underline}.fac-checkbox-label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-color-secondary);cursor:pointer}.fac-checkbox-label input{accent-color:var(--primary-color, #e8732a)}.fac-perms-section{flex:1;overflow-y:auto;padding:16px 20px}.fac-loading,.fac-empty{text-align:center;padding:20px;color:var(--text-color-secondary);font-size:13px}.fac-perm-row{display:flex;align-items:center;justify-content:space-between;padding:8px 0;border-bottom:1px solid rgba(255,255,255,.05);gap:8px}.fac-perm-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.fac-perm-info i{color:var(--text-color-secondary);flex-shrink:0}.fac-perm-name{font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fac-badge{font-size:10px;padding:2px 6px;border-radius:8px;flex-shrink:0}.fac-badge.inherited{background:#ffffff1a;color:var(--text-color-secondary)}.fac-badge.deny{background:#ff3b302e;color:#ff3b30;text-transform:uppercase;font-weight:600;letter-spacing:.5px}.fac-perm-row-deny{background:#ff3b300f;border-inline-start:3px solid #ff3b30;padding-inline-start:8px;border-radius:6px}.fac-perm-row-deny .fac-perm-info i{color:#ff3b30}.fac-deny-toggle{color:#ff6b6b}.fac-deny-toggle i{color:#ff6b6b;font-size:11px;margin-inline-end:2px}.fac-deny-toggle input{accent-color:#ff3b30}.fac-role-section{margin-top:10px;display:flex;flex-direction:column;gap:6px}.fac-role-list{margin-top:6px;max-height:220px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fac-role-item{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;font-size:13px}.fac-role-item:hover{background:var(--surface-hover)}.fac-role-item i{color:var(--text-color-secondary)}.fac-role-app{margin-inline-start:auto;font-size:11px;color:var(--text-color-secondary);text-transform:uppercase;letter-spacing:.5px}.fac-perm-actions{display:flex;align-items:center;gap:6px;flex-shrink:0}.fac-icon-btn{background:#ffffff0f;border:none;border-radius:6px;width:28px;height:28px;display:flex;align-items:center;justify-content:center;color:inherit;cursor:pointer;font-size:12px}.fac-icon-btn:hover{background:#ffffff24}.fac-icon-btn.danger:hover{background:#ff3b3033;color:#ff3b30}.fac-icon-btn:disabled{opacity:.4;cursor:default}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3466
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: SharePanelComponent, isStandalone: true, selector: "fly-share-panel", inputs: { targetName: "targetName", titleKey: "titleKey", loadPermissions: "loadPermissions", searchUsers: "searchUsers", loadOuTree: "loadOuTree", loadChartOptions: "loadChartOptions", defaultChartSystemKey: "defaultChartSystemKey", defaultChartId: "defaultChartId", loadOuLabelMap: "loadOuLabelMap", grantToUser: "grantToUser", grantToOu: "grantToOu", updatePermission: "updatePermission", revokePermission: "revokePermission", showApplyToChildren: "showApplyToChildren", supportsDeny: "supportsDeny", permissionLevels: "permissionLevels", everyoneLabelKey: "everyoneLabelKey", loadRoleOus: "loadRoleOus" }, outputs: { close: "close" }, ngImport: i0, template: "<div class=\"fac-overlay\" (click)=\"close.emit()\">\n <div class=\"fac-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"fac-header\">\n <h3>{{ titleKey | translate }}</h3>\n <span class=\"fac-target-name\">{{ targetName }}</span>\n <button\n type=\"button\"\n class=\"fac-close\"\n (click)=\"close.emit()\"\n [attr.aria-label]=\"'files.share.close' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <div class=\"fac-add-section\">\n <div class=\"fac-search-row\">\n <input\n type=\"text\"\n class=\"fac-input\"\n [(ngModel)]=\"searchQuery\"\n (input)=\"onSearchInput()\"\n [placeholder]=\"'files.share.search_placeholder' | translate\"\n [attr.aria-label]=\"'files.share.search_users' | translate\"\n />\n <select class=\"fac-select\" [(ngModel)]=\"newLevel\">\n @for (opt of levelOptions; track opt.value) {\n <option [value]=\"opt.value\">{{ opt.labelKey | translate }}</option>\n }\n </select>\n </div>\n\n @if (searchResults().length > 0) {\n <div class=\"fac-search-results\">\n @for (result of searchResults(); track result.id) {\n <div class=\"fac-search-item\" (click)=\"onGrantToUser(result)\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <span>{{ result.firstName }} {{ result.lastName }}</span>\n <span class=\"fac-email\">{{ result.email }}</span>\n </div>\n }\n </div>\n }\n\n @if (chartOptions().length > 0) {\n <div class=\"fac-chart-row\">\n <label for=\"fac-org-chart-select\" class=\"fac-section-label\">{{\n 'files.share.org_chart' | translate\n }}</label>\n <select\n id=\"fac-org-chart-select\"\n class=\"fac-select\"\n [ngModel]=\"selectedOrgChartId()\"\n (ngModelChange)=\"onOrgChartSelectChange($event)\">\n @for (opt of chartOptions(); track $index) {\n <option [ngValue]=\"opt.id\">{{ opt.name }}</option>\n }\n </select>\n </div>\n }\n\n @if (showOuPicker()) {\n <div class=\"fac-ou-section\">\n <div class=\"fac-section-label\">{{ 'files.share.share_with_ou' | translate }}</div>\n @for (ou of ouTree(); track ou.id) {\n <button\n type=\"button\"\n class=\"fac-ou-item\"\n [style.padding-inline-start.px]=\"ouIndentStartPx(ou)\"\n (click)=\"onGrantToOu(ou)\"\n [attr.aria-label]=\"('files.share.share_with_ou_named' | translate) + ' ' + ou.displayName\"\n >\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\n <span dir=\"auto\">{{ ou.displayName }}</span>\n </button>\n }\n </div>\n }\n\n @if (loadRoleOus && roleOus().length > 0) {\n <div class=\"fac-role-section\">\n <div class=\"fac-section-label\">{{ 'files.share.share_with_role' | translate }}</div>\n <input\n type=\"text\"\n class=\"fac-input\"\n [(ngModel)]=\"roleSearchQuery\"\n [placeholder]=\"'files.share.role_search_placeholder' | translate\"\n [attr.aria-label]=\"'files.share.search_roles' | translate\"\n [hidden]=\"!showRolePicker()\" />\n @if (showRolePicker()) {\n <div class=\"fac-role-list\">\n @for (role of filteredRoles(); track role.ouId) {\n <button\n type=\"button\"\n class=\"fac-role-item\"\n (click)=\"onGrantToRole(role)\"\n [attr.aria-label]=\"('files.share.share_with_role_named' | translate) + ' ' + role.displayName\">\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\n <span dir=\"auto\">{{ role.displayName }}</span>\n <span class=\"fac-role-app\">{{ role.appId }}</span>\n </button>\n }\n @if (filteredRoles().length === 0) {\n <div class=\"fac-empty\">{{ 'files.share.no_roles_match' | translate }}</div>\n }\n </div>\n }\n </div>\n }\n\n <div class=\"fac-toggle-row\">\n <button type=\"button\" class=\"fac-link\" (click)=\"showOuPicker.set(!showOuPicker())\">\n {{ showOuPicker() ? ('files.share.hide_ous' | translate) : ('files.share.show_ous' | translate) }}\n </button>\n @if (loadRoleOus && roleOus().length > 0) {\n <button type=\"button\" class=\"fac-link\" (click)=\"showRolePicker.set(!showRolePicker())\">\n {{ showRolePicker() ? ('files.share.hide_roles' | translate) : ('files.share.show_roles' | translate) }}\n </button>\n }\n @if (showApplyToChildren) {\n <label class=\"fac-checkbox-label\">\n <input type=\"checkbox\" [(ngModel)]=\"applyToChildren\" />\n {{ 'files.share.apply_children' | translate }}\n </label>\n }\n @if (supportsDeny) {\n <label class=\"fac-checkbox-label fac-deny-toggle\"\n [title]=\"'files.share.deny_help' | translate\">\n <input type=\"checkbox\" [(ngModel)]=\"addAsDeny\" />\n <i class=\"pi pi-ban\" aria-hidden=\"true\"></i>\n {{ 'files.share.add_as_deny' | translate }}\n </label>\n }\n </div>\n </div>\n\n <div class=\"fac-perms-section\">\n <div class=\"fac-section-label\">{{ 'files.share.current_permissions' | translate }}</div>\n @if (loading()) {\n <div class=\"fac-loading\"><i class=\"pi pi-spin pi-spinner\" aria-hidden=\"true\"></i></div>\n } @else if (permissions().length === 0) {\n <div class=\"fac-empty\">{{ 'files.share.no_permissions' | translate }}</div>\n } @else {\n @for (perm of permissions(); track perm.id) {\n <div class=\"fac-perm-row\" [class.fac-perm-row-deny]=\"perm.isDeny\">\n <div class=\"fac-perm-info\">\n <i [class]=\"getPermIcon(perm)\" aria-hidden=\"true\"></i>\n <span class=\"fac-perm-name\" dir=\"auto\">{{ getPermLabel(perm) }}</span>\n @if (perm.isDeny) {\n <span class=\"fac-badge deny\">{{ 'files.share.denied' | translate }}</span>\n }\n @if (perm.isInherited) {\n <span class=\"fac-badge inherited\">{{ 'files.share.inherited' | translate }}</span>\n }\n </div>\n <div class=\"fac-perm-actions\">\n @if (!perm.isDeny) {\n <select\n class=\"fac-select sm\"\n [ngModel]=\"perm.level\"\n (ngModelChange)=\"onUpdateLevel(perm, $event)\"\n [disabled]=\"perm.isInherited === true\"\n >\n @for (opt of levelOptions; track opt.value) {\n <option [value]=\"opt.value\">{{ opt.labelKey | translate }}</option>\n }\n </select>\n }\n <button\n type=\"button\"\n class=\"fac-icon-btn danger\"\n (click)=\"onRevokePermission(perm)\"\n [disabled]=\"perm.isInherited === true\"\n [title]=\"'files.share.revoke' | translate\"\n >\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n }\n }\n </div>\n </div>\n</div>\n", styles: [".fac-overlay{position:fixed;inset:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:2000;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.fac-panel{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:12px;width:600px;max-width:min(600px,96vw);max-height:85vh;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 16px 48px #0006}.fac-header{display:flex;align-items:center;gap:10px;padding:16px 20px;border-bottom:1px solid var(--surface-border)}.fac-header h3{margin:0;font-size:16px;font-weight:600}.fac-target-name{flex:1;font-size:13px;color:var(--text-color-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fac-close{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;font-size:16px;padding:4px}.fac-close:hover{color:var(--text-color)}.fac-add-section{padding:16px 20px;border-bottom:1px solid var(--surface-border)}.fac-search-row{display:flex;gap:8px}.fac-chart-row{display:flex;flex-direction:column;gap:6px;margin-top:12px}.fac-chart-row .fac-select{width:100%}.fac-input{flex:1;background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 12px;color:inherit;font-size:13px;outline:none}.fac-input:focus{border-color:var(--primary-color, #e8732a)}.fac-select{background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 10px;color:inherit;font-size:13px;outline:none}.fac-select.sm{padding:4px 8px;font-size:12px}.fac-search-results{margin-top:8px;max-height:150px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fac-search-item{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;font-size:13px}.fac-search-item:hover{background:var(--surface-hover)}.fac-search-item i{color:var(--text-color-secondary)}.fac-email{color:var(--text-color-secondary);font-size:12px;margin-inline-start:auto}.fac-ou-section{margin-top:10px;max-height:220px;overflow-y:auto}.fac-ou-item{display:flex;align-items:center;gap:8px;padding:6px 12px;padding-inline-start:12px;cursor:pointer;font-size:13px;border-radius:6px}.fac-ou-item:hover{background:var(--surface-hover)}.fac-ou-item i{color:var(--text-color-secondary)}.fac-section-label{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--text-color-secondary);letter-spacing:.5px;margin-bottom:8px}.fac-toggle-row{display:flex;align-items:center;justify-content:space-between;margin-top:10px}.fac-link{background:none;border:none;color:var(--primary-color, #e8732a);cursor:pointer;font-size:12px;padding:0}.fac-link:hover{text-decoration:underline}.fac-checkbox-label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-color-secondary);cursor:pointer}.fac-checkbox-label input{accent-color:var(--primary-color, #e8732a)}.fac-perms-section{flex:1;overflow-y:auto;padding:16px 20px}.fac-loading,.fac-empty{text-align:center;padding:20px;color:var(--text-color-secondary);font-size:13px}.fac-perm-row{display:flex;align-items:center;justify-content:space-between;padding:8px 0;border-bottom:1px solid rgba(255,255,255,.05);gap:8px}.fac-perm-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.fac-perm-info i{color:var(--text-color-secondary);flex-shrink:0}.fac-perm-name{font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fac-badge{font-size:10px;padding:2px 6px;border-radius:8px;flex-shrink:0}.fac-badge.inherited{background:#ffffff1a;color:var(--text-color-secondary)}.fac-badge.deny{background:#ff3b302e;color:#ff3b30;text-transform:uppercase;font-weight:600;letter-spacing:.5px}.fac-perm-row-deny{background:#ff3b300f;border-inline-start:3px solid #ff3b30;padding-inline-start:8px;border-radius:6px}.fac-perm-row-deny .fac-perm-info i{color:#ff3b30}.fac-deny-toggle{color:#ff6b6b}.fac-deny-toggle i{color:#ff6b6b;font-size:11px;margin-inline-end:2px}.fac-deny-toggle input{accent-color:#ff3b30}.fac-role-section{margin-top:10px;display:flex;flex-direction:column;gap:6px}.fac-role-list{margin-top:6px;max-height:220px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fac-role-item{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;font-size:13px}.fac-role-item:hover{background:var(--surface-hover)}.fac-role-item i{color:var(--text-color-secondary)}.fac-role-app{margin-inline-start:auto;font-size:11px;color:var(--text-color-secondary);text-transform:uppercase;letter-spacing:.5px}.fac-perm-actions{display:flex;align-items:center;gap:6px;flex-shrink:0}.fac-icon-btn{background:#ffffff0f;border:none;border-radius:6px;width:28px;height:28px;display:flex;align-items:center;justify-content:center;color:inherit;cursor:pointer;font-size:12px}.fac-icon-btn:hover{background:#ffffff24}.fac-icon-btn.danger:hover{background:#ff3b3033;color:#ff3b30}.fac-icon-btn:disabled{opacity:.4;cursor:default}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3465
3467
  }
3466
3468
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SharePanelComponent, decorators: [{
3467
3469
  type: Component,
3468
- args: [{ selector: 'fly-share-panel', standalone: true, imports: [CommonModule, FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fac-overlay\" (click)=\"close.emit()\">\r\n <div class=\"fac-panel\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"fac-header\">\r\n <h3>{{ titleKey | translate }}</h3>\r\n <span class=\"fac-target-name\">{{ targetName }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"fac-close\"\r\n (click)=\"close.emit()\"\r\n [attr.aria-label]=\"'files.share.close' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n\r\n <div class=\"fac-add-section\">\r\n <div class=\"fac-search-row\">\r\n <input\r\n type=\"text\"\r\n class=\"fac-input\"\r\n [(ngModel)]=\"searchQuery\"\r\n (input)=\"onSearchInput()\"\r\n [placeholder]=\"'files.share.search_placeholder' | translate\"\r\n [attr.aria-label]=\"'files.share.search_users' | translate\"\r\n />\r\n <select class=\"fac-select\" [(ngModel)]=\"newLevel\">\r\n @for (opt of levelOptions; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.labelKey | translate }}</option>\r\n }\r\n </select>\r\n </div>\r\n\r\n @if (searchResults().length > 0) {\r\n <div class=\"fac-search-results\">\r\n @for (result of searchResults(); track result.id) {\r\n <div class=\"fac-search-item\" (click)=\"onGrantToUser(result)\">\r\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\r\n <span>{{ result.firstName }} {{ result.lastName }}</span>\r\n <span class=\"fac-email\">{{ result.email }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (chartOptions().length > 0) {\r\n <div class=\"fac-chart-row\">\r\n <label for=\"fac-org-chart-select\" class=\"fac-section-label\">{{\r\n 'files.share.org_chart' | translate\r\n }}</label>\r\n <select\r\n id=\"fac-org-chart-select\"\r\n class=\"fac-select\"\r\n [ngModel]=\"selectedOrgChartId()\"\r\n (ngModelChange)=\"onOrgChartSelectChange($event)\">\r\n @for (opt of chartOptions(); track $index) {\r\n <option [ngValue]=\"opt.id\">{{ opt.name }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n\r\n @if (showOuPicker()) {\r\n <div class=\"fac-ou-section\">\r\n <div class=\"fac-section-label\">{{ 'files.share.share_with_ou' | translate }}</div>\r\n @for (ou of ouTree(); track ou.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fac-ou-item\"\r\n [style.padding-inline-start.px]=\"ouIndentStartPx(ou)\"\r\n (click)=\"onGrantToOu(ou)\"\r\n [attr.aria-label]=\"('files.share.share_with_ou_named' | translate) + ' ' + ou.displayName\"\r\n >\r\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\r\n <span dir=\"auto\">{{ ou.displayName }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n\r\n @if (loadRoleOus && roleOus().length > 0) {\r\n <div class=\"fac-role-section\">\r\n <div class=\"fac-section-label\">{{ 'files.share.share_with_role' | translate }}</div>\r\n <input\r\n type=\"text\"\r\n class=\"fac-input\"\r\n [(ngModel)]=\"roleSearchQuery\"\r\n [placeholder]=\"'files.share.role_search_placeholder' | translate\"\r\n [attr.aria-label]=\"'files.share.search_roles' | translate\"\r\n [hidden]=\"!showRolePicker()\" />\r\n @if (showRolePicker()) {\r\n <div class=\"fac-role-list\">\r\n @for (role of filteredRoles(); track role.ouId) {\r\n <button\r\n type=\"button\"\r\n class=\"fac-role-item\"\r\n (click)=\"onGrantToRole(role)\"\r\n [attr.aria-label]=\"('files.share.share_with_role_named' | translate) + ' ' + role.displayName\">\r\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\r\n <span dir=\"auto\">{{ role.displayName }}</span>\r\n <span class=\"fac-role-app\">{{ role.appId }}</span>\r\n </button>\r\n }\r\n @if (filteredRoles().length === 0) {\r\n <div class=\"fac-empty\">{{ 'files.share.no_roles_match' | translate }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"fac-toggle-row\">\r\n <button type=\"button\" class=\"fac-link\" (click)=\"showOuPicker.set(!showOuPicker())\">\r\n {{ showOuPicker() ? ('files.share.hide_ous' | translate) : ('files.share.show_ous' | translate) }}\r\n </button>\r\n @if (loadRoleOus && roleOus().length > 0) {\r\n <button type=\"button\" class=\"fac-link\" (click)=\"showRolePicker.set(!showRolePicker())\">\r\n {{ showRolePicker() ? ('files.share.hide_roles' | translate) : ('files.share.show_roles' | translate) }}\r\n </button>\r\n }\r\n @if (showApplyToChildren) {\r\n <label class=\"fac-checkbox-label\">\r\n <input type=\"checkbox\" [(ngModel)]=\"applyToChildren\" />\r\n {{ 'files.share.apply_children' | translate }}\r\n </label>\r\n }\r\n @if (supportsDeny) {\r\n <label class=\"fac-checkbox-label fac-deny-toggle\"\r\n [title]=\"'files.share.deny_help' | translate\">\r\n <input type=\"checkbox\" [(ngModel)]=\"addAsDeny\" />\r\n <i class=\"pi pi-ban\" aria-hidden=\"true\"></i>\r\n {{ 'files.share.add_as_deny' | translate }}\r\n </label>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fac-perms-section\">\r\n <div class=\"fac-section-label\">{{ 'files.share.current_permissions' | translate }}</div>\r\n @if (loading()) {\r\n <div class=\"fac-loading\"><i class=\"pi pi-spin pi-spinner\" aria-hidden=\"true\"></i></div>\r\n } @else if (permissions().length === 0) {\r\n <div class=\"fac-empty\">{{ 'files.share.no_permissions' | translate }}</div>\r\n } @else {\r\n @for (perm of permissions(); track perm.id) {\r\n <div class=\"fac-perm-row\" [class.fac-perm-row-deny]=\"perm.isDeny\">\r\n <div class=\"fac-perm-info\">\r\n <i [class]=\"getPermIcon(perm)\" aria-hidden=\"true\"></i>\r\n <span class=\"fac-perm-name\" dir=\"auto\">{{ getPermLabel(perm) }}</span>\r\n @if (perm.isDeny) {\r\n <span class=\"fac-badge deny\">{{ 'files.share.denied' | translate }}</span>\r\n }\r\n @if (perm.isInherited) {\r\n <span class=\"fac-badge inherited\">{{ 'files.share.inherited' | translate }}</span>\r\n }\r\n </div>\r\n <div class=\"fac-perm-actions\">\r\n @if (!perm.isDeny) {\r\n <select\r\n class=\"fac-select sm\"\r\n [ngModel]=\"perm.level\"\r\n (ngModelChange)=\"onUpdateLevel(perm, $event)\"\r\n [disabled]=\"perm.isInherited === true\"\r\n >\r\n @for (opt of levelOptions; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.labelKey | translate }}</option>\r\n }\r\n </select>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"fac-icon-btn danger\"\r\n (click)=\"onRevokePermission(perm)\"\r\n [disabled]=\"perm.isInherited === true\"\r\n [title]=\"'files.share.revoke' | translate\"\r\n >\r\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".fac-overlay{position:fixed;inset:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:2000;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.fac-panel{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:12px;width:600px;max-width:min(600px,96vw);max-height:85vh;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 16px 48px #0006}.fac-header{display:flex;align-items:center;gap:10px;padding:16px 20px;border-bottom:1px solid var(--surface-border)}.fac-header h3{margin:0;font-size:16px;font-weight:600}.fac-target-name{flex:1;font-size:13px;color:var(--text-color-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fac-close{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;font-size:16px;padding:4px}.fac-close:hover{color:var(--text-color)}.fac-add-section{padding:16px 20px;border-bottom:1px solid var(--surface-border)}.fac-search-row{display:flex;gap:8px}.fac-chart-row{display:flex;flex-direction:column;gap:6px;margin-top:12px}.fac-chart-row .fac-select{width:100%}.fac-input{flex:1;background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 12px;color:inherit;font-size:13px;outline:none}.fac-input:focus{border-color:var(--primary-color, #e8732a)}.fac-select{background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 10px;color:inherit;font-size:13px;outline:none}.fac-select.sm{padding:4px 8px;font-size:12px}.fac-search-results{margin-top:8px;max-height:150px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fac-search-item{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;font-size:13px}.fac-search-item:hover{background:var(--surface-hover)}.fac-search-item i{color:var(--text-color-secondary)}.fac-email{color:var(--text-color-secondary);font-size:12px;margin-inline-start:auto}.fac-ou-section{margin-top:10px;max-height:220px;overflow-y:auto}.fac-ou-item{display:flex;align-items:center;gap:8px;padding:6px 12px;padding-inline-start:12px;cursor:pointer;font-size:13px;border-radius:6px}.fac-ou-item:hover{background:var(--surface-hover)}.fac-ou-item i{color:var(--text-color-secondary)}.fac-section-label{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--text-color-secondary);letter-spacing:.5px;margin-bottom:8px}.fac-toggle-row{display:flex;align-items:center;justify-content:space-between;margin-top:10px}.fac-link{background:none;border:none;color:var(--primary-color, #e8732a);cursor:pointer;font-size:12px;padding:0}.fac-link:hover{text-decoration:underline}.fac-checkbox-label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-color-secondary);cursor:pointer}.fac-checkbox-label input{accent-color:var(--primary-color, #e8732a)}.fac-perms-section{flex:1;overflow-y:auto;padding:16px 20px}.fac-loading,.fac-empty{text-align:center;padding:20px;color:var(--text-color-secondary);font-size:13px}.fac-perm-row{display:flex;align-items:center;justify-content:space-between;padding:8px 0;border-bottom:1px solid rgba(255,255,255,.05);gap:8px}.fac-perm-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.fac-perm-info i{color:var(--text-color-secondary);flex-shrink:0}.fac-perm-name{font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fac-badge{font-size:10px;padding:2px 6px;border-radius:8px;flex-shrink:0}.fac-badge.inherited{background:#ffffff1a;color:var(--text-color-secondary)}.fac-badge.deny{background:#ff3b302e;color:#ff3b30;text-transform:uppercase;font-weight:600;letter-spacing:.5px}.fac-perm-row-deny{background:#ff3b300f;border-inline-start:3px solid #ff3b30;padding-inline-start:8px;border-radius:6px}.fac-perm-row-deny .fac-perm-info i{color:#ff3b30}.fac-deny-toggle{color:#ff6b6b}.fac-deny-toggle i{color:#ff6b6b;font-size:11px;margin-inline-end:2px}.fac-deny-toggle input{accent-color:#ff3b30}.fac-role-section{margin-top:10px;display:flex;flex-direction:column;gap:6px}.fac-role-list{margin-top:6px;max-height:220px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fac-role-item{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;font-size:13px}.fac-role-item:hover{background:var(--surface-hover)}.fac-role-item i{color:var(--text-color-secondary)}.fac-role-app{margin-inline-start:auto;font-size:11px;color:var(--text-color-secondary);text-transform:uppercase;letter-spacing:.5px}.fac-perm-actions{display:flex;align-items:center;gap:6px;flex-shrink:0}.fac-icon-btn{background:#ffffff0f;border:none;border-radius:6px;width:28px;height:28px;display:flex;align-items:center;justify-content:center;color:inherit;cursor:pointer;font-size:12px}.fac-icon-btn:hover{background:#ffffff24}.fac-icon-btn.danger:hover{background:#ff3b3033;color:#ff3b30}.fac-icon-btn:disabled{opacity:.4;cursor:default}\n"] }]
3470
+ args: [{ selector: 'fly-share-panel', standalone: true, imports: [CommonModule, FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fac-overlay\" (click)=\"close.emit()\">\n <div class=\"fac-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"fac-header\">\n <h3>{{ titleKey | translate }}</h3>\n <span class=\"fac-target-name\">{{ targetName }}</span>\n <button\n type=\"button\"\n class=\"fac-close\"\n (click)=\"close.emit()\"\n [attr.aria-label]=\"'files.share.close' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <div class=\"fac-add-section\">\n <div class=\"fac-search-row\">\n <input\n type=\"text\"\n class=\"fac-input\"\n [(ngModel)]=\"searchQuery\"\n (input)=\"onSearchInput()\"\n [placeholder]=\"'files.share.search_placeholder' | translate\"\n [attr.aria-label]=\"'files.share.search_users' | translate\"\n />\n <select class=\"fac-select\" [(ngModel)]=\"newLevel\">\n @for (opt of levelOptions; track opt.value) {\n <option [value]=\"opt.value\">{{ opt.labelKey | translate }}</option>\n }\n </select>\n </div>\n\n @if (searchResults().length > 0) {\n <div class=\"fac-search-results\">\n @for (result of searchResults(); track result.id) {\n <div class=\"fac-search-item\" (click)=\"onGrantToUser(result)\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <span>{{ result.firstName }} {{ result.lastName }}</span>\n <span class=\"fac-email\">{{ result.email }}</span>\n </div>\n }\n </div>\n }\n\n @if (chartOptions().length > 0) {\n <div class=\"fac-chart-row\">\n <label for=\"fac-org-chart-select\" class=\"fac-section-label\">{{\n 'files.share.org_chart' | translate\n }}</label>\n <select\n id=\"fac-org-chart-select\"\n class=\"fac-select\"\n [ngModel]=\"selectedOrgChartId()\"\n (ngModelChange)=\"onOrgChartSelectChange($event)\">\n @for (opt of chartOptions(); track $index) {\n <option [ngValue]=\"opt.id\">{{ opt.name }}</option>\n }\n </select>\n </div>\n }\n\n @if (showOuPicker()) {\n <div class=\"fac-ou-section\">\n <div class=\"fac-section-label\">{{ 'files.share.share_with_ou' | translate }}</div>\n @for (ou of ouTree(); track ou.id) {\n <button\n type=\"button\"\n class=\"fac-ou-item\"\n [style.padding-inline-start.px]=\"ouIndentStartPx(ou)\"\n (click)=\"onGrantToOu(ou)\"\n [attr.aria-label]=\"('files.share.share_with_ou_named' | translate) + ' ' + ou.displayName\"\n >\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\n <span dir=\"auto\">{{ ou.displayName }}</span>\n </button>\n }\n </div>\n }\n\n @if (loadRoleOus && roleOus().length > 0) {\n <div class=\"fac-role-section\">\n <div class=\"fac-section-label\">{{ 'files.share.share_with_role' | translate }}</div>\n <input\n type=\"text\"\n class=\"fac-input\"\n [(ngModel)]=\"roleSearchQuery\"\n [placeholder]=\"'files.share.role_search_placeholder' | translate\"\n [attr.aria-label]=\"'files.share.search_roles' | translate\"\n [hidden]=\"!showRolePicker()\" />\n @if (showRolePicker()) {\n <div class=\"fac-role-list\">\n @for (role of filteredRoles(); track role.ouId) {\n <button\n type=\"button\"\n class=\"fac-role-item\"\n (click)=\"onGrantToRole(role)\"\n [attr.aria-label]=\"('files.share.share_with_role_named' | translate) + ' ' + role.displayName\">\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\n <span dir=\"auto\">{{ role.displayName }}</span>\n <span class=\"fac-role-app\">{{ role.appId }}</span>\n </button>\n }\n @if (filteredRoles().length === 0) {\n <div class=\"fac-empty\">{{ 'files.share.no_roles_match' | translate }}</div>\n }\n </div>\n }\n </div>\n }\n\n <div class=\"fac-toggle-row\">\n <button type=\"button\" class=\"fac-link\" (click)=\"showOuPicker.set(!showOuPicker())\">\n {{ showOuPicker() ? ('files.share.hide_ous' | translate) : ('files.share.show_ous' | translate) }}\n </button>\n @if (loadRoleOus && roleOus().length > 0) {\n <button type=\"button\" class=\"fac-link\" (click)=\"showRolePicker.set(!showRolePicker())\">\n {{ showRolePicker() ? ('files.share.hide_roles' | translate) : ('files.share.show_roles' | translate) }}\n </button>\n }\n @if (showApplyToChildren) {\n <label class=\"fac-checkbox-label\">\n <input type=\"checkbox\" [(ngModel)]=\"applyToChildren\" />\n {{ 'files.share.apply_children' | translate }}\n </label>\n }\n @if (supportsDeny) {\n <label class=\"fac-checkbox-label fac-deny-toggle\"\n [title]=\"'files.share.deny_help' | translate\">\n <input type=\"checkbox\" [(ngModel)]=\"addAsDeny\" />\n <i class=\"pi pi-ban\" aria-hidden=\"true\"></i>\n {{ 'files.share.add_as_deny' | translate }}\n </label>\n }\n </div>\n </div>\n\n <div class=\"fac-perms-section\">\n <div class=\"fac-section-label\">{{ 'files.share.current_permissions' | translate }}</div>\n @if (loading()) {\n <div class=\"fac-loading\"><i class=\"pi pi-spin pi-spinner\" aria-hidden=\"true\"></i></div>\n } @else if (permissions().length === 0) {\n <div class=\"fac-empty\">{{ 'files.share.no_permissions' | translate }}</div>\n } @else {\n @for (perm of permissions(); track perm.id) {\n <div class=\"fac-perm-row\" [class.fac-perm-row-deny]=\"perm.isDeny\">\n <div class=\"fac-perm-info\">\n <i [class]=\"getPermIcon(perm)\" aria-hidden=\"true\"></i>\n <span class=\"fac-perm-name\" dir=\"auto\">{{ getPermLabel(perm) }}</span>\n @if (perm.isDeny) {\n <span class=\"fac-badge deny\">{{ 'files.share.denied' | translate }}</span>\n }\n @if (perm.isInherited) {\n <span class=\"fac-badge inherited\">{{ 'files.share.inherited' | translate }}</span>\n }\n </div>\n <div class=\"fac-perm-actions\">\n @if (!perm.isDeny) {\n <select\n class=\"fac-select sm\"\n [ngModel]=\"perm.level\"\n (ngModelChange)=\"onUpdateLevel(perm, $event)\"\n [disabled]=\"perm.isInherited === true\"\n >\n @for (opt of levelOptions; track opt.value) {\n <option [value]=\"opt.value\">{{ opt.labelKey | translate }}</option>\n }\n </select>\n }\n <button\n type=\"button\"\n class=\"fac-icon-btn danger\"\n (click)=\"onRevokePermission(perm)\"\n [disabled]=\"perm.isInherited === true\"\n [title]=\"'files.share.revoke' | translate\"\n >\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n }\n }\n </div>\n </div>\n</div>\n", styles: [".fac-overlay{position:fixed;inset:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:2000;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.fac-panel{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:12px;width:600px;max-width:min(600px,96vw);max-height:85vh;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 16px 48px #0006}.fac-header{display:flex;align-items:center;gap:10px;padding:16px 20px;border-bottom:1px solid var(--surface-border)}.fac-header h3{margin:0;font-size:16px;font-weight:600}.fac-target-name{flex:1;font-size:13px;color:var(--text-color-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fac-close{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;font-size:16px;padding:4px}.fac-close:hover{color:var(--text-color)}.fac-add-section{padding:16px 20px;border-bottom:1px solid var(--surface-border)}.fac-search-row{display:flex;gap:8px}.fac-chart-row{display:flex;flex-direction:column;gap:6px;margin-top:12px}.fac-chart-row .fac-select{width:100%}.fac-input{flex:1;background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 12px;color:inherit;font-size:13px;outline:none}.fac-input:focus{border-color:var(--primary-color, #e8732a)}.fac-select{background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 10px;color:inherit;font-size:13px;outline:none}.fac-select.sm{padding:4px 8px;font-size:12px}.fac-search-results{margin-top:8px;max-height:150px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fac-search-item{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;font-size:13px}.fac-search-item:hover{background:var(--surface-hover)}.fac-search-item i{color:var(--text-color-secondary)}.fac-email{color:var(--text-color-secondary);font-size:12px;margin-inline-start:auto}.fac-ou-section{margin-top:10px;max-height:220px;overflow-y:auto}.fac-ou-item{display:flex;align-items:center;gap:8px;padding:6px 12px;padding-inline-start:12px;cursor:pointer;font-size:13px;border-radius:6px}.fac-ou-item:hover{background:var(--surface-hover)}.fac-ou-item i{color:var(--text-color-secondary)}.fac-section-label{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--text-color-secondary);letter-spacing:.5px;margin-bottom:8px}.fac-toggle-row{display:flex;align-items:center;justify-content:space-between;margin-top:10px}.fac-link{background:none;border:none;color:var(--primary-color, #e8732a);cursor:pointer;font-size:12px;padding:0}.fac-link:hover{text-decoration:underline}.fac-checkbox-label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-color-secondary);cursor:pointer}.fac-checkbox-label input{accent-color:var(--primary-color, #e8732a)}.fac-perms-section{flex:1;overflow-y:auto;padding:16px 20px}.fac-loading,.fac-empty{text-align:center;padding:20px;color:var(--text-color-secondary);font-size:13px}.fac-perm-row{display:flex;align-items:center;justify-content:space-between;padding:8px 0;border-bottom:1px solid rgba(255,255,255,.05);gap:8px}.fac-perm-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.fac-perm-info i{color:var(--text-color-secondary);flex-shrink:0}.fac-perm-name{font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fac-badge{font-size:10px;padding:2px 6px;border-radius:8px;flex-shrink:0}.fac-badge.inherited{background:#ffffff1a;color:var(--text-color-secondary)}.fac-badge.deny{background:#ff3b302e;color:#ff3b30;text-transform:uppercase;font-weight:600;letter-spacing:.5px}.fac-perm-row-deny{background:#ff3b300f;border-inline-start:3px solid #ff3b30;padding-inline-start:8px;border-radius:6px}.fac-perm-row-deny .fac-perm-info i{color:#ff3b30}.fac-deny-toggle{color:#ff6b6b}.fac-deny-toggle i{color:#ff6b6b;font-size:11px;margin-inline-end:2px}.fac-deny-toggle input{accent-color:#ff3b30}.fac-role-section{margin-top:10px;display:flex;flex-direction:column;gap:6px}.fac-role-list{margin-top:6px;max-height:220px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fac-role-item{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;font-size:13px}.fac-role-item:hover{background:var(--surface-hover)}.fac-role-item i{color:var(--text-color-secondary)}.fac-role-app{margin-inline-start:auto;font-size:11px;color:var(--text-color-secondary);text-transform:uppercase;letter-spacing:.5px}.fac-perm-actions{display:flex;align-items:center;gap:6px;flex-shrink:0}.fac-icon-btn{background:#ffffff0f;border:none;border-radius:6px;width:28px;height:28px;display:flex;align-items:center;justify-content:center;color:inherit;cursor:pointer;font-size:12px}.fac-icon-btn:hover{background:#ffffff24}.fac-icon-btn.danger:hover{background:#ff3b3033;color:#ff3b30}.fac-icon-btn:disabled{opacity:.4;cursor:default}\n"] }]
3469
3471
  }], propDecorators: { targetName: [{
3470
3472
  type: Input
3471
3473
  }], titleKey: [{
@@ -4111,7 +4113,7 @@ class AudienceBuilderComponent {
4111
4113
  useExisting: forwardRef(() => AudienceBuilderComponent),
4112
4114
  multi: true,
4113
4115
  },
4114
- ], usesOnChanges: true, ngImport: i0, template: "<div class=\"fab-root\">\r\n\r\n <!-- Includes section -->\r\n <div class=\"fab-bucket\">\r\n <div class=\"fab-bucket-header\">\r\n <div class=\"fab-section-label\" id=\"fab-includes-label\">{{ 'audience.includes' | translate }}</div>\r\n <button\r\n type=\"button\"\r\n class=\"fab-add-btn\"\r\n (click)=\"openPicker('includes')\"\r\n [attr.aria-expanded]=\"pickerOpen() && editTarget() === 'includes'\"\r\n [attr.aria-controls]=\"pickerOpen() && editTarget() === 'includes' ? 'fab-picker-region' : null\"\r\n >\r\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\r\n {{ 'audience.add_term' | translate }}\r\n </button>\r\n </div>\r\n\r\n @if (includes().length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.includes_empty' | translate }}</div>\r\n } @else {\r\n <ul class=\"fab-term-list\" aria-labelledby=\"fab-includes-label\">\r\n @for (term of includes(); track term) {\r\n <li class=\"fab-term\">\r\n <ng-container\r\n *ngTemplateOutlet=\"termCard; context: { $implicit: term, target: 'includes', index: $index }\">\r\n </ng-container>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </div>\r\n\r\n <!-- Excludes section -->\r\n @if (showExcludes) {\r\n <div class=\"fab-bucket fab-bucket-exclude\">\r\n <div class=\"fab-bucket-header\">\r\n <div class=\"fab-section-label\" id=\"fab-excludes-label\">{{ 'audience.excludes' | translate }}</div>\r\n <button\r\n type=\"button\"\r\n class=\"fab-add-btn\"\r\n (click)=\"openPicker('excludes')\"\r\n [attr.aria-expanded]=\"pickerOpen() && editTarget() === 'excludes'\"\r\n [attr.aria-controls]=\"pickerOpen() && editTarget() === 'excludes' ? 'fab-picker-region' : null\"\r\n >\r\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\r\n {{ 'audience.add_term' | translate }}\r\n </button>\r\n </div>\r\n\r\n @if (excludes().length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.excludes_empty' | translate }}</div>\r\n } @else {\r\n <ul class=\"fab-term-list\" aria-labelledby=\"fab-excludes-label\">\r\n @for (term of excludes(); track term) {\r\n <li class=\"fab-term\">\r\n <ng-container\r\n *ngTemplateOutlet=\"termCard; context: { $implicit: term, target: 'excludes', index: $index }\">\r\n </ng-container>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Inline picker (shared across includes/excludes; gated by pickerOpen) -->\r\n @if (pickerOpen()) {\r\n <div\r\n id=\"fab-picker-region\"\r\n class=\"fab-picker\"\r\n role=\"region\"\r\n [attr.aria-label]=\"(editTarget() === 'includes'\r\n ? ('audience.adding_to_includes' | translate)\r\n : ('audience.adding_to_excludes' | translate))\"\r\n >\r\n <div class=\"fab-picker-header\">\r\n <span class=\"fab-picker-target\">\r\n {{\r\n editTarget() === 'includes'\r\n ? ('audience.adding_to_includes' | translate)\r\n : ('audience.adding_to_excludes' | translate)\r\n }}\r\n </span>\r\n <button type=\"button\" class=\"fab-close\" (click)=\"closePicker()\" [attr.aria-label]=\"'audience.close' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n\r\n <!-- Kind tabs -->\r\n <div class=\"fab-kind-tabs\" role=\"tablist\">\r\n @for (kind of supportedKinds; track kind) {\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"fab-kind-tab\"\r\n [id]=\"'fab-tab-' + kind\"\r\n [class.active]=\"activeKind() === kind\"\r\n [attr.aria-selected]=\"activeKind() === kind\"\r\n [attr.aria-controls]=\"'fab-tabpanel-' + kind\"\r\n (click)=\"selectKind(kind)\"\r\n >\r\n <i [class]=\"kindIconClass(kind)\" aria-hidden=\"true\"></i>\r\n <span>{{ kindLocaleKey(kind) | translate }}</span>\r\n </button>\r\n }\r\n </div>\r\n\r\n @if (errorKey()) {\r\n <div class=\"fab-inline-error\" role=\"alert\">\r\n <i class=\"pi pi-exclamation-triangle\" aria-hidden=\"true\"></i>\r\n {{ errorKey()! | translate }}\r\n </div>\r\n }\r\n\r\n <!-- Per-kind picker bodies -->\r\n <div\r\n class=\"fab-picker-body\"\r\n role=\"tabpanel\"\r\n [id]=\"'fab-tabpanel-' + activeKind()\"\r\n [attr.aria-labelledby]=\"'fab-tab-' + activeKind()\"\r\n >\r\n @switch (activeKind()) {\r\n\r\n @case ('users') {\r\n <input\r\n type=\"text\"\r\n class=\"fab-input\"\r\n [ngModel]=\"userSearchQuery()\"\r\n (ngModelChange)=\"userSearchQuery.set($event); onUserSearchInput()\"\r\n [placeholder]=\"'audience.search_users_placeholder' | translate\"\r\n [attr.aria-label]=\"'audience.search_users_placeholder' | translate\"\r\n />\r\n @if (userSearchResults().length > 0) {\r\n <div class=\"fab-result-list\" role=\"list\">\r\n @for (u of userSearchResults(); track u.id) {\r\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickUser(u)\">\r\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\r\n <span>{{ u.firstName }} {{ u.lastName }}</span>\r\n <span class=\"fab-result-secondary\">{{ u.email }}</span>\r\n </button>\r\n }\r\n </div>\r\n } @else if (userSearchQuery().length >= 2) {\r\n <div class=\"fab-empty\">{{ 'audience.no_users_match' | translate }}</div>\r\n }\r\n }\r\n\r\n @case ('roles') {\r\n @if (loadRoleOus && roleOus().length > 0) {\r\n <input\r\n type=\"text\"\r\n class=\"fab-input\"\r\n [ngModel]=\"roleSearchQuery()\"\r\n (ngModelChange)=\"roleSearchQuery.set($event)\"\r\n [placeholder]=\"'audience.search_roles_placeholder' | translate\"\r\n [attr.aria-label]=\"'audience.search_roles_placeholder' | translate\"\r\n />\r\n <div class=\"fab-result-list\" role=\"list\">\r\n @for (role of filteredRoles(); track role.ouId) {\r\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickRole(role)\">\r\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\r\n <span>{{ role.displayName }}</span>\r\n <span class=\"fab-result-secondary\">{{ role.appId }}</span>\r\n </button>\r\n }\r\n @if (filteredRoles().length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.no_roles_match' | translate }}</div>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"fab-empty\">{{ 'audience.roles_unavailable' | translate }}</div>\r\n }\r\n }\r\n\r\n @case ('ou') {\r\n @if (chartOptions().length > 0) {\r\n <label for=\"fab-chart-select\" class=\"fab-mini-label\">\r\n {{ 'audience.org_chart' | translate }}\r\n </label>\r\n <select\r\n id=\"fab-chart-select\"\r\n class=\"fab-select\"\r\n [ngModel]=\"selectedChartId()\"\r\n (ngModelChange)=\"onChartChange($event)\"\r\n >\r\n @for (opt of chartOptions(); track $index) {\r\n <option [ngValue]=\"opt.id\">{{ opt.name }}</option>\r\n }\r\n </select>\r\n }\r\n <label class=\"fab-checkbox-label\">\r\n <input\r\n type=\"checkbox\"\r\n [ngModel]=\"ouIncludeDescendants()\"\r\n (ngModelChange)=\"ouIncludeDescendants.set($event)\"\r\n />\r\n {{ 'audience.include_descendants' | translate }}\r\n </label>\r\n @if (ouTree().length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.ou_tree_empty' | translate }}</div>\r\n } @else {\r\n <div class=\"fab-result-list fab-ou-tree\" role=\"list\">\r\n @for (ou of ouTree(); track ou.id) {\r\n <button\r\n type=\"button\"\r\n role=\"listitem\"\r\n class=\"fab-result-item\"\r\n [style.padding-inline-start.px]=\"ouIndentStartPx(ou)\"\r\n (click)=\"pickOu(ou)\"\r\n >\r\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\r\n <span>{{ ou.displayName }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @case ('app-everyone') {\r\n @if (appEveryoneOptions.length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.app_everyone_empty' | translate }}</div>\r\n } @else {\r\n <div class=\"fab-result-list\" role=\"list\">\r\n @for (app of appEveryoneOptions; track app.appId) {\r\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickAppEveryone(app.appId)\">\r\n <i class=\"pi pi-globe\" aria-hidden=\"true\"></i>\r\n <span>{{ app.displayName }}</span>\r\n <span class=\"fab-result-secondary\">{{ app.appId }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @case ('chart') {\r\n @if (chartTermOptions().length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.chart_options_empty' | translate }}</div>\r\n } @else {\r\n <div class=\"fab-result-list\" role=\"list\">\r\n @for (opt of chartTermOptions(); track opt.id) {\r\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickChart(opt.id)\">\r\n <i class=\"pi pi-share-alt\" aria-hidden=\"true\"></i>\r\n <span>{{ opt.name }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @case ('preset') {\r\n <div class=\"fab-result-list\" role=\"list\">\r\n @for (p of presetOptions; track p) {\r\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickPreset(p)\">\r\n <i class=\"pi pi-star\" aria-hidden=\"true\"></i>\r\n <span>{{ presetLocaleKey(p) | translate }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n</div>\r\n\r\n<!-- Reusable term card template, parameterised by target bucket + index for removal callbacks -->\r\n<ng-template #termCard let-term let-target=\"target\" let-index=\"index\">\r\n <div class=\"fab-term-card\" [class.fab-term-exclude]=\"target === 'excludes'\">\r\n\r\n @switch (term.kind) {\r\n @case ('users') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ 'audience.term_users' | translate: { count: term.userIds.length } }}\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n <div class=\"fab-term-chips\">\r\n @for (id of term.userIds; track id) {\r\n <span class=\"fab-chip\">\r\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\r\n <span>{{ id.substring(0, 8) }}\u2026</span>\r\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeUserId(target, index, id)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </span>\r\n }\r\n </div>\r\n }\r\n\r\n @case ('roles') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ 'audience.term_roles' | translate: { app: appLabel(term.appId), count: term.roleKeys.length } }}\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n <div class=\"fab-term-chips\">\r\n @for (k of term.roleKeys; track k) {\r\n <span class=\"fab-chip\">\r\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\r\n <span>{{ roleLabel(term.appId, k) }}</span>\r\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeRoleKey(target, index, k)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </span>\r\n }\r\n </div>\r\n }\r\n\r\n @case ('ou') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ 'audience.term_ous' | translate: { count: term.ouIds.length } }}\r\n @if (term.includeDescendants) {\r\n <span class=\"fab-badge\">{{ 'audience.descendants_badge' | translate }}</span>\r\n }\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n <div class=\"fab-term-chips\">\r\n @for (id of term.ouIds; track id) {\r\n <span class=\"fab-chip\">\r\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\r\n <span>{{ ouLabel(id) }}</span>\r\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeOuId(target, index, id)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </span>\r\n }\r\n </div>\r\n }\r\n\r\n @case ('app-everyone') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-globe\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ 'audience.term_app_everyone' | translate: { app: appLabel(term.appId) } }}\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n }\r\n\r\n @case ('chart') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-share-alt\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ 'audience.term_chart' | translate: { chart: chartLabel(term.chartId) } }}\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n }\r\n\r\n @case ('preset') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-star\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ presetLocaleKey(term.preset) | translate }}\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n }\r\n }\r\n </div>\r\n</ng-template>\r\n", styles: [".fab-root{display:flex;flex-direction:column;gap:14px;width:100%}.fab-bucket{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:10px;padding:12px 14px}.fab-bucket.fab-bucket-exclude{border-inline-start:3px solid rgba(255,59,48,.55)}.fab-bucket-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.fab-section-label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--text-color-secondary)}.fab-add-btn{display:inline-flex;align-items:center;gap:6px;background:var(--primary-color, #e8732a);color:#fff;border:none;border-radius:6px;padding:5px 10px;font-size:12px;cursor:pointer}.fab-add-btn:hover{filter:brightness(1.05)}.fab-add-btn i{font-size:11px}.fab-empty{text-align:center;padding:12px;color:var(--text-color-secondary);font-size:12px;font-style:italic}.fab-term-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.fab-term-card{background:#ffffff0a;border:1px solid rgba(255,255,255,.08);border-radius:8px;padding:8px 10px}.fab-term-card.fab-term-exclude{background:#ff3b300d;border-color:#ff3b302e}.fab-term-head{display:flex;align-items:center;gap:8px}.fab-term-head i:first-child{color:var(--text-color-secondary)}.fab-term-title{flex:1;font-size:13px;display:inline-flex;align-items:center;gap:6px}.fab-badge{font-size:10px;background:#ffffff1a;color:var(--text-color-secondary);padding:2px 6px;border-radius:8px;text-transform:uppercase;letter-spacing:.5px}.fab-term-chips{margin-top:6px;display:flex;flex-wrap:wrap;gap:4px}.fab-chip{display:inline-flex;align-items:center;gap:4px;background:#ffffff0f;border-radius:12px;padding:2px 4px 2px 8px;font-size:11px}.fab-chip i{font-size:10px;color:var(--text-color-secondary)}.fab-chip-x{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;padding:2px 4px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center}.fab-chip-x i{font-size:9px}.fab-chip-x:hover{background:#ff3b302e;color:#ff3b30}.fab-icon-btn{background:#ffffff0f;border:none;border-radius:6px;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;color:inherit;cursor:pointer;font-size:11px}.fab-icon-btn:hover{background:#ffffff24}.fab-icon-btn.danger:hover{background:#ff3b3033;color:#ff3b30}.fab-picker{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:10px;padding:12px 14px;display:flex;flex-direction:column;gap:10px;box-shadow:0 6px 18px #0000002e}.fab-picker-header{display:flex;align-items:center;justify-content:space-between}.fab-picker-target{font-size:12px;color:var(--text-color-secondary)}.fab-close{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;font-size:14px;padding:4px}.fab-close:hover{color:var(--text-color)}.fab-kind-tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--surface-border);padding-bottom:6px}.fab-kind-tab{background:transparent;border:1px solid transparent;border-radius:6px;padding:6px 10px;font-size:12px;color:var(--text-color-secondary);cursor:pointer;display:inline-flex;align-items:center;gap:6px}.fab-kind-tab i{font-size:11px}.fab-kind-tab:hover{background:var(--surface-hover);color:var(--text-color)}.fab-kind-tab.active{background:#e8732a1f;border-color:var(--primary-color, #e8732a);color:var(--text-color)}.fab-picker-body{display:flex;flex-direction:column;gap:8px}.fab-input,.fab-select{background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 12px;color:inherit;font-size:13px;outline:none}.fab-input:focus,.fab-select:focus{border-color:var(--primary-color, #e8732a)}.fab-mini-label{font-size:11px;color:var(--text-color-secondary)}.fab-result-list{max-height:200px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fab-result-list.fab-ou-tree{max-height:240px}button.fab-result-item{width:100%;background:transparent;border:none;color:inherit;font:inherit;text-align:start;appearance:none}.fab-result-item{display:flex;align-items:center;gap:8px;padding:6px 12px;cursor:pointer;font-size:13px}.fab-result-item:hover{background:var(--surface-hover)}.fab-result-item:focus-visible{outline:2px solid var(--primary-color, #e8732a);outline-offset:-2px}.fab-result-item i{color:var(--text-color-secondary)}.fab-result-secondary{color:var(--text-color-secondary);font-size:11px;margin-inline-start:auto;text-transform:uppercase;letter-spacing:.4px}.fab-checkbox-label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-color-secondary);cursor:pointer}.fab-checkbox-label input{accent-color:var(--primary-color, #e8732a)}.fab-inline-error{display:flex;align-items:center;gap:6px;background:#ff3b301a;color:#ff8a80;border-radius:6px;padding:6px 10px;font-size:12px}.fab-inline-error i{font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4116
+ ], usesOnChanges: true, ngImport: i0, template: "<div class=\"fab-root\">\n\n <!-- Includes section -->\n <div class=\"fab-bucket\">\n <div class=\"fab-bucket-header\">\n <div class=\"fab-section-label\" id=\"fab-includes-label\">{{ 'audience.includes' | translate }}</div>\n <button\n type=\"button\"\n class=\"fab-add-btn\"\n (click)=\"openPicker('includes')\"\n [attr.aria-expanded]=\"pickerOpen() && editTarget() === 'includes'\"\n [attr.aria-controls]=\"pickerOpen() && editTarget() === 'includes' ? 'fab-picker-region' : null\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n {{ 'audience.add_term' | translate }}\n </button>\n </div>\n\n @if (includes().length === 0) {\n <div class=\"fab-empty\">{{ 'audience.includes_empty' | translate }}</div>\n } @else {\n <ul class=\"fab-term-list\" aria-labelledby=\"fab-includes-label\">\n @for (term of includes(); track term) {\n <li class=\"fab-term\">\n <ng-container\n *ngTemplateOutlet=\"termCard; context: { $implicit: term, target: 'includes', index: $index }\">\n </ng-container>\n </li>\n }\n </ul>\n }\n </div>\n\n <!-- Excludes section -->\n @if (showExcludes) {\n <div class=\"fab-bucket fab-bucket-exclude\">\n <div class=\"fab-bucket-header\">\n <div class=\"fab-section-label\" id=\"fab-excludes-label\">{{ 'audience.excludes' | translate }}</div>\n <button\n type=\"button\"\n class=\"fab-add-btn\"\n (click)=\"openPicker('excludes')\"\n [attr.aria-expanded]=\"pickerOpen() && editTarget() === 'excludes'\"\n [attr.aria-controls]=\"pickerOpen() && editTarget() === 'excludes' ? 'fab-picker-region' : null\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n {{ 'audience.add_term' | translate }}\n </button>\n </div>\n\n @if (excludes().length === 0) {\n <div class=\"fab-empty\">{{ 'audience.excludes_empty' | translate }}</div>\n } @else {\n <ul class=\"fab-term-list\" aria-labelledby=\"fab-excludes-label\">\n @for (term of excludes(); track term) {\n <li class=\"fab-term\">\n <ng-container\n *ngTemplateOutlet=\"termCard; context: { $implicit: term, target: 'excludes', index: $index }\">\n </ng-container>\n </li>\n }\n </ul>\n }\n </div>\n }\n\n <!-- Inline picker (shared across includes/excludes; gated by pickerOpen) -->\n @if (pickerOpen()) {\n <div\n id=\"fab-picker-region\"\n class=\"fab-picker\"\n role=\"region\"\n [attr.aria-label]=\"(editTarget() === 'includes'\n ? ('audience.adding_to_includes' | translate)\n : ('audience.adding_to_excludes' | translate))\"\n >\n <div class=\"fab-picker-header\">\n <span class=\"fab-picker-target\">\n {{\n editTarget() === 'includes'\n ? ('audience.adding_to_includes' | translate)\n : ('audience.adding_to_excludes' | translate)\n }}\n </span>\n <button type=\"button\" class=\"fab-close\" (click)=\"closePicker()\" [attr.aria-label]=\"'audience.close' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <!-- Kind tabs -->\n <div class=\"fab-kind-tabs\" role=\"tablist\">\n @for (kind of supportedKinds; track kind) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"fab-kind-tab\"\n [id]=\"'fab-tab-' + kind\"\n [class.active]=\"activeKind() === kind\"\n [attr.aria-selected]=\"activeKind() === kind\"\n [attr.aria-controls]=\"'fab-tabpanel-' + kind\"\n (click)=\"selectKind(kind)\"\n >\n <i [class]=\"kindIconClass(kind)\" aria-hidden=\"true\"></i>\n <span>{{ kindLocaleKey(kind) | translate }}</span>\n </button>\n }\n </div>\n\n @if (errorKey()) {\n <div class=\"fab-inline-error\" role=\"alert\">\n <i class=\"pi pi-exclamation-triangle\" aria-hidden=\"true\"></i>\n {{ errorKey()! | translate }}\n </div>\n }\n\n <!-- Per-kind picker bodies -->\n <div\n class=\"fab-picker-body\"\n role=\"tabpanel\"\n [id]=\"'fab-tabpanel-' + activeKind()\"\n [attr.aria-labelledby]=\"'fab-tab-' + activeKind()\"\n >\n @switch (activeKind()) {\n\n @case ('users') {\n <input\n type=\"text\"\n class=\"fab-input\"\n [ngModel]=\"userSearchQuery()\"\n (ngModelChange)=\"userSearchQuery.set($event); onUserSearchInput()\"\n [placeholder]=\"'audience.search_users_placeholder' | translate\"\n [attr.aria-label]=\"'audience.search_users_placeholder' | translate\"\n />\n @if (userSearchResults().length > 0) {\n <div class=\"fab-result-list\" role=\"list\">\n @for (u of userSearchResults(); track u.id) {\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickUser(u)\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <span>{{ u.firstName }} {{ u.lastName }}</span>\n <span class=\"fab-result-secondary\">{{ u.email }}</span>\n </button>\n }\n </div>\n } @else if (userSearchQuery().length >= 2) {\n <div class=\"fab-empty\">{{ 'audience.no_users_match' | translate }}</div>\n }\n }\n\n @case ('roles') {\n @if (loadRoleOus && roleOus().length > 0) {\n <input\n type=\"text\"\n class=\"fab-input\"\n [ngModel]=\"roleSearchQuery()\"\n (ngModelChange)=\"roleSearchQuery.set($event)\"\n [placeholder]=\"'audience.search_roles_placeholder' | translate\"\n [attr.aria-label]=\"'audience.search_roles_placeholder' | translate\"\n />\n <div class=\"fab-result-list\" role=\"list\">\n @for (role of filteredRoles(); track role.ouId) {\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickRole(role)\">\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\n <span>{{ role.displayName }}</span>\n <span class=\"fab-result-secondary\">{{ role.appId }}</span>\n </button>\n }\n @if (filteredRoles().length === 0) {\n <div class=\"fab-empty\">{{ 'audience.no_roles_match' | translate }}</div>\n }\n </div>\n } @else {\n <div class=\"fab-empty\">{{ 'audience.roles_unavailable' | translate }}</div>\n }\n }\n\n @case ('ou') {\n @if (chartOptions().length > 0) {\n <label for=\"fab-chart-select\" class=\"fab-mini-label\">\n {{ 'audience.org_chart' | translate }}\n </label>\n <select\n id=\"fab-chart-select\"\n class=\"fab-select\"\n [ngModel]=\"selectedChartId()\"\n (ngModelChange)=\"onChartChange($event)\"\n >\n @for (opt of chartOptions(); track $index) {\n <option [ngValue]=\"opt.id\">{{ opt.name }}</option>\n }\n </select>\n }\n <label class=\"fab-checkbox-label\">\n <input\n type=\"checkbox\"\n [ngModel]=\"ouIncludeDescendants()\"\n (ngModelChange)=\"ouIncludeDescendants.set($event)\"\n />\n {{ 'audience.include_descendants' | translate }}\n </label>\n @if (ouTree().length === 0) {\n <div class=\"fab-empty\">{{ 'audience.ou_tree_empty' | translate }}</div>\n } @else {\n <div class=\"fab-result-list fab-ou-tree\" role=\"list\">\n @for (ou of ouTree(); track ou.id) {\n <button\n type=\"button\"\n role=\"listitem\"\n class=\"fab-result-item\"\n [style.padding-inline-start.px]=\"ouIndentStartPx(ou)\"\n (click)=\"pickOu(ou)\"\n >\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\n <span>{{ ou.displayName }}</span>\n </button>\n }\n </div>\n }\n }\n\n @case ('app-everyone') {\n @if (appEveryoneOptions.length === 0) {\n <div class=\"fab-empty\">{{ 'audience.app_everyone_empty' | translate }}</div>\n } @else {\n <div class=\"fab-result-list\" role=\"list\">\n @for (app of appEveryoneOptions; track app.appId) {\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickAppEveryone(app.appId)\">\n <i class=\"pi pi-globe\" aria-hidden=\"true\"></i>\n <span>{{ app.displayName }}</span>\n <span class=\"fab-result-secondary\">{{ app.appId }}</span>\n </button>\n }\n </div>\n }\n }\n\n @case ('chart') {\n @if (chartTermOptions().length === 0) {\n <div class=\"fab-empty\">{{ 'audience.chart_options_empty' | translate }}</div>\n } @else {\n <div class=\"fab-result-list\" role=\"list\">\n @for (opt of chartTermOptions(); track opt.id) {\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickChart(opt.id)\">\n <i class=\"pi pi-share-alt\" aria-hidden=\"true\"></i>\n <span>{{ opt.name }}</span>\n </button>\n }\n </div>\n }\n }\n\n @case ('preset') {\n <div class=\"fab-result-list\" role=\"list\">\n @for (p of presetOptions; track p) {\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickPreset(p)\">\n <i class=\"pi pi-star\" aria-hidden=\"true\"></i>\n <span>{{ presetLocaleKey(p) | translate }}</span>\n </button>\n }\n </div>\n }\n }\n </div>\n </div>\n }\n\n</div>\n\n<!-- Reusable term card template, parameterised by target bucket + index for removal callbacks -->\n<ng-template #termCard let-term let-target=\"target\" let-index=\"index\">\n <div class=\"fab-term-card\" [class.fab-term-exclude]=\"target === 'excludes'\">\n\n @switch (term.kind) {\n @case ('users') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ 'audience.term_users' | translate: { count: term.userIds.length } }}\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"fab-term-chips\">\n @for (id of term.userIds; track id) {\n <span class=\"fab-chip\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <span>{{ id.substring(0, 8) }}\u2026</span>\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeUserId(target, index, id)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n }\n\n @case ('roles') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ 'audience.term_roles' | translate: { app: appLabel(term.appId), count: term.roleKeys.length } }}\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"fab-term-chips\">\n @for (k of term.roleKeys; track k) {\n <span class=\"fab-chip\">\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\n <span>{{ roleLabel(term.appId, k) }}</span>\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeRoleKey(target, index, k)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n }\n\n @case ('ou') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ 'audience.term_ous' | translate: { count: term.ouIds.length } }}\n @if (term.includeDescendants) {\n <span class=\"fab-badge\">{{ 'audience.descendants_badge' | translate }}</span>\n }\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"fab-term-chips\">\n @for (id of term.ouIds; track id) {\n <span class=\"fab-chip\">\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\n <span>{{ ouLabel(id) }}</span>\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeOuId(target, index, id)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n }\n\n @case ('app-everyone') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-globe\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ 'audience.term_app_everyone' | translate: { app: appLabel(term.appId) } }}\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n @case ('chart') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-share-alt\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ 'audience.term_chart' | translate: { chart: chartLabel(term.chartId) } }}\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n @case ('preset') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-star\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ presetLocaleKey(term.preset) | translate }}\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n }\n </div>\n</ng-template>\n", styles: [".fab-root{display:flex;flex-direction:column;gap:14px;width:100%}.fab-bucket{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:10px;padding:12px 14px}.fab-bucket.fab-bucket-exclude{border-inline-start:3px solid rgba(255,59,48,.55)}.fab-bucket-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.fab-section-label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--text-color-secondary)}.fab-add-btn{display:inline-flex;align-items:center;gap:6px;background:var(--primary-color, #e8732a);color:#fff;border:none;border-radius:6px;padding:5px 10px;font-size:12px;cursor:pointer}.fab-add-btn:hover{filter:brightness(1.05)}.fab-add-btn i{font-size:11px}.fab-empty{text-align:center;padding:12px;color:var(--text-color-secondary);font-size:12px;font-style:italic}.fab-term-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.fab-term-card{background:#ffffff0a;border:1px solid rgba(255,255,255,.08);border-radius:8px;padding:8px 10px}.fab-term-card.fab-term-exclude{background:#ff3b300d;border-color:#ff3b302e}.fab-term-head{display:flex;align-items:center;gap:8px}.fab-term-head i:first-child{color:var(--text-color-secondary)}.fab-term-title{flex:1;font-size:13px;display:inline-flex;align-items:center;gap:6px}.fab-badge{font-size:10px;background:#ffffff1a;color:var(--text-color-secondary);padding:2px 6px;border-radius:8px;text-transform:uppercase;letter-spacing:.5px}.fab-term-chips{margin-top:6px;display:flex;flex-wrap:wrap;gap:4px}.fab-chip{display:inline-flex;align-items:center;gap:4px;background:#ffffff0f;border-radius:12px;padding:2px 4px 2px 8px;font-size:11px}.fab-chip i{font-size:10px;color:var(--text-color-secondary)}.fab-chip-x{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;padding:2px 4px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center}.fab-chip-x i{font-size:9px}.fab-chip-x:hover{background:#ff3b302e;color:#ff3b30}.fab-icon-btn{background:#ffffff0f;border:none;border-radius:6px;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;color:inherit;cursor:pointer;font-size:11px}.fab-icon-btn:hover{background:#ffffff24}.fab-icon-btn.danger:hover{background:#ff3b3033;color:#ff3b30}.fab-picker{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:10px;padding:12px 14px;display:flex;flex-direction:column;gap:10px;box-shadow:0 6px 18px #0000002e}.fab-picker-header{display:flex;align-items:center;justify-content:space-between}.fab-picker-target{font-size:12px;color:var(--text-color-secondary)}.fab-close{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;font-size:14px;padding:4px}.fab-close:hover{color:var(--text-color)}.fab-kind-tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--surface-border);padding-bottom:6px}.fab-kind-tab{background:transparent;border:1px solid transparent;border-radius:6px;padding:6px 10px;font-size:12px;color:var(--text-color-secondary);cursor:pointer;display:inline-flex;align-items:center;gap:6px}.fab-kind-tab i{font-size:11px}.fab-kind-tab:hover{background:var(--surface-hover);color:var(--text-color)}.fab-kind-tab.active{background:#e8732a1f;border-color:var(--primary-color, #e8732a);color:var(--text-color)}.fab-picker-body{display:flex;flex-direction:column;gap:8px}.fab-input,.fab-select{background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 12px;color:inherit;font-size:13px;outline:none}.fab-input:focus,.fab-select:focus{border-color:var(--primary-color, #e8732a)}.fab-mini-label{font-size:11px;color:var(--text-color-secondary)}.fab-result-list{max-height:200px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fab-result-list.fab-ou-tree{max-height:240px}button.fab-result-item{width:100%;background:transparent;border:none;color:inherit;font:inherit;text-align:start;appearance:none}.fab-result-item{display:flex;align-items:center;gap:8px;padding:6px 12px;cursor:pointer;font-size:13px}.fab-result-item:hover{background:var(--surface-hover)}.fab-result-item:focus-visible{outline:2px solid var(--primary-color, #e8732a);outline-offset:-2px}.fab-result-item i{color:var(--text-color-secondary)}.fab-result-secondary{color:var(--text-color-secondary);font-size:11px;margin-inline-start:auto;text-transform:uppercase;letter-spacing:.4px}.fab-checkbox-label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-color-secondary);cursor:pointer}.fab-checkbox-label input{accent-color:var(--primary-color, #e8732a)}.fab-inline-error{display:flex;align-items:center;gap:6px;background:#ff3b301a;color:#ff8a80;border-radius:6px;padding:6px 10px;font-size:12px}.fab-inline-error i{font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4115
4117
  }
4116
4118
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AudienceBuilderComponent, decorators: [{
4117
4119
  type: Component,
@@ -4126,7 +4128,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
4126
4128
  useExisting: forwardRef(() => AudienceBuilderComponent),
4127
4129
  multi: true,
4128
4130
  },
4129
- ], template: "<div class=\"fab-root\">\r\n\r\n <!-- Includes section -->\r\n <div class=\"fab-bucket\">\r\n <div class=\"fab-bucket-header\">\r\n <div class=\"fab-section-label\" id=\"fab-includes-label\">{{ 'audience.includes' | translate }}</div>\r\n <button\r\n type=\"button\"\r\n class=\"fab-add-btn\"\r\n (click)=\"openPicker('includes')\"\r\n [attr.aria-expanded]=\"pickerOpen() && editTarget() === 'includes'\"\r\n [attr.aria-controls]=\"pickerOpen() && editTarget() === 'includes' ? 'fab-picker-region' : null\"\r\n >\r\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\r\n {{ 'audience.add_term' | translate }}\r\n </button>\r\n </div>\r\n\r\n @if (includes().length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.includes_empty' | translate }}</div>\r\n } @else {\r\n <ul class=\"fab-term-list\" aria-labelledby=\"fab-includes-label\">\r\n @for (term of includes(); track term) {\r\n <li class=\"fab-term\">\r\n <ng-container\r\n *ngTemplateOutlet=\"termCard; context: { $implicit: term, target: 'includes', index: $index }\">\r\n </ng-container>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </div>\r\n\r\n <!-- Excludes section -->\r\n @if (showExcludes) {\r\n <div class=\"fab-bucket fab-bucket-exclude\">\r\n <div class=\"fab-bucket-header\">\r\n <div class=\"fab-section-label\" id=\"fab-excludes-label\">{{ 'audience.excludes' | translate }}</div>\r\n <button\r\n type=\"button\"\r\n class=\"fab-add-btn\"\r\n (click)=\"openPicker('excludes')\"\r\n [attr.aria-expanded]=\"pickerOpen() && editTarget() === 'excludes'\"\r\n [attr.aria-controls]=\"pickerOpen() && editTarget() === 'excludes' ? 'fab-picker-region' : null\"\r\n >\r\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\r\n {{ 'audience.add_term' | translate }}\r\n </button>\r\n </div>\r\n\r\n @if (excludes().length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.excludes_empty' | translate }}</div>\r\n } @else {\r\n <ul class=\"fab-term-list\" aria-labelledby=\"fab-excludes-label\">\r\n @for (term of excludes(); track term) {\r\n <li class=\"fab-term\">\r\n <ng-container\r\n *ngTemplateOutlet=\"termCard; context: { $implicit: term, target: 'excludes', index: $index }\">\r\n </ng-container>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Inline picker (shared across includes/excludes; gated by pickerOpen) -->\r\n @if (pickerOpen()) {\r\n <div\r\n id=\"fab-picker-region\"\r\n class=\"fab-picker\"\r\n role=\"region\"\r\n [attr.aria-label]=\"(editTarget() === 'includes'\r\n ? ('audience.adding_to_includes' | translate)\r\n : ('audience.adding_to_excludes' | translate))\"\r\n >\r\n <div class=\"fab-picker-header\">\r\n <span class=\"fab-picker-target\">\r\n {{\r\n editTarget() === 'includes'\r\n ? ('audience.adding_to_includes' | translate)\r\n : ('audience.adding_to_excludes' | translate)\r\n }}\r\n </span>\r\n <button type=\"button\" class=\"fab-close\" (click)=\"closePicker()\" [attr.aria-label]=\"'audience.close' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n\r\n <!-- Kind tabs -->\r\n <div class=\"fab-kind-tabs\" role=\"tablist\">\r\n @for (kind of supportedKinds; track kind) {\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n class=\"fab-kind-tab\"\r\n [id]=\"'fab-tab-' + kind\"\r\n [class.active]=\"activeKind() === kind\"\r\n [attr.aria-selected]=\"activeKind() === kind\"\r\n [attr.aria-controls]=\"'fab-tabpanel-' + kind\"\r\n (click)=\"selectKind(kind)\"\r\n >\r\n <i [class]=\"kindIconClass(kind)\" aria-hidden=\"true\"></i>\r\n <span>{{ kindLocaleKey(kind) | translate }}</span>\r\n </button>\r\n }\r\n </div>\r\n\r\n @if (errorKey()) {\r\n <div class=\"fab-inline-error\" role=\"alert\">\r\n <i class=\"pi pi-exclamation-triangle\" aria-hidden=\"true\"></i>\r\n {{ errorKey()! | translate }}\r\n </div>\r\n }\r\n\r\n <!-- Per-kind picker bodies -->\r\n <div\r\n class=\"fab-picker-body\"\r\n role=\"tabpanel\"\r\n [id]=\"'fab-tabpanel-' + activeKind()\"\r\n [attr.aria-labelledby]=\"'fab-tab-' + activeKind()\"\r\n >\r\n @switch (activeKind()) {\r\n\r\n @case ('users') {\r\n <input\r\n type=\"text\"\r\n class=\"fab-input\"\r\n [ngModel]=\"userSearchQuery()\"\r\n (ngModelChange)=\"userSearchQuery.set($event); onUserSearchInput()\"\r\n [placeholder]=\"'audience.search_users_placeholder' | translate\"\r\n [attr.aria-label]=\"'audience.search_users_placeholder' | translate\"\r\n />\r\n @if (userSearchResults().length > 0) {\r\n <div class=\"fab-result-list\" role=\"list\">\r\n @for (u of userSearchResults(); track u.id) {\r\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickUser(u)\">\r\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\r\n <span>{{ u.firstName }} {{ u.lastName }}</span>\r\n <span class=\"fab-result-secondary\">{{ u.email }}</span>\r\n </button>\r\n }\r\n </div>\r\n } @else if (userSearchQuery().length >= 2) {\r\n <div class=\"fab-empty\">{{ 'audience.no_users_match' | translate }}</div>\r\n }\r\n }\r\n\r\n @case ('roles') {\r\n @if (loadRoleOus && roleOus().length > 0) {\r\n <input\r\n type=\"text\"\r\n class=\"fab-input\"\r\n [ngModel]=\"roleSearchQuery()\"\r\n (ngModelChange)=\"roleSearchQuery.set($event)\"\r\n [placeholder]=\"'audience.search_roles_placeholder' | translate\"\r\n [attr.aria-label]=\"'audience.search_roles_placeholder' | translate\"\r\n />\r\n <div class=\"fab-result-list\" role=\"list\">\r\n @for (role of filteredRoles(); track role.ouId) {\r\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickRole(role)\">\r\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\r\n <span>{{ role.displayName }}</span>\r\n <span class=\"fab-result-secondary\">{{ role.appId }}</span>\r\n </button>\r\n }\r\n @if (filteredRoles().length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.no_roles_match' | translate }}</div>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"fab-empty\">{{ 'audience.roles_unavailable' | translate }}</div>\r\n }\r\n }\r\n\r\n @case ('ou') {\r\n @if (chartOptions().length > 0) {\r\n <label for=\"fab-chart-select\" class=\"fab-mini-label\">\r\n {{ 'audience.org_chart' | translate }}\r\n </label>\r\n <select\r\n id=\"fab-chart-select\"\r\n class=\"fab-select\"\r\n [ngModel]=\"selectedChartId()\"\r\n (ngModelChange)=\"onChartChange($event)\"\r\n >\r\n @for (opt of chartOptions(); track $index) {\r\n <option [ngValue]=\"opt.id\">{{ opt.name }}</option>\r\n }\r\n </select>\r\n }\r\n <label class=\"fab-checkbox-label\">\r\n <input\r\n type=\"checkbox\"\r\n [ngModel]=\"ouIncludeDescendants()\"\r\n (ngModelChange)=\"ouIncludeDescendants.set($event)\"\r\n />\r\n {{ 'audience.include_descendants' | translate }}\r\n </label>\r\n @if (ouTree().length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.ou_tree_empty' | translate }}</div>\r\n } @else {\r\n <div class=\"fab-result-list fab-ou-tree\" role=\"list\">\r\n @for (ou of ouTree(); track ou.id) {\r\n <button\r\n type=\"button\"\r\n role=\"listitem\"\r\n class=\"fab-result-item\"\r\n [style.padding-inline-start.px]=\"ouIndentStartPx(ou)\"\r\n (click)=\"pickOu(ou)\"\r\n >\r\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\r\n <span>{{ ou.displayName }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @case ('app-everyone') {\r\n @if (appEveryoneOptions.length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.app_everyone_empty' | translate }}</div>\r\n } @else {\r\n <div class=\"fab-result-list\" role=\"list\">\r\n @for (app of appEveryoneOptions; track app.appId) {\r\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickAppEveryone(app.appId)\">\r\n <i class=\"pi pi-globe\" aria-hidden=\"true\"></i>\r\n <span>{{ app.displayName }}</span>\r\n <span class=\"fab-result-secondary\">{{ app.appId }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @case ('chart') {\r\n @if (chartTermOptions().length === 0) {\r\n <div class=\"fab-empty\">{{ 'audience.chart_options_empty' | translate }}</div>\r\n } @else {\r\n <div class=\"fab-result-list\" role=\"list\">\r\n @for (opt of chartTermOptions(); track opt.id) {\r\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickChart(opt.id)\">\r\n <i class=\"pi pi-share-alt\" aria-hidden=\"true\"></i>\r\n <span>{{ opt.name }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @case ('preset') {\r\n <div class=\"fab-result-list\" role=\"list\">\r\n @for (p of presetOptions; track p) {\r\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickPreset(p)\">\r\n <i class=\"pi pi-star\" aria-hidden=\"true\"></i>\r\n <span>{{ presetLocaleKey(p) | translate }}</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n</div>\r\n\r\n<!-- Reusable term card template, parameterised by target bucket + index for removal callbacks -->\r\n<ng-template #termCard let-term let-target=\"target\" let-index=\"index\">\r\n <div class=\"fab-term-card\" [class.fab-term-exclude]=\"target === 'excludes'\">\r\n\r\n @switch (term.kind) {\r\n @case ('users') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ 'audience.term_users' | translate: { count: term.userIds.length } }}\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n <div class=\"fab-term-chips\">\r\n @for (id of term.userIds; track id) {\r\n <span class=\"fab-chip\">\r\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\r\n <span>{{ id.substring(0, 8) }}\u2026</span>\r\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeUserId(target, index, id)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </span>\r\n }\r\n </div>\r\n }\r\n\r\n @case ('roles') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ 'audience.term_roles' | translate: { app: appLabel(term.appId), count: term.roleKeys.length } }}\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n <div class=\"fab-term-chips\">\r\n @for (k of term.roleKeys; track k) {\r\n <span class=\"fab-chip\">\r\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\r\n <span>{{ roleLabel(term.appId, k) }}</span>\r\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeRoleKey(target, index, k)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </span>\r\n }\r\n </div>\r\n }\r\n\r\n @case ('ou') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ 'audience.term_ous' | translate: { count: term.ouIds.length } }}\r\n @if (term.includeDescendants) {\r\n <span class=\"fab-badge\">{{ 'audience.descendants_badge' | translate }}</span>\r\n }\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n <div class=\"fab-term-chips\">\r\n @for (id of term.ouIds; track id) {\r\n <span class=\"fab-chip\">\r\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\r\n <span>{{ ouLabel(id) }}</span>\r\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeOuId(target, index, id)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </span>\r\n }\r\n </div>\r\n }\r\n\r\n @case ('app-everyone') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-globe\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ 'audience.term_app_everyone' | translate: { app: appLabel(term.appId) } }}\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n }\r\n\r\n @case ('chart') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-share-alt\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ 'audience.term_chart' | translate: { chart: chartLabel(term.chartId) } }}\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n }\r\n\r\n @case ('preset') {\r\n <div class=\"fab-term-head\">\r\n <i class=\"pi pi-star\" aria-hidden=\"true\"></i>\r\n <span class=\"fab-term-title\">\r\n {{ presetLocaleKey(term.preset) | translate }}\r\n </span>\r\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\r\n [attr.aria-label]=\"'audience.remove_term' | translate\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n </div>\r\n }\r\n }\r\n </div>\r\n</ng-template>\r\n", styles: [".fab-root{display:flex;flex-direction:column;gap:14px;width:100%}.fab-bucket{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:10px;padding:12px 14px}.fab-bucket.fab-bucket-exclude{border-inline-start:3px solid rgba(255,59,48,.55)}.fab-bucket-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.fab-section-label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--text-color-secondary)}.fab-add-btn{display:inline-flex;align-items:center;gap:6px;background:var(--primary-color, #e8732a);color:#fff;border:none;border-radius:6px;padding:5px 10px;font-size:12px;cursor:pointer}.fab-add-btn:hover{filter:brightness(1.05)}.fab-add-btn i{font-size:11px}.fab-empty{text-align:center;padding:12px;color:var(--text-color-secondary);font-size:12px;font-style:italic}.fab-term-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.fab-term-card{background:#ffffff0a;border:1px solid rgba(255,255,255,.08);border-radius:8px;padding:8px 10px}.fab-term-card.fab-term-exclude{background:#ff3b300d;border-color:#ff3b302e}.fab-term-head{display:flex;align-items:center;gap:8px}.fab-term-head i:first-child{color:var(--text-color-secondary)}.fab-term-title{flex:1;font-size:13px;display:inline-flex;align-items:center;gap:6px}.fab-badge{font-size:10px;background:#ffffff1a;color:var(--text-color-secondary);padding:2px 6px;border-radius:8px;text-transform:uppercase;letter-spacing:.5px}.fab-term-chips{margin-top:6px;display:flex;flex-wrap:wrap;gap:4px}.fab-chip{display:inline-flex;align-items:center;gap:4px;background:#ffffff0f;border-radius:12px;padding:2px 4px 2px 8px;font-size:11px}.fab-chip i{font-size:10px;color:var(--text-color-secondary)}.fab-chip-x{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;padding:2px 4px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center}.fab-chip-x i{font-size:9px}.fab-chip-x:hover{background:#ff3b302e;color:#ff3b30}.fab-icon-btn{background:#ffffff0f;border:none;border-radius:6px;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;color:inherit;cursor:pointer;font-size:11px}.fab-icon-btn:hover{background:#ffffff24}.fab-icon-btn.danger:hover{background:#ff3b3033;color:#ff3b30}.fab-picker{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:10px;padding:12px 14px;display:flex;flex-direction:column;gap:10px;box-shadow:0 6px 18px #0000002e}.fab-picker-header{display:flex;align-items:center;justify-content:space-between}.fab-picker-target{font-size:12px;color:var(--text-color-secondary)}.fab-close{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;font-size:14px;padding:4px}.fab-close:hover{color:var(--text-color)}.fab-kind-tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--surface-border);padding-bottom:6px}.fab-kind-tab{background:transparent;border:1px solid transparent;border-radius:6px;padding:6px 10px;font-size:12px;color:var(--text-color-secondary);cursor:pointer;display:inline-flex;align-items:center;gap:6px}.fab-kind-tab i{font-size:11px}.fab-kind-tab:hover{background:var(--surface-hover);color:var(--text-color)}.fab-kind-tab.active{background:#e8732a1f;border-color:var(--primary-color, #e8732a);color:var(--text-color)}.fab-picker-body{display:flex;flex-direction:column;gap:8px}.fab-input,.fab-select{background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 12px;color:inherit;font-size:13px;outline:none}.fab-input:focus,.fab-select:focus{border-color:var(--primary-color, #e8732a)}.fab-mini-label{font-size:11px;color:var(--text-color-secondary)}.fab-result-list{max-height:200px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fab-result-list.fab-ou-tree{max-height:240px}button.fab-result-item{width:100%;background:transparent;border:none;color:inherit;font:inherit;text-align:start;appearance:none}.fab-result-item{display:flex;align-items:center;gap:8px;padding:6px 12px;cursor:pointer;font-size:13px}.fab-result-item:hover{background:var(--surface-hover)}.fab-result-item:focus-visible{outline:2px solid var(--primary-color, #e8732a);outline-offset:-2px}.fab-result-item i{color:var(--text-color-secondary)}.fab-result-secondary{color:var(--text-color-secondary);font-size:11px;margin-inline-start:auto;text-transform:uppercase;letter-spacing:.4px}.fab-checkbox-label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-color-secondary);cursor:pointer}.fab-checkbox-label input{accent-color:var(--primary-color, #e8732a)}.fab-inline-error{display:flex;align-items:center;gap:6px;background:#ff3b301a;color:#ff8a80;border-radius:6px;padding:6px 10px;font-size:12px}.fab-inline-error i{font-size:12px}\n"] }]
4131
+ ], template: "<div class=\"fab-root\">\n\n <!-- Includes section -->\n <div class=\"fab-bucket\">\n <div class=\"fab-bucket-header\">\n <div class=\"fab-section-label\" id=\"fab-includes-label\">{{ 'audience.includes' | translate }}</div>\n <button\n type=\"button\"\n class=\"fab-add-btn\"\n (click)=\"openPicker('includes')\"\n [attr.aria-expanded]=\"pickerOpen() && editTarget() === 'includes'\"\n [attr.aria-controls]=\"pickerOpen() && editTarget() === 'includes' ? 'fab-picker-region' : null\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n {{ 'audience.add_term' | translate }}\n </button>\n </div>\n\n @if (includes().length === 0) {\n <div class=\"fab-empty\">{{ 'audience.includes_empty' | translate }}</div>\n } @else {\n <ul class=\"fab-term-list\" aria-labelledby=\"fab-includes-label\">\n @for (term of includes(); track term) {\n <li class=\"fab-term\">\n <ng-container\n *ngTemplateOutlet=\"termCard; context: { $implicit: term, target: 'includes', index: $index }\">\n </ng-container>\n </li>\n }\n </ul>\n }\n </div>\n\n <!-- Excludes section -->\n @if (showExcludes) {\n <div class=\"fab-bucket fab-bucket-exclude\">\n <div class=\"fab-bucket-header\">\n <div class=\"fab-section-label\" id=\"fab-excludes-label\">{{ 'audience.excludes' | translate }}</div>\n <button\n type=\"button\"\n class=\"fab-add-btn\"\n (click)=\"openPicker('excludes')\"\n [attr.aria-expanded]=\"pickerOpen() && editTarget() === 'excludes'\"\n [attr.aria-controls]=\"pickerOpen() && editTarget() === 'excludes' ? 'fab-picker-region' : null\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n {{ 'audience.add_term' | translate }}\n </button>\n </div>\n\n @if (excludes().length === 0) {\n <div class=\"fab-empty\">{{ 'audience.excludes_empty' | translate }}</div>\n } @else {\n <ul class=\"fab-term-list\" aria-labelledby=\"fab-excludes-label\">\n @for (term of excludes(); track term) {\n <li class=\"fab-term\">\n <ng-container\n *ngTemplateOutlet=\"termCard; context: { $implicit: term, target: 'excludes', index: $index }\">\n </ng-container>\n </li>\n }\n </ul>\n }\n </div>\n }\n\n <!-- Inline picker (shared across includes/excludes; gated by pickerOpen) -->\n @if (pickerOpen()) {\n <div\n id=\"fab-picker-region\"\n class=\"fab-picker\"\n role=\"region\"\n [attr.aria-label]=\"(editTarget() === 'includes'\n ? ('audience.adding_to_includes' | translate)\n : ('audience.adding_to_excludes' | translate))\"\n >\n <div class=\"fab-picker-header\">\n <span class=\"fab-picker-target\">\n {{\n editTarget() === 'includes'\n ? ('audience.adding_to_includes' | translate)\n : ('audience.adding_to_excludes' | translate)\n }}\n </span>\n <button type=\"button\" class=\"fab-close\" (click)=\"closePicker()\" [attr.aria-label]=\"'audience.close' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <!-- Kind tabs -->\n <div class=\"fab-kind-tabs\" role=\"tablist\">\n @for (kind of supportedKinds; track kind) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"fab-kind-tab\"\n [id]=\"'fab-tab-' + kind\"\n [class.active]=\"activeKind() === kind\"\n [attr.aria-selected]=\"activeKind() === kind\"\n [attr.aria-controls]=\"'fab-tabpanel-' + kind\"\n (click)=\"selectKind(kind)\"\n >\n <i [class]=\"kindIconClass(kind)\" aria-hidden=\"true\"></i>\n <span>{{ kindLocaleKey(kind) | translate }}</span>\n </button>\n }\n </div>\n\n @if (errorKey()) {\n <div class=\"fab-inline-error\" role=\"alert\">\n <i class=\"pi pi-exclamation-triangle\" aria-hidden=\"true\"></i>\n {{ errorKey()! | translate }}\n </div>\n }\n\n <!-- Per-kind picker bodies -->\n <div\n class=\"fab-picker-body\"\n role=\"tabpanel\"\n [id]=\"'fab-tabpanel-' + activeKind()\"\n [attr.aria-labelledby]=\"'fab-tab-' + activeKind()\"\n >\n @switch (activeKind()) {\n\n @case ('users') {\n <input\n type=\"text\"\n class=\"fab-input\"\n [ngModel]=\"userSearchQuery()\"\n (ngModelChange)=\"userSearchQuery.set($event); onUserSearchInput()\"\n [placeholder]=\"'audience.search_users_placeholder' | translate\"\n [attr.aria-label]=\"'audience.search_users_placeholder' | translate\"\n />\n @if (userSearchResults().length > 0) {\n <div class=\"fab-result-list\" role=\"list\">\n @for (u of userSearchResults(); track u.id) {\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickUser(u)\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <span>{{ u.firstName }} {{ u.lastName }}</span>\n <span class=\"fab-result-secondary\">{{ u.email }}</span>\n </button>\n }\n </div>\n } @else if (userSearchQuery().length >= 2) {\n <div class=\"fab-empty\">{{ 'audience.no_users_match' | translate }}</div>\n }\n }\n\n @case ('roles') {\n @if (loadRoleOus && roleOus().length > 0) {\n <input\n type=\"text\"\n class=\"fab-input\"\n [ngModel]=\"roleSearchQuery()\"\n (ngModelChange)=\"roleSearchQuery.set($event)\"\n [placeholder]=\"'audience.search_roles_placeholder' | translate\"\n [attr.aria-label]=\"'audience.search_roles_placeholder' | translate\"\n />\n <div class=\"fab-result-list\" role=\"list\">\n @for (role of filteredRoles(); track role.ouId) {\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickRole(role)\">\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\n <span>{{ role.displayName }}</span>\n <span class=\"fab-result-secondary\">{{ role.appId }}</span>\n </button>\n }\n @if (filteredRoles().length === 0) {\n <div class=\"fab-empty\">{{ 'audience.no_roles_match' | translate }}</div>\n }\n </div>\n } @else {\n <div class=\"fab-empty\">{{ 'audience.roles_unavailable' | translate }}</div>\n }\n }\n\n @case ('ou') {\n @if (chartOptions().length > 0) {\n <label for=\"fab-chart-select\" class=\"fab-mini-label\">\n {{ 'audience.org_chart' | translate }}\n </label>\n <select\n id=\"fab-chart-select\"\n class=\"fab-select\"\n [ngModel]=\"selectedChartId()\"\n (ngModelChange)=\"onChartChange($event)\"\n >\n @for (opt of chartOptions(); track $index) {\n <option [ngValue]=\"opt.id\">{{ opt.name }}</option>\n }\n </select>\n }\n <label class=\"fab-checkbox-label\">\n <input\n type=\"checkbox\"\n [ngModel]=\"ouIncludeDescendants()\"\n (ngModelChange)=\"ouIncludeDescendants.set($event)\"\n />\n {{ 'audience.include_descendants' | translate }}\n </label>\n @if (ouTree().length === 0) {\n <div class=\"fab-empty\">{{ 'audience.ou_tree_empty' | translate }}</div>\n } @else {\n <div class=\"fab-result-list fab-ou-tree\" role=\"list\">\n @for (ou of ouTree(); track ou.id) {\n <button\n type=\"button\"\n role=\"listitem\"\n class=\"fab-result-item\"\n [style.padding-inline-start.px]=\"ouIndentStartPx(ou)\"\n (click)=\"pickOu(ou)\"\n >\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\n <span>{{ ou.displayName }}</span>\n </button>\n }\n </div>\n }\n }\n\n @case ('app-everyone') {\n @if (appEveryoneOptions.length === 0) {\n <div class=\"fab-empty\">{{ 'audience.app_everyone_empty' | translate }}</div>\n } @else {\n <div class=\"fab-result-list\" role=\"list\">\n @for (app of appEveryoneOptions; track app.appId) {\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickAppEveryone(app.appId)\">\n <i class=\"pi pi-globe\" aria-hidden=\"true\"></i>\n <span>{{ app.displayName }}</span>\n <span class=\"fab-result-secondary\">{{ app.appId }}</span>\n </button>\n }\n </div>\n }\n }\n\n @case ('chart') {\n @if (chartTermOptions().length === 0) {\n <div class=\"fab-empty\">{{ 'audience.chart_options_empty' | translate }}</div>\n } @else {\n <div class=\"fab-result-list\" role=\"list\">\n @for (opt of chartTermOptions(); track opt.id) {\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickChart(opt.id)\">\n <i class=\"pi pi-share-alt\" aria-hidden=\"true\"></i>\n <span>{{ opt.name }}</span>\n </button>\n }\n </div>\n }\n }\n\n @case ('preset') {\n <div class=\"fab-result-list\" role=\"list\">\n @for (p of presetOptions; track p) {\n <button type=\"button\" role=\"listitem\" class=\"fab-result-item\" (click)=\"pickPreset(p)\">\n <i class=\"pi pi-star\" aria-hidden=\"true\"></i>\n <span>{{ presetLocaleKey(p) | translate }}</span>\n </button>\n }\n </div>\n }\n }\n </div>\n </div>\n }\n\n</div>\n\n<!-- Reusable term card template, parameterised by target bucket + index for removal callbacks -->\n<ng-template #termCard let-term let-target=\"target\" let-index=\"index\">\n <div class=\"fab-term-card\" [class.fab-term-exclude]=\"target === 'excludes'\">\n\n @switch (term.kind) {\n @case ('users') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ 'audience.term_users' | translate: { count: term.userIds.length } }}\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"fab-term-chips\">\n @for (id of term.userIds; track id) {\n <span class=\"fab-chip\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <span>{{ id.substring(0, 8) }}\u2026</span>\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeUserId(target, index, id)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n }\n\n @case ('roles') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ 'audience.term_roles' | translate: { app: appLabel(term.appId), count: term.roleKeys.length } }}\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"fab-term-chips\">\n @for (k of term.roleKeys; track k) {\n <span class=\"fab-chip\">\n <i class=\"pi pi-id-card\" aria-hidden=\"true\"></i>\n <span>{{ roleLabel(term.appId, k) }}</span>\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeRoleKey(target, index, k)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n }\n\n @case ('ou') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ 'audience.term_ous' | translate: { count: term.ouIds.length } }}\n @if (term.includeDescendants) {\n <span class=\"fab-badge\">{{ 'audience.descendants_badge' | translate }}</span>\n }\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"fab-term-chips\">\n @for (id of term.ouIds; track id) {\n <span class=\"fab-chip\">\n <i class=\"pi pi-sitemap\" aria-hidden=\"true\"></i>\n <span>{{ ouLabel(id) }}</span>\n <button type=\"button\" class=\"fab-chip-x\" (click)=\"removeOuId(target, index, id)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n </div>\n }\n\n @case ('app-everyone') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-globe\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ 'audience.term_app_everyone' | translate: { app: appLabel(term.appId) } }}\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n @case ('chart') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-share-alt\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ 'audience.term_chart' | translate: { chart: chartLabel(term.chartId) } }}\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n @case ('preset') {\n <div class=\"fab-term-head\">\n <i class=\"pi pi-star\" aria-hidden=\"true\"></i>\n <span class=\"fab-term-title\">\n {{ presetLocaleKey(term.preset) | translate }}\n </span>\n <button type=\"button\" class=\"fab-icon-btn danger\" (click)=\"removeTerm(target, index)\"\n [attr.aria-label]=\"'audience.remove_term' | translate\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n }\n </div>\n</ng-template>\n", styles: [".fab-root{display:flex;flex-direction:column;gap:14px;width:100%}.fab-bucket{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:10px;padding:12px 14px}.fab-bucket.fab-bucket-exclude{border-inline-start:3px solid rgba(255,59,48,.55)}.fab-bucket-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.fab-section-label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--text-color-secondary)}.fab-add-btn{display:inline-flex;align-items:center;gap:6px;background:var(--primary-color, #e8732a);color:#fff;border:none;border-radius:6px;padding:5px 10px;font-size:12px;cursor:pointer}.fab-add-btn:hover{filter:brightness(1.05)}.fab-add-btn i{font-size:11px}.fab-empty{text-align:center;padding:12px;color:var(--text-color-secondary);font-size:12px;font-style:italic}.fab-term-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.fab-term-card{background:#ffffff0a;border:1px solid rgba(255,255,255,.08);border-radius:8px;padding:8px 10px}.fab-term-card.fab-term-exclude{background:#ff3b300d;border-color:#ff3b302e}.fab-term-head{display:flex;align-items:center;gap:8px}.fab-term-head i:first-child{color:var(--text-color-secondary)}.fab-term-title{flex:1;font-size:13px;display:inline-flex;align-items:center;gap:6px}.fab-badge{font-size:10px;background:#ffffff1a;color:var(--text-color-secondary);padding:2px 6px;border-radius:8px;text-transform:uppercase;letter-spacing:.5px}.fab-term-chips{margin-top:6px;display:flex;flex-wrap:wrap;gap:4px}.fab-chip{display:inline-flex;align-items:center;gap:4px;background:#ffffff0f;border-radius:12px;padding:2px 4px 2px 8px;font-size:11px}.fab-chip i{font-size:10px;color:var(--text-color-secondary)}.fab-chip-x{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;padding:2px 4px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center}.fab-chip-x i{font-size:9px}.fab-chip-x:hover{background:#ff3b302e;color:#ff3b30}.fab-icon-btn{background:#ffffff0f;border:none;border-radius:6px;width:24px;height:24px;display:inline-flex;align-items:center;justify-content:center;color:inherit;cursor:pointer;font-size:11px}.fab-icon-btn:hover{background:#ffffff24}.fab-icon-btn.danger:hover{background:#ff3b3033;color:#ff3b30}.fab-picker{background:var(--surface-card, #1e1e1e);border:1px solid var(--surface-border);border-radius:10px;padding:12px 14px;display:flex;flex-direction:column;gap:10px;box-shadow:0 6px 18px #0000002e}.fab-picker-header{display:flex;align-items:center;justify-content:space-between}.fab-picker-target{font-size:12px;color:var(--text-color-secondary)}.fab-close{background:none;border:none;color:var(--text-color-secondary);cursor:pointer;font-size:14px;padding:4px}.fab-close:hover{color:var(--text-color)}.fab-kind-tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--surface-border);padding-bottom:6px}.fab-kind-tab{background:transparent;border:1px solid transparent;border-radius:6px;padding:6px 10px;font-size:12px;color:var(--text-color-secondary);cursor:pointer;display:inline-flex;align-items:center;gap:6px}.fab-kind-tab i{font-size:11px}.fab-kind-tab:hover{background:var(--surface-hover);color:var(--text-color)}.fab-kind-tab.active{background:#e8732a1f;border-color:var(--primary-color, #e8732a);color:var(--text-color)}.fab-picker-body{display:flex;flex-direction:column;gap:8px}.fab-input,.fab-select{background:#ffffff14;border:1px solid rgba(255,255,255,.15);border-radius:8px;padding:8px 12px;color:inherit;font-size:13px;outline:none}.fab-input:focus,.fab-select:focus{border-color:var(--primary-color, #e8732a)}.fab-mini-label{font-size:11px;color:var(--text-color-secondary)}.fab-result-list{max-height:200px;overflow-y:auto;border:1px solid var(--surface-border);border-radius:8px}.fab-result-list.fab-ou-tree{max-height:240px}button.fab-result-item{width:100%;background:transparent;border:none;color:inherit;font:inherit;text-align:start;appearance:none}.fab-result-item{display:flex;align-items:center;gap:8px;padding:6px 12px;cursor:pointer;font-size:13px}.fab-result-item:hover{background:var(--surface-hover)}.fab-result-item:focus-visible{outline:2px solid var(--primary-color, #e8732a);outline-offset:-2px}.fab-result-item i{color:var(--text-color-secondary)}.fab-result-secondary{color:var(--text-color-secondary);font-size:11px;margin-inline-start:auto;text-transform:uppercase;letter-spacing:.4px}.fab-checkbox-label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-color-secondary);cursor:pointer}.fab-checkbox-label input{accent-color:var(--primary-color, #e8732a)}.fab-inline-error{display:flex;align-items:center;gap:6px;background:#ff3b301a;color:#ff8a80;border-radius:6px;padding:6px 10px;font-size:12px}.fab-inline-error i{font-size:12px}\n"] }]
4130
4132
  }], propDecorators: { value: [{
4131
4133
  type: Input
4132
4134
  }], showExcludes: [{
@@ -4176,6 +4178,159 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
4176
4178
  args: [{ selector: 'fly-block-ui', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (active()) {\n <div\n class=\"fly-block-ui\"\n role=\"status\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n [attr.aria-label]=\"resolvedMessageKey() | translate\">\n <div class=\"fly-block-ui__card\">\n <i class=\"pi pi-spin pi-spinner fly-block-ui__spinner\" aria-hidden=\"true\"></i>\n <span class=\"fly-block-ui__text\">{{ resolvedMessageKey() | translate }}</span>\n </div>\n </div>\n}\n", styles: [":host{display:contents}.fly-block-ui{position:absolute;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--surface-ground, #0c0c12) 58%,transparent);-webkit-backdrop-filter:blur(6px) saturate(120%);backdrop-filter:blur(6px) saturate(120%)}.fly-block-ui__card{display:flex;flex-direction:column;align-items:center;gap:12px;padding:24px 36px;border-radius:12px;background:var(--glass-bg, rgba(255, 255, 255, .14));border:1px solid var(--glass-border, rgba(255, 255, 255, .22));box-shadow:0 8px 32px #0000002e}.fly-block-ui__spinner{font-size:2rem;color:var(--primary-color)}.fly-block-ui__text{font-size:.875rem;color:var(--text-color-secondary)}\n"] }]
4177
4179
  }], propDecorators: { active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: true }] }], messageKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageKey", required: false }] }] } });
4178
4180
 
4181
+ /**
4182
+ * `fly-drawer` — the ONE overlay-drawer primitive for FlyOS apps.
4183
+ *
4184
+ * Replaces every hand-rolled centered modal / `*-backdrop` + `modal-panel`
4185
+ * scaffold. A slide-in panel pinned to the window's inline-end edge over a
4186
+ * scrim, dismissing away — drops onto ANY app layout (sidebar+main, editor,
4187
+ * list) with no restructuring.
4188
+ *
4189
+ * ## Windowed rendering (important)
4190
+ * Desktop apps are windowed, so the drawer renders **in-place** — the scrim is
4191
+ * `position: absolute; inset: 0` and overlays the nearest positioned ancestor,
4192
+ * NOT a body/CDK portal (a body-level overlay would escape the app window and
4193
+ * break the shell's window stacking). **The consuming app's root container must
4194
+ * be `position: relative`** (add it where missing) so the scrim is clipped to
4195
+ * the window.
4196
+ *
4197
+ * ## Controlled
4198
+ * `open` is a controlled input — bind it to a signal and flip it in the
4199
+ * `(closed)` / `(openChange)` handlers. The drawer never closes itself; it only
4200
+ * requests closure (scrim / Escape / ✕) by emitting.
4201
+ *
4202
+ * ## Owns (so apps stop reimplementing it)
4203
+ * slide in/out (honours `prefers-reduced-motion`), focus trap + focus restore,
4204
+ * Escape + scrim dismiss (both gated), scroll-lock of the host content, ARIA
4205
+ * (`role=dialog` + `aria-modal` + labelledby/label), logical CSS (RTL-safe),
4206
+ * dark theme.
4207
+ *
4208
+ * ## Slots
4209
+ * - `[flyDrawerHeader]` — optional custom header (else `heading` + close ✕).
4210
+ * - default — body (scrolls).
4211
+ * - `[flyDrawerFooter]` — optional sticky footer (action bar).
4212
+ */
4213
+ class FlyDrawerComponent {
4214
+ host = inject((ElementRef));
4215
+ destroyRef = inject(DestroyRef);
4216
+ /** Drives mount + slide. Controlled by the parent. */
4217
+ open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
4218
+ /** Width tier → inline-size (sm 360 / md 480 / lg 640 / xl min(960px, 94%)). */
4219
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
4220
+ /** Convenience title shown in the default header (ignored if `[flyDrawerHeader]` is projected). Treated as an i18n key. */
4221
+ heading = input(null, ...(ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []));
4222
+ /** Edge to pin to. `end` (default) slides from inline-end; RTL flips it. */
4223
+ side = input('end', ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
4224
+ /** Close when the scrim is clicked. */
4225
+ dismissOnScrim = input(true, ...(ngDevMode ? [{ debugName: "dismissOnScrim" }] : /* istanbul ignore next */ []));
4226
+ /** Close on Escape. */
4227
+ dismissOnEscape = input(true, ...(ngDevMode ? [{ debugName: "dismissOnEscape" }] : /* istanbul ignore next */ []));
4228
+ /** Accessible label when no `heading` / projected header title is available. Treated as an i18n key. */
4229
+ ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
4230
+ /** Hide the built-in close ✕ in the default header (e.g. a mandatory step). */
4231
+ hideCloseButton = input(false, ...(ngDevMode ? [{ debugName: "hideCloseButton" }] : /* istanbul ignore next */ []));
4232
+ /** Emitted when the user requests dismissal (scrim / Escape / ✕). */
4233
+ closed = output();
4234
+ /** Two-way friendly: emits `false` on a dismissal request. */
4235
+ openChange = output();
4236
+ /** Whether the panel is mounted (true while open AND during the slide-out). */
4237
+ rendered = signal(false, ...(ngDevMode ? [{ debugName: "rendered" }] : /* istanbul ignore next */ []));
4238
+ /** Whether the panel is in its entered (slid-in) state. */
4239
+ entered = signal(false, ...(ngDevMode ? [{ debugName: "entered" }] : /* istanbul ignore next */ []));
4240
+ headingId = 'fly-drawer-heading';
4241
+ labelledBy = computed(() => (this.heading() ? this.headingId : null), ...(ngDevMode ? [{ debugName: "labelledBy" }] : /* istanbul ignore next */ []));
4242
+ /** Element focused before the drawer opened, restored on close. */
4243
+ previouslyFocused = null;
4244
+ /** Parent element whose overflow we lock while open. */
4245
+ scrollLockTarget = null;
4246
+ prevOverflow = '';
4247
+ constructor() {
4248
+ effect(() => {
4249
+ if (this.open())
4250
+ this.onOpen();
4251
+ else
4252
+ this.onClose();
4253
+ });
4254
+ this.destroyRef.onDestroy(() => this.releaseScrollLock());
4255
+ }
4256
+ onOpen() {
4257
+ if (this.rendered())
4258
+ return;
4259
+ this.previouslyFocused =
4260
+ document.activeElement instanceof HTMLElement ? document.activeElement : null;
4261
+ this.lockScroll();
4262
+ this.rendered.set(true);
4263
+ // Next frame → flip to entered so the CSS transition runs.
4264
+ requestAnimationFrame(() => requestAnimationFrame(() => this.entered.set(true)));
4265
+ }
4266
+ onClose() {
4267
+ if (!this.rendered())
4268
+ return;
4269
+ this.entered.set(false);
4270
+ this.releaseScrollLock();
4271
+ this.restoreFocus();
4272
+ // Unmount on transitionend; fallback timer covers reduced-motion / a missed
4273
+ // event so the (still pointer-grabbing) scrim can never linger.
4274
+ setTimeout(() => {
4275
+ if (!this.open())
4276
+ this.rendered.set(false);
4277
+ }, 320);
4278
+ }
4279
+ /** Remove the panel from the DOM once the slide-out transition completes. */
4280
+ onPanelTransitionEnd() {
4281
+ if (!this.entered() && !this.open())
4282
+ this.rendered.set(false);
4283
+ }
4284
+ onEscape() {
4285
+ if (this.open() && this.dismissOnEscape())
4286
+ this.requestClose();
4287
+ }
4288
+ onScrimClick() {
4289
+ if (this.dismissOnScrim())
4290
+ this.requestClose();
4291
+ }
4292
+ requestClose() {
4293
+ this.openChange.emit(false);
4294
+ this.closed.emit();
4295
+ }
4296
+ lockScroll() {
4297
+ // Lock the nearest positioned ancestor (the app window root) — the same box
4298
+ // the absolutely-positioned scrim clips to — not the immediate DOM parent
4299
+ // (which may be a `display:contents` dialog wrapper).
4300
+ const target = this.host.nativeElement.offsetParent ??
4301
+ this.host.nativeElement.parentElement;
4302
+ if (!target)
4303
+ return;
4304
+ this.scrollLockTarget = target;
4305
+ this.prevOverflow = target.style.overflow;
4306
+ target.style.overflow = 'hidden';
4307
+ }
4308
+ releaseScrollLock() {
4309
+ if (!this.scrollLockTarget)
4310
+ return;
4311
+ this.scrollLockTarget.style.overflow = this.prevOverflow;
4312
+ this.scrollLockTarget = null;
4313
+ this.prevOverflow = '';
4314
+ }
4315
+ restoreFocus() {
4316
+ const el = this.previouslyFocused;
4317
+ this.previouslyFocused = null;
4318
+ if (el && document.contains(el)) {
4319
+ // Defer so focus lands after the panel is removed from the a11y tree.
4320
+ requestAnimationFrame(() => el.focus());
4321
+ }
4322
+ }
4323
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FlyDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4324
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: FlyDrawerComponent, isStandalone: true, selector: "fly-drawer", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, heading: { classPropertyName: "heading", publicName: "heading", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, dismissOnScrim: { classPropertyName: "dismissOnScrim", publicName: "dismissOnScrim", isSignal: true, isRequired: false, transformFunction: null }, dismissOnEscape: { classPropertyName: "dismissOnEscape", publicName: "dismissOnEscape", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hideCloseButton: { classPropertyName: "hideCloseButton", publicName: "hideCloseButton", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", openChange: "openChange" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "<!--\n Windowed overlay drawer. Renders only while mounted (open or sliding out).\n Scrim + panel are absolutely positioned within the nearest positioned\n ancestor (the consuming app root must be position:relative).\n-->\n@if (rendered()) {\n <div\n class=\"fly-drawer__scrim\"\n [class.fly-drawer__scrim--in]=\"entered()\"\n (click)=\"onScrimClick()\"\n aria-hidden=\"true\"\n ></div>\n\n <div\n class=\"fly-drawer__panel\"\n [class.fly-drawer__panel--in]=\"entered()\"\n [class]=\"'fly-drawer__panel--' + size() + ' fly-drawer__panel--side-' + side()\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-label]=\"!labelledBy() && ariaLabel() ? (ariaLabel()! | translate) : null\"\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"true\"\n (transitionend)=\"onPanelTransitionEnd()\"\n >\n <!-- Header: custom slot, else heading + close \u2715. -->\n <ng-content select=\"[flyDrawerHeader]\">\n @if (heading()) {\n <header class=\"fly-drawer__header\">\n <h2 class=\"fly-drawer__title\" [id]=\"headingId\">{{ heading()! | translate }}</h2>\n @if (!hideCloseButton()) {\n <button\n type=\"button\"\n class=\"fly-drawer__close\"\n (click)=\"requestClose()\"\n [attr.aria-label]=\"'common.action.close' | translate\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n }\n </ng-content>\n\n <div class=\"fly-drawer__body\">\n <ng-content></ng-content>\n </div>\n\n <ng-content select=\"[flyDrawerFooter]\"></ng-content>\n </div>\n}\n", styles: [":host{position:absolute;inset:0;z-index:60;pointer-events:none}.fly-drawer__scrim{position:absolute;inset:0;pointer-events:auto;background:#00000061;opacity:0;transition:opacity .24s ease}.fly-drawer__scrim--in{opacity:1}.fly-drawer__panel{position:absolute;inset-block:0;inset-inline-end:0;pointer-events:auto;display:flex;flex-direction:column;min-block-size:0;inline-size:min(480px,100%);max-inline-size:100%;background:var(--surface-card, #fff);border-inline-start:1px solid var(--surface-border, rgba(0, 0, 0, .08));box-shadow:-16px 0 48px #00000038;transform:translate(100%);transition:transform .28s cubic-bezier(.32,.72,0,1)}.fly-drawer__panel--sm{inline-size:min(360px,100%)}.fly-drawer__panel--md{inline-size:min(480px,100%)}.fly-drawer__panel--lg{inline-size:min(640px,100%)}.fly-drawer__panel--xl{inline-size:min(960px,94%)}.fly-drawer__panel--side-start{inset-inline-end:auto;inset-inline-start:0;border-inline-start:none;border-inline-end:1px solid var(--surface-border, rgba(0, 0, 0, .08));box-shadow:16px 0 48px #00000038;transform:translate(-100%)}.fly-drawer__panel--in{transform:translate(0)}:host-context([dir=rtl]) .fly-drawer__panel{transform:translate(-100%)}:host-context([dir=rtl]) .fly-drawer__panel--side-start{transform:translate(100%)}:host-context([dir=rtl]) .fly-drawer__panel--in{transform:translate(0)}:host-context([dir=rtl]) .fly-drawer__panel{box-shadow:16px 0 48px #00000038;border-inline-start:1px solid var(--surface-border, rgba(0, 0, 0, .08))}.fly-drawer__header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;border-block-end:1px solid var(--surface-border, rgba(0, 0, 0, .08));flex:0 0 auto}.fly-drawer__title{margin:0;font-size:16px;font-weight:600;color:var(--label-primary, #1d1d1f)}.fly-drawer__close{display:inline-flex;align-items:center;justify-content:center;inline-size:30px;block-size:30px;border:none;border-radius:8px;background:transparent;color:var(--label-secondary, #6e6e73);cursor:pointer}.fly-drawer__close:hover{background:#0000000f}.fly-drawer__body{flex:1 1 auto;min-block-size:0;overflow-y:auto}:host ::ng-deep [flyDrawerFooter]{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 18px;border-block-start:1px solid var(--surface-border, rgba(0, 0, 0, .08))}:host-context(html.dark-theme) .fly-drawer__panel{background:#1c1c1e}:host-context(html.dark-theme) .fly-drawer__title{color:#f5f5f7}:host-context(html.dark-theme) .fly-drawer__close:hover{background:#ffffff14}@media(prefers-reduced-motion:reduce){.fly-drawer__scrim,.fly-drawer__panel{transition:none}}@media(forced-colors:active){.fly-drawer__panel{border:1px solid CanvasText}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i1$2.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4325
+ }
4326
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FlyDrawerComponent, decorators: [{
4327
+ type: Component,
4328
+ args: [{ selector: 'fly-drawer', standalone: true, imports: [CommonModule, A11yModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n Windowed overlay drawer. Renders only while mounted (open or sliding out).\n Scrim + panel are absolutely positioned within the nearest positioned\n ancestor (the consuming app root must be position:relative).\n-->\n@if (rendered()) {\n <div\n class=\"fly-drawer__scrim\"\n [class.fly-drawer__scrim--in]=\"entered()\"\n (click)=\"onScrimClick()\"\n aria-hidden=\"true\"\n ></div>\n\n <div\n class=\"fly-drawer__panel\"\n [class.fly-drawer__panel--in]=\"entered()\"\n [class]=\"'fly-drawer__panel--' + size() + ' fly-drawer__panel--side-' + side()\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-label]=\"!labelledBy() && ariaLabel() ? (ariaLabel()! | translate) : null\"\n cdkTrapFocus\n [cdkTrapFocusAutoCapture]=\"true\"\n (transitionend)=\"onPanelTransitionEnd()\"\n >\n <!-- Header: custom slot, else heading + close \u2715. -->\n <ng-content select=\"[flyDrawerHeader]\">\n @if (heading()) {\n <header class=\"fly-drawer__header\">\n <h2 class=\"fly-drawer__title\" [id]=\"headingId\">{{ heading()! | translate }}</h2>\n @if (!hideCloseButton()) {\n <button\n type=\"button\"\n class=\"fly-drawer__close\"\n (click)=\"requestClose()\"\n [attr.aria-label]=\"'common.action.close' | translate\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n }\n </ng-content>\n\n <div class=\"fly-drawer__body\">\n <ng-content></ng-content>\n </div>\n\n <ng-content select=\"[flyDrawerFooter]\"></ng-content>\n </div>\n}\n", styles: [":host{position:absolute;inset:0;z-index:60;pointer-events:none}.fly-drawer__scrim{position:absolute;inset:0;pointer-events:auto;background:#00000061;opacity:0;transition:opacity .24s ease}.fly-drawer__scrim--in{opacity:1}.fly-drawer__panel{position:absolute;inset-block:0;inset-inline-end:0;pointer-events:auto;display:flex;flex-direction:column;min-block-size:0;inline-size:min(480px,100%);max-inline-size:100%;background:var(--surface-card, #fff);border-inline-start:1px solid var(--surface-border, rgba(0, 0, 0, .08));box-shadow:-16px 0 48px #00000038;transform:translate(100%);transition:transform .28s cubic-bezier(.32,.72,0,1)}.fly-drawer__panel--sm{inline-size:min(360px,100%)}.fly-drawer__panel--md{inline-size:min(480px,100%)}.fly-drawer__panel--lg{inline-size:min(640px,100%)}.fly-drawer__panel--xl{inline-size:min(960px,94%)}.fly-drawer__panel--side-start{inset-inline-end:auto;inset-inline-start:0;border-inline-start:none;border-inline-end:1px solid var(--surface-border, rgba(0, 0, 0, .08));box-shadow:16px 0 48px #00000038;transform:translate(-100%)}.fly-drawer__panel--in{transform:translate(0)}:host-context([dir=rtl]) .fly-drawer__panel{transform:translate(-100%)}:host-context([dir=rtl]) .fly-drawer__panel--side-start{transform:translate(100%)}:host-context([dir=rtl]) .fly-drawer__panel--in{transform:translate(0)}:host-context([dir=rtl]) .fly-drawer__panel{box-shadow:16px 0 48px #00000038;border-inline-start:1px solid var(--surface-border, rgba(0, 0, 0, .08))}.fly-drawer__header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;border-block-end:1px solid var(--surface-border, rgba(0, 0, 0, .08));flex:0 0 auto}.fly-drawer__title{margin:0;font-size:16px;font-weight:600;color:var(--label-primary, #1d1d1f)}.fly-drawer__close{display:inline-flex;align-items:center;justify-content:center;inline-size:30px;block-size:30px;border:none;border-radius:8px;background:transparent;color:var(--label-secondary, #6e6e73);cursor:pointer}.fly-drawer__close:hover{background:#0000000f}.fly-drawer__body{flex:1 1 auto;min-block-size:0;overflow-y:auto}:host ::ng-deep [flyDrawerFooter]{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 18px;border-block-start:1px solid var(--surface-border, rgba(0, 0, 0, .08))}:host-context(html.dark-theme) .fly-drawer__panel{background:#1c1c1e}:host-context(html.dark-theme) .fly-drawer__title{color:#f5f5f7}:host-context(html.dark-theme) .fly-drawer__close:hover{background:#ffffff14}@media(prefers-reduced-motion:reduce){.fly-drawer__scrim,.fly-drawer__panel{transition:none}}@media(forced-colors:active){.fly-drawer__panel{border:1px solid CanvasText}}\n"] }]
4329
+ }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], heading: [{ type: i0.Input, args: [{ isSignal: true, alias: "heading", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], dismissOnScrim: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissOnScrim", required: false }] }], dismissOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissOnEscape", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hideCloseButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideCloseButton", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], openChange: [{ type: i0.Output, args: ["openChange"] }], onEscape: [{
4330
+ type: HostListener,
4331
+ args: ['document:keydown.escape']
4332
+ }] } });
4333
+
4179
4334
  /**
4180
4335
  * Image upload component with built-in cropperjs cropping modal.
4181
4336
  *
@@ -4354,110 +4509,110 @@ class FlyImageUploadComponent {
4354
4509
  });
4355
4510
  }
4356
4511
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FlyImageUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4357
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: FlyImageUploadComponent, isStandalone: true, selector: "fly-image-upload", inputs: { aspectRatio: { classPropertyName: "aspectRatio", publicName: "aspectRatio", isSignal: true, isRequired: false, transformFunction: null }, maxSizeBytes: { classPropertyName: "maxSizeBytes", publicName: "maxSizeBytes", isSignal: true, isRequired: false, transformFunction: null }, currentImageId: { classPropertyName: "currentImageId", publicName: "currentImageId", isSignal: true, isRequired: false, transformFunction: null }, sourceApp: { classPropertyName: "sourceApp", publicName: "sourceApp", isSignal: true, isRequired: false, transformFunction: null }, sourceEntityType: { classPropertyName: "sourceEntityType", publicName: "sourceEntityType", isSignal: true, isRequired: false, transformFunction: null }, sourceEntityId: { classPropertyName: "sourceEntityId", publicName: "sourceEntityId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { uploaded: "uploaded", removed: "removed" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }, { propertyName: "cropImage", first: true, predicate: ["cropImage"], descendants: true, isSignal: true }], ngImport: i0, template: `
4358
- <div class="fly-image-upload">
4359
- @if (previewUrl()) {
4360
- <div class="fly-image-upload__preview">
4361
- <img [src]="previewUrl()" alt="" class="fly-image-upload__img" />
4362
- <div class="fly-image-upload__overlay">
4363
- <button type="button" class="fly-image-upload__action-btn" (click)="triggerFileInput()" [title]="'files.imageUpload.change' | translate">
4364
- <span class="pi pi-pencil" aria-hidden="true"></span>
4365
- </button>
4366
- <button type="button" class="fly-image-upload__action-btn fly-image-upload__action-btn--danger" (click)="removeImage()" [title]="'files.imageUpload.remove' | translate">
4367
- <span class="pi pi-trash" aria-hidden="true"></span>
4368
- </button>
4369
- </div>
4370
- </div>
4371
- } @else {
4372
- <button type="button" class="fly-image-upload__dropzone" (click)="triggerFileInput()" (dragover)="onDragOver($event)" (drop)="onDrop($event)">
4373
- @if (uploading()) {
4374
- <span class="pi pi-spin pi-spinner fly-image-upload__icon" aria-hidden="true"></span>
4375
- <span class="fly-image-upload__label">{{ 'files.imageUpload.uploading' | translate }}</span>
4376
- } @else {
4377
- <span class="pi pi-image fly-image-upload__icon" aria-hidden="true"></span>
4378
- <span class="fly-image-upload__label">{{ 'files.imageUpload.placeholder' | translate }}</span>
4379
- <span class="fly-image-upload__hint">{{ sizeHint() }}</span>
4380
- }
4381
- </button>
4382
- }
4383
-
4384
- @if (error()) {
4385
- <div class="fly-image-upload__error">{{ error() }}</div>
4386
- }
4387
-
4388
- <input #fileInput type="file" accept="image/*" class="fly-image-upload__hidden" (change)="onFileSelected($event)" />
4389
-
4390
- @if (showCropper()) {
4391
- <div class="fly-image-upload__crop-backdrop" (click)="cancelCrop()">
4392
- <div class="fly-image-upload__crop-modal" (click)="$event.stopPropagation()">
4393
- <div class="fly-image-upload__crop-header">
4394
- <h3>{{ 'files.imageUpload.crop' | translate }}</h3>
4395
- </div>
4396
- <div class="fly-image-upload__crop-body">
4397
- <img #cropImage [src]="rawImageUrl()" alt="" />
4398
- </div>
4399
- <div class="fly-image-upload__crop-footer">
4400
- <button type="button" class="vos-btn sm platter" (click)="cancelCrop()">{{ 'common.cancel' | translate }}</button>
4401
- <button type="button" class="vos-btn sm primary" (click)="applyCrop()">{{ 'files.imageUpload.apply' | translate }}</button>
4402
- </div>
4403
- </div>
4404
- </div>
4405
- }
4406
- </div>
4512
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: FlyImageUploadComponent, isStandalone: true, selector: "fly-image-upload", inputs: { aspectRatio: { classPropertyName: "aspectRatio", publicName: "aspectRatio", isSignal: true, isRequired: false, transformFunction: null }, maxSizeBytes: { classPropertyName: "maxSizeBytes", publicName: "maxSizeBytes", isSignal: true, isRequired: false, transformFunction: null }, currentImageId: { classPropertyName: "currentImageId", publicName: "currentImageId", isSignal: true, isRequired: false, transformFunction: null }, sourceApp: { classPropertyName: "sourceApp", publicName: "sourceApp", isSignal: true, isRequired: false, transformFunction: null }, sourceEntityType: { classPropertyName: "sourceEntityType", publicName: "sourceEntityType", isSignal: true, isRequired: false, transformFunction: null }, sourceEntityId: { classPropertyName: "sourceEntityId", publicName: "sourceEntityId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { uploaded: "uploaded", removed: "removed" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }, { propertyName: "cropImage", first: true, predicate: ["cropImage"], descendants: true, isSignal: true }], ngImport: i0, template: `
4513
+ <div class="fly-image-upload">
4514
+ @if (previewUrl()) {
4515
+ <div class="fly-image-upload__preview">
4516
+ <img [src]="previewUrl()" alt="" class="fly-image-upload__img" />
4517
+ <div class="fly-image-upload__overlay">
4518
+ <button type="button" class="fly-image-upload__action-btn" (click)="triggerFileInput()" [title]="'files.imageUpload.change' | translate">
4519
+ <span class="pi pi-pencil" aria-hidden="true"></span>
4520
+ </button>
4521
+ <button type="button" class="fly-image-upload__action-btn fly-image-upload__action-btn--danger" (click)="removeImage()" [title]="'files.imageUpload.remove' | translate">
4522
+ <span class="pi pi-trash" aria-hidden="true"></span>
4523
+ </button>
4524
+ </div>
4525
+ </div>
4526
+ } @else {
4527
+ <button type="button" class="fly-image-upload__dropzone" (click)="triggerFileInput()" (dragover)="onDragOver($event)" (drop)="onDrop($event)">
4528
+ @if (uploading()) {
4529
+ <span class="pi pi-spin pi-spinner fly-image-upload__icon" aria-hidden="true"></span>
4530
+ <span class="fly-image-upload__label">{{ 'files.imageUpload.uploading' | translate }}</span>
4531
+ } @else {
4532
+ <span class="pi pi-image fly-image-upload__icon" aria-hidden="true"></span>
4533
+ <span class="fly-image-upload__label">{{ 'files.imageUpload.placeholder' | translate }}</span>
4534
+ <span class="fly-image-upload__hint">{{ sizeHint() }}</span>
4535
+ }
4536
+ </button>
4537
+ }
4538
+
4539
+ @if (error()) {
4540
+ <div class="fly-image-upload__error">{{ error() }}</div>
4541
+ }
4542
+
4543
+ <input #fileInput type="file" accept="image/*" class="fly-image-upload__hidden" (change)="onFileSelected($event)" />
4544
+
4545
+ @if (showCropper()) {
4546
+ <div class="fly-image-upload__crop-backdrop" (click)="cancelCrop()">
4547
+ <div class="fly-image-upload__crop-modal" (click)="$event.stopPropagation()">
4548
+ <div class="fly-image-upload__crop-header">
4549
+ <h3>{{ 'files.imageUpload.crop' | translate }}</h3>
4550
+ </div>
4551
+ <div class="fly-image-upload__crop-body">
4552
+ <img #cropImage [src]="rawImageUrl()" alt="" />
4553
+ </div>
4554
+ <div class="fly-image-upload__crop-footer">
4555
+ <button type="button" class="vos-btn sm platter" (click)="cancelCrop()">{{ 'common.cancel' | translate }}</button>
4556
+ <button type="button" class="vos-btn sm primary" (click)="applyCrop()">{{ 'files.imageUpload.apply' | translate }}</button>
4557
+ </div>
4558
+ </div>
4559
+ </div>
4560
+ }
4561
+ </div>
4407
4562
  `, isInline: true, styles: [".cropper-container{-webkit-touch-callout:none;direction:ltr;font-size:0;line-height:0;position:relative;touch-action:none;-webkit-user-select:none;user-select:none}.cropper-container img{backface-visibility:hidden;display:block;height:100%;image-orientation:0deg;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;width:100%}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{inset:0;position:absolute}.cropper-canvas,.cropper-wrap-box{overflow:hidden}.cropper-drag-box{background-color:#fff;opacity:0}.cropper-modal{background-color:#000;opacity:.5}.cropper-view-box{display:block;height:100%;outline:1px solid #39f;outline-color:#3399ffbf;overflow:hidden;width:100%}.cropper-dashed{border:0 dashed #eee;display:block;opacity:.5;position:absolute}.cropper-dashed.dashed-h{border-bottom-width:1px;border-top-width:1px;height:33.33333%;left:0;top:33.33333%;width:100%}.cropper-dashed.dashed-v{border-left-width:1px;border-right-width:1px;height:100%;left:33.33333%;top:0;width:33.33333%}.cropper-center{display:block;height:0;left:50%;opacity:.75;position:absolute;top:50%;width:0}.cropper-center:after,.cropper-center:before{background-color:#eee;content:\" \";display:block;position:absolute}.cropper-center:before{height:1px;left:-3px;top:0;width:7px}.cropper-center:after{height:7px;left:0;top:-3px;width:1px}.cropper-face,.cropper-line,.cropper-point{display:block;height:100%;opacity:.1;position:absolute;width:100%}.cropper-face{background-color:#fff;left:0;top:0}.cropper-line{background-color:#39f}.cropper-line.line-e{cursor:ew-resize;right:-3px;top:0;width:5px}.cropper-line.line-n{cursor:ns-resize;height:5px;left:0;top:-3px}.cropper-line.line-w{cursor:ew-resize;left:-3px;top:0;width:5px}.cropper-line.line-s{bottom:-3px;cursor:ns-resize;height:5px;left:0}.cropper-point{background-color:#39f;height:5px;opacity:.75;width:5px}.cropper-point.point-e{cursor:ew-resize;margin-top:-3px;right:-3px;top:50%}.cropper-point.point-n{cursor:ns-resize;left:50%;margin-left:-3px;top:-3px}.cropper-point.point-w{cursor:ew-resize;left:-3px;margin-top:-3px;top:50%}.cropper-point.point-s{bottom:-3px;cursor:s-resize;left:50%;margin-left:-3px}.cropper-point.point-ne{cursor:nesw-resize;right:-3px;top:-3px}.cropper-point.point-nw{cursor:nwse-resize;left:-3px;top:-3px}.cropper-point.point-sw{bottom:-3px;cursor:nesw-resize;left:-3px}.cropper-point.point-se{bottom:-3px;cursor:nwse-resize;height:20px;opacity:1;right:-3px;width:20px}.cropper-invisible{opacity:0}.cropper-bg{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC)}.cropper-hide{display:block;height:0;position:absolute;width:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed}\n", ".fly-image-upload{display:flex;flex-direction:column;gap:6px}.fly-image-upload__hidden{display:none}.fly-image-upload__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:24px;border:2px dashed var(--separator-primary, #e5e7eb);border-radius:12px;background:var(--fill-quaternary, #f9fafb);cursor:pointer;transition:border-color .15s,background .15s;min-height:120px}.fly-image-upload__dropzone:hover{border-color:var(--accent-primary, #0071e3);background:var(--fill-tertiary, #f3f4f6)}.fly-image-upload__icon{font-size:28px;color:var(--label-tertiary, #9ca3af)}.fly-image-upload__label{font-size:13px;color:var(--label-secondary, #6b7280)}.fly-image-upload__hint{font-size:11px;color:var(--label-tertiary, #9ca3af)}.fly-image-upload__preview{position:relative;border-radius:12px;overflow:hidden}.fly-image-upload__img{display:block;width:100%;max-height:280px;object-fit:cover;border-radius:12px}.fly-image-upload__overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:12px;background:#00000059;opacity:0;transition:opacity .15s}.fly-image-upload__preview:hover .fly-image-upload__overlay{opacity:1}.fly-image-upload__action-btn{width:36px;height:36px;border-radius:50%;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;background:#ffffffe6;color:var(--label-primary, #1f2937);font-size:14px;transition:background .15s}.fly-image-upload__action-btn:hover{background:#fff}.fly-image-upload__action-btn--danger:hover{background:#fee2e2;color:#dc2626}.fly-image-upload__error{font-size:12px;color:var(--system-red, #ef4444)}.fly-image-upload__crop-backdrop{position:fixed;inset:0;z-index:10000;display:flex;align-items:center;justify-content:center;background:#0009;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.fly-image-upload__crop-modal{background:var(--bg-primary, #fff);color:var(--label-primary, #1f2937);border-radius:16px;overflow:hidden;max-width:700px;width:90vw;box-shadow:0 20px 60px #0006;border:1px solid var(--separator-primary, rgba(0,0,0,.1))}.fly-image-upload__crop-header{padding:16px 20px;border-bottom:1px solid var(--separator-primary, #e5e7eb);background:var(--fill-quaternary, transparent)}.fly-image-upload__crop-header h3{margin:0;font-size:16px;font-weight:600;color:var(--label-primary, #1f2937)}.fly-image-upload__crop-body{max-height:60vh;overflow:hidden;background:var(--fill-tertiary, #f3f4f6)}.fly-image-upload__crop-body img{display:block;max-width:100%}.fly-image-upload__crop-footer{display:flex;justify-content:flex-end;gap:10px;padding:14px 20px;border-top:1px solid var(--separator-primary, #e5e7eb);background:var(--fill-quaternary, transparent)}html.dark-theme .fly-image-upload__crop-modal{background:var(--bg-primary, #1c1c1e);border:1px solid var(--separator-primary, rgba(255,255,255,.1))}html.dark-theme .fly-image-upload__crop-body{background:var(--fill-tertiary, #2c2c2e)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4408
4563
  }
4409
4564
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FlyImageUploadComponent, decorators: [{
4410
4565
  type: Component,
4411
- args: [{ selector: 'fly-image-upload', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
4412
- <div class="fly-image-upload">
4413
- @if (previewUrl()) {
4414
- <div class="fly-image-upload__preview">
4415
- <img [src]="previewUrl()" alt="" class="fly-image-upload__img" />
4416
- <div class="fly-image-upload__overlay">
4417
- <button type="button" class="fly-image-upload__action-btn" (click)="triggerFileInput()" [title]="'files.imageUpload.change' | translate">
4418
- <span class="pi pi-pencil" aria-hidden="true"></span>
4419
- </button>
4420
- <button type="button" class="fly-image-upload__action-btn fly-image-upload__action-btn--danger" (click)="removeImage()" [title]="'files.imageUpload.remove' | translate">
4421
- <span class="pi pi-trash" aria-hidden="true"></span>
4422
- </button>
4423
- </div>
4424
- </div>
4425
- } @else {
4426
- <button type="button" class="fly-image-upload__dropzone" (click)="triggerFileInput()" (dragover)="onDragOver($event)" (drop)="onDrop($event)">
4427
- @if (uploading()) {
4428
- <span class="pi pi-spin pi-spinner fly-image-upload__icon" aria-hidden="true"></span>
4429
- <span class="fly-image-upload__label">{{ 'files.imageUpload.uploading' | translate }}</span>
4430
- } @else {
4431
- <span class="pi pi-image fly-image-upload__icon" aria-hidden="true"></span>
4432
- <span class="fly-image-upload__label">{{ 'files.imageUpload.placeholder' | translate }}</span>
4433
- <span class="fly-image-upload__hint">{{ sizeHint() }}</span>
4434
- }
4435
- </button>
4436
- }
4437
-
4438
- @if (error()) {
4439
- <div class="fly-image-upload__error">{{ error() }}</div>
4440
- }
4441
-
4442
- <input #fileInput type="file" accept="image/*" class="fly-image-upload__hidden" (change)="onFileSelected($event)" />
4443
-
4444
- @if (showCropper()) {
4445
- <div class="fly-image-upload__crop-backdrop" (click)="cancelCrop()">
4446
- <div class="fly-image-upload__crop-modal" (click)="$event.stopPropagation()">
4447
- <div class="fly-image-upload__crop-header">
4448
- <h3>{{ 'files.imageUpload.crop' | translate }}</h3>
4449
- </div>
4450
- <div class="fly-image-upload__crop-body">
4451
- <img #cropImage [src]="rawImageUrl()" alt="" />
4452
- </div>
4453
- <div class="fly-image-upload__crop-footer">
4454
- <button type="button" class="vos-btn sm platter" (click)="cancelCrop()">{{ 'common.cancel' | translate }}</button>
4455
- <button type="button" class="vos-btn sm primary" (click)="applyCrop()">{{ 'files.imageUpload.apply' | translate }}</button>
4456
- </div>
4457
- </div>
4458
- </div>
4459
- }
4460
- </div>
4566
+ args: [{ selector: 'fly-image-upload', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
4567
+ <div class="fly-image-upload">
4568
+ @if (previewUrl()) {
4569
+ <div class="fly-image-upload__preview">
4570
+ <img [src]="previewUrl()" alt="" class="fly-image-upload__img" />
4571
+ <div class="fly-image-upload__overlay">
4572
+ <button type="button" class="fly-image-upload__action-btn" (click)="triggerFileInput()" [title]="'files.imageUpload.change' | translate">
4573
+ <span class="pi pi-pencil" aria-hidden="true"></span>
4574
+ </button>
4575
+ <button type="button" class="fly-image-upload__action-btn fly-image-upload__action-btn--danger" (click)="removeImage()" [title]="'files.imageUpload.remove' | translate">
4576
+ <span class="pi pi-trash" aria-hidden="true"></span>
4577
+ </button>
4578
+ </div>
4579
+ </div>
4580
+ } @else {
4581
+ <button type="button" class="fly-image-upload__dropzone" (click)="triggerFileInput()" (dragover)="onDragOver($event)" (drop)="onDrop($event)">
4582
+ @if (uploading()) {
4583
+ <span class="pi pi-spin pi-spinner fly-image-upload__icon" aria-hidden="true"></span>
4584
+ <span class="fly-image-upload__label">{{ 'files.imageUpload.uploading' | translate }}</span>
4585
+ } @else {
4586
+ <span class="pi pi-image fly-image-upload__icon" aria-hidden="true"></span>
4587
+ <span class="fly-image-upload__label">{{ 'files.imageUpload.placeholder' | translate }}</span>
4588
+ <span class="fly-image-upload__hint">{{ sizeHint() }}</span>
4589
+ }
4590
+ </button>
4591
+ }
4592
+
4593
+ @if (error()) {
4594
+ <div class="fly-image-upload__error">{{ error() }}</div>
4595
+ }
4596
+
4597
+ <input #fileInput type="file" accept="image/*" class="fly-image-upload__hidden" (change)="onFileSelected($event)" />
4598
+
4599
+ @if (showCropper()) {
4600
+ <div class="fly-image-upload__crop-backdrop" (click)="cancelCrop()">
4601
+ <div class="fly-image-upload__crop-modal" (click)="$event.stopPropagation()">
4602
+ <div class="fly-image-upload__crop-header">
4603
+ <h3>{{ 'files.imageUpload.crop' | translate }}</h3>
4604
+ </div>
4605
+ <div class="fly-image-upload__crop-body">
4606
+ <img #cropImage [src]="rawImageUrl()" alt="" />
4607
+ </div>
4608
+ <div class="fly-image-upload__crop-footer">
4609
+ <button type="button" class="vos-btn sm platter" (click)="cancelCrop()">{{ 'common.cancel' | translate }}</button>
4610
+ <button type="button" class="vos-btn sm primary" (click)="applyCrop()">{{ 'files.imageUpload.apply' | translate }}</button>
4611
+ </div>
4612
+ </div>
4613
+ </div>
4614
+ }
4615
+ </div>
4461
4616
  `, styles: [".cropper-container{-webkit-touch-callout:none;direction:ltr;font-size:0;line-height:0;position:relative;touch-action:none;-webkit-user-select:none;user-select:none}.cropper-container img{backface-visibility:hidden;display:block;height:100%;image-orientation:0deg;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;width:100%}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{inset:0;position:absolute}.cropper-canvas,.cropper-wrap-box{overflow:hidden}.cropper-drag-box{background-color:#fff;opacity:0}.cropper-modal{background-color:#000;opacity:.5}.cropper-view-box{display:block;height:100%;outline:1px solid #39f;outline-color:#3399ffbf;overflow:hidden;width:100%}.cropper-dashed{border:0 dashed #eee;display:block;opacity:.5;position:absolute}.cropper-dashed.dashed-h{border-bottom-width:1px;border-top-width:1px;height:33.33333%;left:0;top:33.33333%;width:100%}.cropper-dashed.dashed-v{border-left-width:1px;border-right-width:1px;height:100%;left:33.33333%;top:0;width:33.33333%}.cropper-center{display:block;height:0;left:50%;opacity:.75;position:absolute;top:50%;width:0}.cropper-center:after,.cropper-center:before{background-color:#eee;content:\" \";display:block;position:absolute}.cropper-center:before{height:1px;left:-3px;top:0;width:7px}.cropper-center:after{height:7px;left:0;top:-3px;width:1px}.cropper-face,.cropper-line,.cropper-point{display:block;height:100%;opacity:.1;position:absolute;width:100%}.cropper-face{background-color:#fff;left:0;top:0}.cropper-line{background-color:#39f}.cropper-line.line-e{cursor:ew-resize;right:-3px;top:0;width:5px}.cropper-line.line-n{cursor:ns-resize;height:5px;left:0;top:-3px}.cropper-line.line-w{cursor:ew-resize;left:-3px;top:0;width:5px}.cropper-line.line-s{bottom:-3px;cursor:ns-resize;height:5px;left:0}.cropper-point{background-color:#39f;height:5px;opacity:.75;width:5px}.cropper-point.point-e{cursor:ew-resize;margin-top:-3px;right:-3px;top:50%}.cropper-point.point-n{cursor:ns-resize;left:50%;margin-left:-3px;top:-3px}.cropper-point.point-w{cursor:ew-resize;left:-3px;margin-top:-3px;top:50%}.cropper-point.point-s{bottom:-3px;cursor:s-resize;left:50%;margin-left:-3px}.cropper-point.point-ne{cursor:nesw-resize;right:-3px;top:-3px}.cropper-point.point-nw{cursor:nwse-resize;left:-3px;top:-3px}.cropper-point.point-sw{bottom:-3px;cursor:nesw-resize;left:-3px}.cropper-point.point-se{bottom:-3px;cursor:nwse-resize;height:20px;opacity:1;right:-3px;width:20px}.cropper-invisible{opacity:0}.cropper-bg{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC)}.cropper-hide{display:block;height:0;position:absolute;width:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed}\n", ".fly-image-upload{display:flex;flex-direction:column;gap:6px}.fly-image-upload__hidden{display:none}.fly-image-upload__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:24px;border:2px dashed var(--separator-primary, #e5e7eb);border-radius:12px;background:var(--fill-quaternary, #f9fafb);cursor:pointer;transition:border-color .15s,background .15s;min-height:120px}.fly-image-upload__dropzone:hover{border-color:var(--accent-primary, #0071e3);background:var(--fill-tertiary, #f3f4f6)}.fly-image-upload__icon{font-size:28px;color:var(--label-tertiary, #9ca3af)}.fly-image-upload__label{font-size:13px;color:var(--label-secondary, #6b7280)}.fly-image-upload__hint{font-size:11px;color:var(--label-tertiary, #9ca3af)}.fly-image-upload__preview{position:relative;border-radius:12px;overflow:hidden}.fly-image-upload__img{display:block;width:100%;max-height:280px;object-fit:cover;border-radius:12px}.fly-image-upload__overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:12px;background:#00000059;opacity:0;transition:opacity .15s}.fly-image-upload__preview:hover .fly-image-upload__overlay{opacity:1}.fly-image-upload__action-btn{width:36px;height:36px;border-radius:50%;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;background:#ffffffe6;color:var(--label-primary, #1f2937);font-size:14px;transition:background .15s}.fly-image-upload__action-btn:hover{background:#fff}.fly-image-upload__action-btn--danger:hover{background:#fee2e2;color:#dc2626}.fly-image-upload__error{font-size:12px;color:var(--system-red, #ef4444)}.fly-image-upload__crop-backdrop{position:fixed;inset:0;z-index:10000;display:flex;align-items:center;justify-content:center;background:#0009;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.fly-image-upload__crop-modal{background:var(--bg-primary, #fff);color:var(--label-primary, #1f2937);border-radius:16px;overflow:hidden;max-width:700px;width:90vw;box-shadow:0 20px 60px #0006;border:1px solid var(--separator-primary, rgba(0,0,0,.1))}.fly-image-upload__crop-header{padding:16px 20px;border-bottom:1px solid var(--separator-primary, #e5e7eb);background:var(--fill-quaternary, transparent)}.fly-image-upload__crop-header h3{margin:0;font-size:16px;font-weight:600;color:var(--label-primary, #1f2937)}.fly-image-upload__crop-body{max-height:60vh;overflow:hidden;background:var(--fill-tertiary, #f3f4f6)}.fly-image-upload__crop-body img{display:block;max-width:100%}.fly-image-upload__crop-footer{display:flex;justify-content:flex-end;gap:10px;padding:14px 20px;border-top:1px solid var(--separator-primary, #e5e7eb);background:var(--fill-quaternary, transparent)}html.dark-theme .fly-image-upload__crop-modal{background:var(--bg-primary, #1c1c1e);border:1px solid var(--separator-primary, rgba(255,255,255,.1))}html.dark-theme .fly-image-upload__crop-body{background:var(--fill-tertiary, #2c2c2e)}\n"] }]
4462
4617
  }], ctorParameters: () => [], propDecorators: { aspectRatio: [{ type: i0.Input, args: [{ isSignal: true, alias: "aspectRatio", required: false }] }], maxSizeBytes: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSizeBytes", required: false }] }], currentImageId: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentImageId", required: false }] }], sourceApp: [{ type: i0.Input, args: [{ isSignal: true, alias: "sourceApp", required: false }] }], sourceEntityType: [{ type: i0.Input, args: [{ isSignal: true, alias: "sourceEntityType", required: false }] }], sourceEntityId: [{ type: i0.Input, args: [{ isSignal: true, alias: "sourceEntityId", required: false }] }], uploaded: [{ type: i0.Output, args: ["uploaded"] }], removed: [{ type: i0.Output, args: ["removed"] }], fileInput: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }], cropImage: [{ type: i0.ViewChild, args: ['cropImage', { isSignal: true }] }] } });
4463
4618
 
@@ -6632,5 +6787,5 @@ const AUDIENCE_ERROR_CODES = {
6632
6787
  * Generated bundle index. Do not edit.
6633
6788
  */
6634
6789
 
6635
- export { AGENT_DRAG_MIME, AGENT_PAYLOAD_VERSION, APP_LOOKUP, AUDIENCE_ERROR_CODES, AUDIENCE_LIMITS, AUDIENCE_PRESETS, AUDIENCE_TERM_KINDS, AgentActionBus, AgentActionUnsupportedDispatchError, AgentCommandRegistry, AgentDropRegistry, AgentFlightAnimator, AgentLookupRegistry, AgentPayloadOversizeError, AudienceBuilderComponent, AuthService, ContextMenuComponent, DEFAULT_AGENT_PAYLOAD_LIMITS, DEFAULT_FLY_THEME_MODE, DS_BASELINE_LOCALES, DialogResult, ENTITY_LINK_LAUNCHER, EntityLookupComponent, FLYOS_LAUNCH_EVENT, FLYOS_PROTOCOL, FLYOS_REMOTE_ROUTE_EVENT, FLY_LOCALE_CATALOG, FLY_REMOTE_BASE_PATH, FLY_REMOTE_CONTEXT_EVENT, FLY_REMOTE_CONTEXT_STORE_KEY, FLY_REMOTE_ROUTES, FLY_THEME_MODE_IDS, FLY_WINDOW_HELP_HINT_EVENT, FlyAgentDraggableDirective, FlyBlockUiComponent, FlyFileUploadComponent, FlyImageUploadComponent, FlyMarkdownEditorComponent, FlyRemoteContextService, FlyRemoteRouter, FlyRemoteRouterOutletComponent, FlySecureSrcDirective, FlyThemeService, FlyWindowHelpService, FlyosLink, FlyosPendingLaunchesGlobalKey, FlyosShellOwnsHistoryGlobalKey, I18nService, LAUNCH_CONTEXT, MARKDOWN_TOOLBAR_PRESETS, MessageBoxButtons, MessageBoxComponent, MessageBoxIcon, MessageBoxService, MockAuthService, RTL_LOCALE_SET, SHARE_ORG_CHART_SYSTEM_KEY_APPS, SHARE_ORG_CHART_SYSTEM_KEY_DEFAULT, SHARE_PANEL_DEFAULT_FILE_LEVELS, SUPPORTED_AGENT_PAYLOAD_VERSIONS, SharePanelComponent, SourceAppResolver, StandaloneWindowManagerService, TranslatePipe, WINDOW_DATA, WINDOW_HELP_HINT, WindowManagerService, findLocaleByDialect, findLocaleByPrefix, isRtlLocale, isRtlLocaleEntry, loadRemoteStyles, matchFlyRoutePattern, normalizeFlyTheme, registerFlyosProtocol, trimAgentPayload, trimAgentString, unloadRemoteStyles, utf8ByteLength, validateAgentPayload };
6790
+ export { AGENT_DRAG_MIME, AGENT_PAYLOAD_VERSION, APP_LOOKUP, AUDIENCE_ERROR_CODES, AUDIENCE_LIMITS, AUDIENCE_PRESETS, AUDIENCE_TERM_KINDS, AgentActionBus, AgentActionUnsupportedDispatchError, AgentCommandRegistry, AgentDropRegistry, AgentFlightAnimator, AgentLookupRegistry, AgentPayloadOversizeError, AudienceBuilderComponent, AuthService, ContextMenuComponent, DEFAULT_AGENT_PAYLOAD_LIMITS, DEFAULT_FLY_THEME_MODE, DS_BASELINE_LOCALES, DialogResult, ENTITY_LINK_LAUNCHER, EntityLookupComponent, FLYOS_LAUNCH_EVENT, FLYOS_PROTOCOL, FLYOS_REMOTE_ROUTE_EVENT, FLY_LOCALE_CATALOG, FLY_REMOTE_BASE_PATH, FLY_REMOTE_CONTEXT_EVENT, FLY_REMOTE_CONTEXT_STORE_KEY, FLY_REMOTE_ROUTES, FLY_THEME_MODE_IDS, FLY_WINDOW_HELP_HINT_EVENT, FlyAgentDraggableDirective, FlyBlockUiComponent, FlyDrawerComponent, FlyFileUploadComponent, FlyImageUploadComponent, FlyMarkdownEditorComponent, FlyRemoteContextService, FlyRemoteRouter, FlyRemoteRouterOutletComponent, FlySecureSrcDirective, FlyThemeService, FlyWindowHelpService, FlyosLink, FlyosPendingLaunchesGlobalKey, FlyosShellOwnsHistoryGlobalKey, I18nService, LAUNCH_CONTEXT, MARKDOWN_TOOLBAR_PRESETS, MessageBoxButtons, MessageBoxComponent, MessageBoxIcon, MessageBoxService, MockAuthService, RTL_LOCALE_SET, SHARE_ORG_CHART_SYSTEM_KEY_APPS, SHARE_ORG_CHART_SYSTEM_KEY_DEFAULT, SHARE_PANEL_DEFAULT_FILE_LEVELS, SUPPORTED_AGENT_PAYLOAD_VERSIONS, SharePanelComponent, SourceAppResolver, StandaloneWindowManagerService, TranslatePipe, WINDOW_DATA, WINDOW_HELP_HINT, WindowManagerService, findLocaleByDialect, findLocaleByPrefix, isRtlLocale, isRtlLocaleEntry, loadRemoteStyles, matchFlyRoutePattern, normalizeFlyTheme, registerFlyosProtocol, trimAgentPayload, trimAgentString, unloadRemoteStyles, utf8ByteLength, validateAgentPayload };
6636
6791
  //# sourceMappingURL=mohamedatia-fly-design-system.mjs.map