@mohamedatia/fly-design-system 2.15.0 → 2.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2419,14 +2419,14 @@ class EntityLookupComponent {
2419
2419
  return resolved;
2420
2420
  }
2421
2421
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EntityLookupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2422
- 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 });
2422
+ 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 });
2423
2423
  }
2424
2424
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EntityLookupComponent, decorators: [{
2425
2425
  type: Component,
2426
2426
  args: [{ selector: 'fly-entity-lookup', standalone: true, imports: [CommonModule, FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2427
2427
  '[class.fly-entity-lookup--down]': "placement() === 'down'",
2428
2428
  '[class.fly-entity-lookup--above]': "placement() === 'above'",
2429
- }, 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"] }]
2429
+ }, 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"] }]
2430
2430
  }], 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: [{
2431
2431
  type: ViewChild,
2432
2432
  args: ['searchRef']
@@ -2701,13 +2701,13 @@ class FlyMarkdownEditorComponent {
2701
2701
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FlyMarkdownEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2702
2702
  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: [
2703
2703
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => FlyMarkdownEditorComponent), multi: true },
2704
- ], 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 });
2704
+ ], 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 });
2705
2705
  }
2706
2706
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FlyMarkdownEditorComponent, decorators: [{
2707
2707
  type: Component,
2708
2708
  args: [{ selector: 'fly-markdown-editor', standalone: true, imports: [CommonModule, FormsModule, TiptapEditorDirective, TranslatePipe, EntityLookupComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
2709
2709
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => FlyMarkdownEditorComponent), multi: true },
2710
- ], 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"] }]
2710
+ ], 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"] }]
2711
2711
  }], 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"] }] } });
2712
2712
 
2713
2713
  class ContextMenuComponent {
@@ -3037,11 +3037,11 @@ class MessageBoxComponent {
3037
3037
  this.previouslyFocused = null;
3038
3038
  }
3039
3039
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3040
- 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 });
3040
+ 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 });
3041
3041
  }
3042
3042
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MessageBoxComponent, decorators: [{
3043
3043
  type: Component,
3044
- 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"] }]
3044
+ 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"] }]
3045
3045
  }], propDecorators: { onEscape: [{
3046
3046
  type: HostListener,
3047
3047
  args: ['document:keydown.escape']
@@ -3373,11 +3373,11 @@ class SharePanelComponent {
3373
3373
  }
3374
3374
  }
3375
3375
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SharePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3376
- 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 });
3376
+ 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 });
3377
3377
  }
3378
3378
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: SharePanelComponent, decorators: [{
3379
3379
  type: Component,
3380
- 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"] }]
3380
+ 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"] }]
3381
3381
  }], propDecorators: { targetName: [{
3382
3382
  type: Input
3383
3383
  }], titleKey: [{
@@ -4023,7 +4023,7 @@ class AudienceBuilderComponent {
4023
4023
  useExisting: forwardRef(() => AudienceBuilderComponent),
4024
4024
  multi: true,
4025
4025
  },
4026
- ], 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 });
4026
+ ], 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 });
4027
4027
  }
4028
4028
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AudienceBuilderComponent, decorators: [{
4029
4029
  type: Component,
@@ -4038,7 +4038,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
4038
4038
  useExisting: forwardRef(() => AudienceBuilderComponent),
4039
4039
  multi: true,
4040
4040
  },
4041
- ], 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"] }]
4041
+ ], 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"] }]
4042
4042
  }], propDecorators: { value: [{
4043
4043
  type: Input
4044
4044
  }], showExcludes: [{
@@ -4266,110 +4266,110 @@ class FlyImageUploadComponent {
4266
4266
  });
4267
4267
  }
4268
4268
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FlyImageUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4269
- 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: `
4270
- <div class="fly-image-upload">
4271
- @if (previewUrl()) {
4272
- <div class="fly-image-upload__preview">
4273
- <img [src]="previewUrl()" alt="" class="fly-image-upload__img" />
4274
- <div class="fly-image-upload__overlay">
4275
- <button type="button" class="fly-image-upload__action-btn" (click)="triggerFileInput()" [title]="'files.imageUpload.change' | translate">
4276
- <span class="pi pi-pencil" aria-hidden="true"></span>
4277
- </button>
4278
- <button type="button" class="fly-image-upload__action-btn fly-image-upload__action-btn--danger" (click)="removeImage()" [title]="'files.imageUpload.remove' | translate">
4279
- <span class="pi pi-trash" aria-hidden="true"></span>
4280
- </button>
4281
- </div>
4282
- </div>
4283
- } @else {
4284
- <button type="button" class="fly-image-upload__dropzone" (click)="triggerFileInput()" (dragover)="onDragOver($event)" (drop)="onDrop($event)">
4285
- @if (uploading()) {
4286
- <span class="pi pi-spin pi-spinner fly-image-upload__icon" aria-hidden="true"></span>
4287
- <span class="fly-image-upload__label">{{ 'files.imageUpload.uploading' | translate }}</span>
4288
- } @else {
4289
- <span class="pi pi-image fly-image-upload__icon" aria-hidden="true"></span>
4290
- <span class="fly-image-upload__label">{{ 'files.imageUpload.placeholder' | translate }}</span>
4291
- <span class="fly-image-upload__hint">{{ sizeHint() }}</span>
4292
- }
4293
- </button>
4294
- }
4295
-
4296
- @if (error()) {
4297
- <div class="fly-image-upload__error">{{ error() }}</div>
4298
- }
4299
-
4300
- <input #fileInput type="file" accept="image/*" class="fly-image-upload__hidden" (change)="onFileSelected($event)" />
4301
-
4302
- @if (showCropper()) {
4303
- <div class="fly-image-upload__crop-backdrop" (click)="cancelCrop()">
4304
- <div class="fly-image-upload__crop-modal" (click)="$event.stopPropagation()">
4305
- <div class="fly-image-upload__crop-header">
4306
- <h3>{{ 'files.imageUpload.crop' | translate }}</h3>
4307
- </div>
4308
- <div class="fly-image-upload__crop-body">
4309
- <img #cropImage [src]="rawImageUrl()" alt="" />
4310
- </div>
4311
- <div class="fly-image-upload__crop-footer">
4312
- <button type="button" class="vos-btn sm platter" (click)="cancelCrop()">{{ 'common.cancel' | translate }}</button>
4313
- <button type="button" class="vos-btn sm primary" (click)="applyCrop()">{{ 'files.imageUpload.apply' | translate }}</button>
4314
- </div>
4315
- </div>
4316
- </div>
4317
- }
4318
- </div>
4269
+ 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: `
4270
+ <div class="fly-image-upload">
4271
+ @if (previewUrl()) {
4272
+ <div class="fly-image-upload__preview">
4273
+ <img [src]="previewUrl()" alt="" class="fly-image-upload__img" />
4274
+ <div class="fly-image-upload__overlay">
4275
+ <button type="button" class="fly-image-upload__action-btn" (click)="triggerFileInput()" [title]="'files.imageUpload.change' | translate">
4276
+ <span class="pi pi-pencil" aria-hidden="true"></span>
4277
+ </button>
4278
+ <button type="button" class="fly-image-upload__action-btn fly-image-upload__action-btn--danger" (click)="removeImage()" [title]="'files.imageUpload.remove' | translate">
4279
+ <span class="pi pi-trash" aria-hidden="true"></span>
4280
+ </button>
4281
+ </div>
4282
+ </div>
4283
+ } @else {
4284
+ <button type="button" class="fly-image-upload__dropzone" (click)="triggerFileInput()" (dragover)="onDragOver($event)" (drop)="onDrop($event)">
4285
+ @if (uploading()) {
4286
+ <span class="pi pi-spin pi-spinner fly-image-upload__icon" aria-hidden="true"></span>
4287
+ <span class="fly-image-upload__label">{{ 'files.imageUpload.uploading' | translate }}</span>
4288
+ } @else {
4289
+ <span class="pi pi-image fly-image-upload__icon" aria-hidden="true"></span>
4290
+ <span class="fly-image-upload__label">{{ 'files.imageUpload.placeholder' | translate }}</span>
4291
+ <span class="fly-image-upload__hint">{{ sizeHint() }}</span>
4292
+ }
4293
+ </button>
4294
+ }
4295
+
4296
+ @if (error()) {
4297
+ <div class="fly-image-upload__error">{{ error() }}</div>
4298
+ }
4299
+
4300
+ <input #fileInput type="file" accept="image/*" class="fly-image-upload__hidden" (change)="onFileSelected($event)" />
4301
+
4302
+ @if (showCropper()) {
4303
+ <div class="fly-image-upload__crop-backdrop" (click)="cancelCrop()">
4304
+ <div class="fly-image-upload__crop-modal" (click)="$event.stopPropagation()">
4305
+ <div class="fly-image-upload__crop-header">
4306
+ <h3>{{ 'files.imageUpload.crop' | translate }}</h3>
4307
+ </div>
4308
+ <div class="fly-image-upload__crop-body">
4309
+ <img #cropImage [src]="rawImageUrl()" alt="" />
4310
+ </div>
4311
+ <div class="fly-image-upload__crop-footer">
4312
+ <button type="button" class="vos-btn sm platter" (click)="cancelCrop()">{{ 'common.cancel' | translate }}</button>
4313
+ <button type="button" class="vos-btn sm primary" (click)="applyCrop()">{{ 'files.imageUpload.apply' | translate }}</button>
4314
+ </div>
4315
+ </div>
4316
+ </div>
4317
+ }
4318
+ </div>
4319
4319
  `, 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 });
4320
4320
  }
4321
4321
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: FlyImageUploadComponent, decorators: [{
4322
4322
  type: Component,
4323
- args: [{ selector: 'fly-image-upload', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
4324
- <div class="fly-image-upload">
4325
- @if (previewUrl()) {
4326
- <div class="fly-image-upload__preview">
4327
- <img [src]="previewUrl()" alt="" class="fly-image-upload__img" />
4328
- <div class="fly-image-upload__overlay">
4329
- <button type="button" class="fly-image-upload__action-btn" (click)="triggerFileInput()" [title]="'files.imageUpload.change' | translate">
4330
- <span class="pi pi-pencil" aria-hidden="true"></span>
4331
- </button>
4332
- <button type="button" class="fly-image-upload__action-btn fly-image-upload__action-btn--danger" (click)="removeImage()" [title]="'files.imageUpload.remove' | translate">
4333
- <span class="pi pi-trash" aria-hidden="true"></span>
4334
- </button>
4335
- </div>
4336
- </div>
4337
- } @else {
4338
- <button type="button" class="fly-image-upload__dropzone" (click)="triggerFileInput()" (dragover)="onDragOver($event)" (drop)="onDrop($event)">
4339
- @if (uploading()) {
4340
- <span class="pi pi-spin pi-spinner fly-image-upload__icon" aria-hidden="true"></span>
4341
- <span class="fly-image-upload__label">{{ 'files.imageUpload.uploading' | translate }}</span>
4342
- } @else {
4343
- <span class="pi pi-image fly-image-upload__icon" aria-hidden="true"></span>
4344
- <span class="fly-image-upload__label">{{ 'files.imageUpload.placeholder' | translate }}</span>
4345
- <span class="fly-image-upload__hint">{{ sizeHint() }}</span>
4346
- }
4347
- </button>
4348
- }
4349
-
4350
- @if (error()) {
4351
- <div class="fly-image-upload__error">{{ error() }}</div>
4352
- }
4353
-
4354
- <input #fileInput type="file" accept="image/*" class="fly-image-upload__hidden" (change)="onFileSelected($event)" />
4355
-
4356
- @if (showCropper()) {
4357
- <div class="fly-image-upload__crop-backdrop" (click)="cancelCrop()">
4358
- <div class="fly-image-upload__crop-modal" (click)="$event.stopPropagation()">
4359
- <div class="fly-image-upload__crop-header">
4360
- <h3>{{ 'files.imageUpload.crop' | translate }}</h3>
4361
- </div>
4362
- <div class="fly-image-upload__crop-body">
4363
- <img #cropImage [src]="rawImageUrl()" alt="" />
4364
- </div>
4365
- <div class="fly-image-upload__crop-footer">
4366
- <button type="button" class="vos-btn sm platter" (click)="cancelCrop()">{{ 'common.cancel' | translate }}</button>
4367
- <button type="button" class="vos-btn sm primary" (click)="applyCrop()">{{ 'files.imageUpload.apply' | translate }}</button>
4368
- </div>
4369
- </div>
4370
- </div>
4371
- }
4372
- </div>
4323
+ args: [{ selector: 'fly-image-upload', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: `
4324
+ <div class="fly-image-upload">
4325
+ @if (previewUrl()) {
4326
+ <div class="fly-image-upload__preview">
4327
+ <img [src]="previewUrl()" alt="" class="fly-image-upload__img" />
4328
+ <div class="fly-image-upload__overlay">
4329
+ <button type="button" class="fly-image-upload__action-btn" (click)="triggerFileInput()" [title]="'files.imageUpload.change' | translate">
4330
+ <span class="pi pi-pencil" aria-hidden="true"></span>
4331
+ </button>
4332
+ <button type="button" class="fly-image-upload__action-btn fly-image-upload__action-btn--danger" (click)="removeImage()" [title]="'files.imageUpload.remove' | translate">
4333
+ <span class="pi pi-trash" aria-hidden="true"></span>
4334
+ </button>
4335
+ </div>
4336
+ </div>
4337
+ } @else {
4338
+ <button type="button" class="fly-image-upload__dropzone" (click)="triggerFileInput()" (dragover)="onDragOver($event)" (drop)="onDrop($event)">
4339
+ @if (uploading()) {
4340
+ <span class="pi pi-spin pi-spinner fly-image-upload__icon" aria-hidden="true"></span>
4341
+ <span class="fly-image-upload__label">{{ 'files.imageUpload.uploading' | translate }}</span>
4342
+ } @else {
4343
+ <span class="pi pi-image fly-image-upload__icon" aria-hidden="true"></span>
4344
+ <span class="fly-image-upload__label">{{ 'files.imageUpload.placeholder' | translate }}</span>
4345
+ <span class="fly-image-upload__hint">{{ sizeHint() }}</span>
4346
+ }
4347
+ </button>
4348
+ }
4349
+
4350
+ @if (error()) {
4351
+ <div class="fly-image-upload__error">{{ error() }}</div>
4352
+ }
4353
+
4354
+ <input #fileInput type="file" accept="image/*" class="fly-image-upload__hidden" (change)="onFileSelected($event)" />
4355
+
4356
+ @if (showCropper()) {
4357
+ <div class="fly-image-upload__crop-backdrop" (click)="cancelCrop()">
4358
+ <div class="fly-image-upload__crop-modal" (click)="$event.stopPropagation()">
4359
+ <div class="fly-image-upload__crop-header">
4360
+ <h3>{{ 'files.imageUpload.crop' | translate }}</h3>
4361
+ </div>
4362
+ <div class="fly-image-upload__crop-body">
4363
+ <img #cropImage [src]="rawImageUrl()" alt="" />
4364
+ </div>
4365
+ <div class="fly-image-upload__crop-footer">
4366
+ <button type="button" class="vos-btn sm platter" (click)="cancelCrop()">{{ 'common.cancel' | translate }}</button>
4367
+ <button type="button" class="vos-btn sm primary" (click)="applyCrop()">{{ 'files.imageUpload.apply' | translate }}</button>
4368
+ </div>
4369
+ </div>
4370
+ </div>
4371
+ }
4372
+ </div>
4373
4373
  `, 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"] }]
4374
4374
  }], 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 }] }] } });
4375
4375