@flyos/design-system 3.5.0 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,7 +47,7 @@ import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
47
47
  // tools/publish-library.ps1 at bump time, and asserted by the spec beside this file.
48
48
  // Used only for the diagnostic message; the duplicate-instance detection itself is
49
49
  // version-agnostic, so a stale literal misnames a fork rather than hiding one.
50
- const FLY_DS_VERSION = '3.5.0';
50
+ const FLY_DS_VERSION = '3.6.0';
51
51
  const FLY_DS_REGISTRY_KEY = '__FLY_DS_INSTANCES__';
52
52
  /**
53
53
  * Records this design-system instance on the shared `scope` and returns the
@@ -6179,14 +6179,14 @@ class EntityLookupComponent {
6179
6179
  return resolved;
6180
6180
  }
6181
6181
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: EntityLookupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6182
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", 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 }, lockEntity: { classPropertyName: "lockEntity", publicName: "lockEntity", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pick: "pick", entityLinkSelected: "entityLinkSelected", invokeSuccess: "invokeSuccess", 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 (showCrumb()) {\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. When `lockEntity` is set the\r\n context accepts only this entity, so the button is DISABLED (the\r\n back chevron is dropped) and it reads as a static entity label. -->\r\n <button\r\n type=\"button\"\r\n class=\"fly-entity-lookup__crumb\"\r\n [class.is-locked]=\"lockEntity()\"\r\n [disabled]=\"lockEntity()\"\r\n (click)=\"goBackToEntity()\"\r\n [attr.aria-label]=\"(lockEntity() ? activeEntityLabel() : ('agent.lookup.back_aria' | translate))\">\r\n @if (!lockEntity()) {\r\n <i class=\"pi pi-angle-left fly-entity-lookup__crumb-back\" aria-hidden=\"true\"></i>\r\n }\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:100% auto;inset-inline:auto;inset-inline-end:0;margin-block:6px 0;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:auto 100%;inset-inline:0;margin-block:0 6px;z-index:1000}.fly-entity-lookup{position:absolute;inset-block-end:100%;inset-inline:12px;margin-block-end:6px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-entity-lookup{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-entity-lookup:before,.fly-entity-lookup:after{display:none}}@media(prefers-contrast:more){.fly-entity-lookup{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-entity-lookup:after{animation:none}}.fly-entity-lookup{border-radius:12px;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);outline-offset:1px}.fly-entity-lookup__crumb.is-locked{cursor:default;opacity:.85}.fly-entity-lookup__crumb.is-locked:hover{background:var(--surface-hover, rgba(255, 255, 255, .06));color:var(--text-color-secondary, rgba(255, 255, 255, .75))}[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 });
6182
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", 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 }, lockEntity: { classPropertyName: "lockEntity", publicName: "lockEntity", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pick: "pick", entityLinkSelected: "entityLinkSelected", invokeSuccess: "invokeSuccess", 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 (showCrumb()) {\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. When `lockEntity` is set the\r\n context accepts only this entity, so the button is DISABLED (the\r\n back chevron is dropped) and it reads as a static entity label. -->\r\n <button\r\n type=\"button\"\r\n class=\"fly-entity-lookup__crumb\"\r\n [class.is-locked]=\"lockEntity()\"\r\n [disabled]=\"lockEntity()\"\r\n (click)=\"goBackToEntity()\"\r\n [attr.aria-label]=\"(lockEntity() ? activeEntityLabel() : ('agent.lookup.back_aria' | translate))\">\r\n @if (!lockEntity()) {\r\n <i class=\"pi pi-angle-left fly-entity-lookup__crumb-back\" aria-hidden=\"true\"></i>\r\n }\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:100% auto;inset-inline:auto;inset-inline-end:0;margin-block:6px 0;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:auto 100%;inset-inline:0;margin-block:0 6px;z-index:1000}.fly-entity-lookup{position:absolute;inset-block-end:100%;inset-inline:12px;margin-block-end:6px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-entity-lookup{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-entity-lookup:before,.fly-entity-lookup:after{display:none}}@media(prefers-contrast:more){.fly-entity-lookup{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-entity-lookup:after{animation:none}}.fly-entity-lookup{border-radius:12px;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;outline-color:var(--primary-color);outline-offset:1px}.fly-entity-lookup__crumb.is-locked{cursor:default;opacity:.85}.fly-entity-lookup__crumb.is-locked:hover{background:var(--surface-hover, rgba(255, 255, 255, .06));color:var(--text-color-secondary, rgba(255, 255, 255, .75))}[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 });
6183
6183
  }
6184
6184
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: EntityLookupComponent, decorators: [{
6185
6185
  type: Component,
6186
6186
  args: [{ selector: 'fly-entity-lookup', standalone: true, imports: [CommonModule, FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: {
6187
6187
  '[class.fly-entity-lookup--down]': "placement() === 'down'",
6188
6188
  '[class.fly-entity-lookup--above]': "placement() === 'above'",
6189
- }, 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 (showCrumb()) {\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. When `lockEntity` is set the\r\n context accepts only this entity, so the button is DISABLED (the\r\n back chevron is dropped) and it reads as a static entity label. -->\r\n <button\r\n type=\"button\"\r\n class=\"fly-entity-lookup__crumb\"\r\n [class.is-locked]=\"lockEntity()\"\r\n [disabled]=\"lockEntity()\"\r\n (click)=\"goBackToEntity()\"\r\n [attr.aria-label]=\"(lockEntity() ? activeEntityLabel() : ('agent.lookup.back_aria' | translate))\">\r\n @if (!lockEntity()) {\r\n <i class=\"pi pi-angle-left fly-entity-lookup__crumb-back\" aria-hidden=\"true\"></i>\r\n }\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:100% auto;inset-inline:auto;inset-inline-end:0;margin-block:6px 0;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:auto 100%;inset-inline:0;margin-block:0 6px;z-index:1000}.fly-entity-lookup{position:absolute;inset-block-end:100%;inset-inline:12px;margin-block-end:6px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-entity-lookup{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-entity-lookup:before,.fly-entity-lookup:after{display:none}}@media(prefers-contrast:more){.fly-entity-lookup{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-entity-lookup:after{animation:none}}.fly-entity-lookup{border-radius:12px;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);outline-offset:1px}.fly-entity-lookup__crumb.is-locked{cursor:default;opacity:.85}.fly-entity-lookup__crumb.is-locked:hover{background:var(--surface-hover, rgba(255, 255, 255, .06));color:var(--text-color-secondary, rgba(255, 255, 255, .75))}[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"] }]
6189
+ }, 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 (showCrumb()) {\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. When `lockEntity` is set the\r\n context accepts only this entity, so the button is DISABLED (the\r\n back chevron is dropped) and it reads as a static entity label. -->\r\n <button\r\n type=\"button\"\r\n class=\"fly-entity-lookup__crumb\"\r\n [class.is-locked]=\"lockEntity()\"\r\n [disabled]=\"lockEntity()\"\r\n (click)=\"goBackToEntity()\"\r\n [attr.aria-label]=\"(lockEntity() ? activeEntityLabel() : ('agent.lookup.back_aria' | translate))\">\r\n @if (!lockEntity()) {\r\n <i class=\"pi pi-angle-left fly-entity-lookup__crumb-back\" aria-hidden=\"true\"></i>\r\n }\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:100% auto;inset-inline:auto;inset-inline-end:0;margin-block:6px 0;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:auto 100%;inset-inline:0;margin-block:0 6px;z-index:1000}.fly-entity-lookup{position:absolute;inset-block-end:100%;inset-inline:12px;margin-block-end:6px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-entity-lookup{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-entity-lookup:before,.fly-entity-lookup:after{display:none}}@media(prefers-contrast:more){.fly-entity-lookup{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-entity-lookup:after{animation:none}}.fly-entity-lookup{border-radius:12px;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;outline-color:var(--primary-color);outline-offset:1px}.fly-entity-lookup__crumb.is-locked{cursor:default;opacity:.85}.fly-entity-lookup__crumb.is-locked:hover{background:var(--surface-hover, rgba(255, 255, 255, .06));color:var(--text-color-secondary, rgba(255, 255, 255, .75))}[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"] }]
6190
6190
  }], 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 }] }], lockEntity: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockEntity", required: false }] }], pick: [{ type: i0.Output, args: ["pick"] }], entityLinkSelected: [{ type: i0.Output, args: ["entityLinkSelected"] }], invokeSuccess: [{ type: i0.Output, args: ["invokeSuccess"] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }], searchEl: [{
6191
6191
  type: ViewChild,
6192
6192
  args: ['searchRef']
@@ -7946,7 +7946,7 @@ class FlyEmojiPickerComponent {
7946
7946
  this.selectionChange.emit(next);
7947
7947
  }
7948
7948
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyEmojiPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7949
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyEmojiPickerComponent, isStandalone: true, selector: "fly-emoji-picker", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selectedIds: { classPropertyName: "selectedIds", publicName: "selectedIds", isSignal: true, isRequired: false, transformFunction: null }, categories: { classPropertyName: "categories", publicName: "categories", isSignal: true, isRequired: false, transformFunction: null }, defaultCategory: { classPropertyName: "defaultCategory", publicName: "defaultCategory", isSignal: true, isRequired: false, transformFunction: null }, skinTones: { classPropertyName: "skinTones", publicName: "skinTones", isSignal: true, isRequired: false, transformFunction: null }, skinTone: { classPropertyName: "skinTone", publicName: "skinTone", isSignal: true, isRequired: false, transformFunction: null }, showMore: { classPropertyName: "showMore", publicName: "showMore", isSignal: true, isRequired: false, transformFunction: null }, previewCount: { classPropertyName: "previewCount", publicName: "previewCount", isSignal: true, isRequired: false, transformFunction: null }, emojiAnimation: { classPropertyName: "emojiAnimation", publicName: "emojiAnimation", isSignal: true, isRequired: false, transformFunction: null }, dismissOnOutsidePress: { classPropertyName: "dismissOnOutsidePress", publicName: "dismissOnOutsidePress", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stickerPicked: "stickerPicked", toggled: "toggled", selectionChange: "selectionChange", skinToneChange: "skinToneChange", dismissed: "dismissed" }, host: { properties: { "class.fly-emoji-picker--small": "size() === 'small'", "class.fly-emoji-picker--medium": "size() === 'medium'", "class.fly-emoji-picker--large": "size() === 'large'" } }, viewQueries: [{ propertyName: "searchRef", first: true, predicate: ["searchRef"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\r\n class=\"fly-emoji-picker\"\r\n [flyClickOutsideEnabled]=\"dismissOnOutsidePress()\"\r\n (flyClickOutside)=\"dismissed.emit()\"\r\n [attr.aria-label]=\"'common.label.emoji_picker' | translate\">\r\n <!-- Stickers mode only: the emoji grid is unchanged, stickers are an ADDITIONAL surface. -->\r\n @if (showTabs()) {\r\n <div\r\n class=\"fly-emoji-picker__tabs\"\r\n role=\"tablist\"\r\n [attr.aria-label]=\"'common.label.emoji_tabs' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tab\"\r\n role=\"tab\"\r\n id=\"fly-emoji-tab-emoji\"\r\n aria-controls=\"fly-emoji-panel-emoji\"\r\n [class.is-active]=\"activeTab() === 'emoji'\"\r\n [attr.aria-selected]=\"activeTab() === 'emoji'\"\r\n [attr.tabindex]=\"activeTab() === 'emoji' ? 0 : -1\"\r\n (keydown)=\"onTabKeydown($event)\"\r\n (click)=\"selectTab('emoji')\">\r\n {{ 'common.label.emoji_tab_emoji' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tab\"\r\n role=\"tab\"\r\n id=\"fly-emoji-tab-stickers\"\r\n aria-controls=\"fly-emoji-panel-stickers\"\r\n [class.is-active]=\"activeTab() === 'stickers'\"\r\n [attr.aria-selected]=\"activeTab() === 'stickers'\"\r\n [attr.tabindex]=\"activeTab() === 'stickers' ? 0 : -1\"\r\n (keydown)=\"onTabKeydown($event)\"\r\n (click)=\"selectTab('stickers')\">\r\n {{ 'common.label.emoji_tab_stickers' | translate }}\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (showTabs() && activeTab() === 'stickers') {\r\n <div\r\n class=\"fly-emoji-picker__stickers\"\r\n id=\"fly-emoji-panel-stickers\"\r\n role=\"tabpanel\"\r\n aria-labelledby=\"fly-emoji-tab-stickers\">\r\n @for (entry of stickers(); track entry.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__sticker\"\r\n [flyTooltip]=\"entry.label\"\r\n [attr.aria-label]=\"entry.label\"\r\n (pointerenter)=\"onCellHover(sticker)\"\r\n (pointerleave)=\"cancelHover()\"\r\n (click)=\"pickSticker(entry)\">\r\n <fly-animated-emoji #sticker [id]=\"entry.id\" [size]=\"64\" />\r\n </button>\r\n } @empty {\r\n <p class=\"fly-emoji-picker__empty\">{{ 'agent.lookup.no_results' | translate }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n @if (!showTabs() || activeTab() === 'emoji') {\r\n <!-- Search + tone sit together as one chrome bar: the tone swatches are hands, and on their own row\r\n above the grid they read as pickable content rather than a setting. -->\r\n <div class=\"fly-emoji-picker__bar\">\r\n <input\r\n class=\"fly-emoji-picker__search\"\r\n type=\"text\"\r\n #searchRef\r\n [value]=\"query()\"\r\n (input)=\"onQueryInput(searchRef.value)\"\r\n [placeholder]=\"'common.label.search_emoji' | translate\"\r\n [attr.aria-label]=\"'common.label.search_emoji' | translate\"\r\n spellcheck=\"false\"\r\n autocomplete=\"off\" />\r\n\r\n @if (showToneStrip()) {\r\n <!-- Escape-to-close listener only \u2014 every actual control inside (trigger + options) is its\r\n own focusable button, so this wrapper itself doesn't need to be. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n class=\"fly-emoji-picker__tones\"\r\n [flyClickOutsideEnabled]=\"toneMenuOpen()\"\r\n (flyClickOutside)=\"toneMenuOpen.set(false)\"\r\n (keydown.escape)=\"toneMenuOpen.set(false)\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tone-trigger\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"toneMenuOpen()\"\r\n [attr.aria-label]=\"'common.label.skin_tone' | translate\"\r\n [flyTooltip]=\"toneLabelKey(effectiveTone()) | translate\"\r\n (click)=\"toneMenuOpen.set(!toneMenuOpen())\">\r\n <span class=\"fly-emoji-picker__tone-glyph\">{{ toneSwatch(effectiveTone()) }}</span>\r\n <i class=\"pi pi-chevron-down fly-emoji-picker__tone-caret\" aria-hidden=\"true\"></i>\r\n </button>\r\n\r\n @if (toneMenuOpen()) {\r\n <div\r\n class=\"fly-emoji-picker__tone-menu\"\r\n role=\"listbox\"\r\n [attr.aria-label]=\"'common.label.skin_tone' | translate\">\r\n @for (tone of tones; track tone) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tone-option\"\r\n role=\"option\"\r\n [class.is-active]=\"effectiveTone() === tone\"\r\n [attr.aria-selected]=\"effectiveTone() === tone\"\r\n [flyTooltip]=\"toneLabelKey(tone) | translate\"\r\n (click)=\"onToneOptionClick(tone)\">\r\n {{ toneSwatch(tone) }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- ONE scrolling list; each category is a separator label over its own grid. Tabs wrapped to three\r\n rows in a sidebar drawer and cost a click to reach any group. -->\r\n <div\r\n class=\"fly-emoji-picker__list\"\r\n role=\"listbox\"\r\n [attr.id]=\"showTabs() ? 'fly-emoji-panel-emoji' : null\"\r\n [attr.aria-labelledby]=\"showTabs() ? 'fly-emoji-tab-emoji' : null\"\r\n [attr.aria-multiselectable]=\"selectionMode() === 'multi'\">\r\n @for (section of sections(); track section.id) {\r\n <div class=\"fly-emoji-picker__section\" role=\"group\" [attr.aria-label]=\"sectionLabel(section)\">\r\n <h4 class=\"fly-emoji-picker__heading\">{{ sectionLabel(section) }}</h4>\r\n <div class=\"fly-emoji-picker__grid\">\r\n @for (cell of section.cells; track cell.entry.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__cell\"\r\n role=\"option\"\r\n [class.is-active]=\"cell.selected\"\r\n [attr.aria-selected]=\"cell.selected\"\r\n [flyTooltip]=\"cell.entry.label\"\r\n [attr.aria-label]=\"cell.entry.label\"\r\n (click)=\"pick(cell.entry)\">\r\n @if (section.animated) {\r\n <!-- Hover lives on the animated element, not the button: a template reference\r\n declared inside a control-flow block isn't visible to the block's parent. -->\r\n <fly-animated-emoji\r\n #anim\r\n class=\"fly-emoji-picker__glyph\"\r\n [id]=\"cell.entry.id\"\r\n [size]=\"20\"\r\n (pointerenter)=\"onCellHover(anim)\"\r\n (pointerleave)=\"cancelHover()\" />\r\n } @else {\r\n <span class=\"fly-emoji-picker__glyph\">{{ cell.glyph }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"fly-emoji-picker__empty\">{{ 'agent.lookup.no_results' | translate }}</p>\r\n }\r\n\r\n <!-- Lives INSIDE the scroller, as the last row, rather than pinned below it \u2014 a static\r\n footer row permanently ate into the vertical space actual emoji rows could use;\r\n scrolled into view instead, it only costs space once you reach the end. -->\r\n @if (hasMore()) {\r\n <button type=\"button\" class=\"fly-emoji-picker__more\" (click)=\"toggleExpanded()\">\r\n {{ (isExpanded() ? 'common.label.emoji_show_less' : 'common.label.emoji_show_more') | translate }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;block-size:100%;-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){:host{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}:host:before,:host:after{display:none}}@media(prefers-contrast:more){:host{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){:host:after{animation:none}}:host{--fly-emoji-cell: 36px;--fly-emoji-cell-gap: 6px;--fly-emoji-glyph: 17px;--fly-emoji-section-gap: 14px;--fly-emoji-bar-gap: 8px;--fly-emoji-search-font: 12px;--fly-emoji-search-padding: 8px 10px;--fly-emoji-heading-display: block}:host(.fly-emoji-picker--medium){--fly-emoji-cell: 30px;--fly-emoji-cell-gap: 5px;--fly-emoji-glyph: 16px;--fly-emoji-section-gap: 10px;--fly-emoji-bar-gap: 6px;--fly-emoji-search-font: 11.5px;--fly-emoji-search-padding: 6px 9px}:host(.fly-emoji-picker--small){--fly-emoji-cell: 24px;--fly-emoji-cell-gap: 3px;--fly-emoji-glyph: 15px;--fly-emoji-section-gap: 6px;--fly-emoji-bar-gap: 5px;--fly-emoji-search-font: 11px;--fly-emoji-search-padding: 4px 7px;--fly-emoji-heading-display: none;--fly-emoji-picker-list-max: 132px}.fly-emoji-picker{display:flex;flex-direction:column;gap:var(--fly-emoji-bar-gap);box-sizing:border-box;block-size:100%;color:var(--text-color, inherit)}.fly-emoji-picker__bar{display:flex;align-items:center;gap:10px}.fly-emoji-picker__search{flex:1 1 auto;min-inline-size:0;box-sizing:border-box;padding:var(--fly-emoji-search-padding);font:inherit;font-size:var(--fly-emoji-search-font);border:1px solid var(--surface-border, rgba(255, 255, 255, .12));border-radius:5px;background:transparent;color:var(--text-color, inherit);outline:none}.fly-emoji-picker__search:focus{border-color:var(--primary-color)}.fly-emoji-picker__list{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--fly-emoji-section-gap);min-block-size:0;max-block-size:var(--fly-emoji-picker-list-max, 320px);overflow-y:auto;padding-inline-end:4px}.fly-emoji-picker__section{display:flex;flex-direction:column;gap:6px}.fly-emoji-picker__heading{display:var(--fly-emoji-heading-display);position:sticky;inset-block-start:0;z-index:1;margin:0;padding-block:3px;font-size:10px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--text-color-secondary, rgba(235, 235, 245, .55));background:var(--surface-overlay, var(--surface-card, #1c1c1e))}.fly-emoji-picker__tones{position:relative;flex:0 0 auto}.fly-emoji-picker__tone-trigger{display:flex;align-items:center;gap:2px;inline-size:auto;block-size:22px;padding:0 4px;font-size:14px;line-height:1;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));border-radius:5px;background:transparent;color:var(--text-color-secondary, rgba(235, 235, 245, .55));cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__tone-trigger:hover{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__tone-trigger:focus-visible{outline:2px solid var(--primary-color);outline-offset:-1px}.fly-emoji-picker__tone-glyph{line-height:1}.fly-emoji-picker__tone-caret{font-size:8px}.fly-emoji-picker__tone-menu{position:absolute;inset-block-start:calc(100% + 4px);inset-inline-end:0;z-index:21;display:grid;grid-template-columns:repeat(3,1fr);gap:2px;padding:4px;border-radius:8px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-emoji-picker__tone-menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-emoji-picker__tone-menu:before,.fly-emoji-picker__tone-menu:after{display:none}}@media(prefers-contrast:more){.fly-emoji-picker__tone-menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-emoji-picker__tone-menu:after{animation:none}}.fly-emoji-picker__tone-option{display:grid;place-items:center;inline-size:26px;block-size:26px;padding:0;font-size:15px;line-height:1;border:1px solid transparent;border-radius:5px;background:transparent;cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__tone-option:hover{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__tone-option:focus-visible{outline:2px solid var(--primary-color);outline-offset:-1px}.fly-emoji-picker__tone-option.is-active{border-color:var(--primary-color);background:var(--surface-hover, rgba(255, 255, 255, .1))}.fly-emoji-picker__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--fly-emoji-cell),1fr));gap:var(--fly-emoji-cell-gap)}.fly-emoji-picker__cell{display:flex;align-items:center;justify-content:center;aspect-ratio:1;min-block-size:var(--fly-emoji-cell);padding:4px;border:1px solid transparent;border-radius:6px;background:transparent;color:var(--text-color, inherit);cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__cell:hover{background:var(--surface-hover, rgba(255, 255, 255, .08));border-color:var(--surface-border, rgba(255, 255, 255, .12))}.fly-emoji-picker__cell:focus-visible{outline:2px solid var(--primary-color);outline-offset:-1px}.fly-emoji-picker__cell.is-active{border-color:var(--primary-color);background:var(--selection-bg, rgba(0, 113, 227, .24))}.fly-emoji-picker__glyph{direction:ltr;font-size:var(--fly-emoji-glyph);line-height:1}.fly-emoji-picker__more{align-self:flex-start;padding:3px 8px;font:inherit;font-size:11px;border:none;border-radius:999px;background:transparent;color:var(--primary-color);cursor:pointer}.fly-emoji-picker__more:hover{background:var(--surface-hover, rgba(255, 255, 255, .06))}.fly-emoji-picker__more:focus-visible{outline:2px solid var(--primary-color);outline-offset:1px}.fly-emoji-picker__empty{margin:0;padding:12px 4px;text-align:center;font-size:12px;color:var(--text-color-secondary, rgba(235, 235, 245, .5))}.fly-emoji-picker__tabs{display:flex;gap:4px;border-block-end:1px solid var(--surface-border, rgba(255, 255, 255, .12))}.fly-emoji-picker__tab{appearance:none;padding:6px 12px;font:inherit;font-size:12px;border:none;border-block-end:2px solid transparent;background:transparent;color:var(--text-color-secondary, rgba(235, 235, 245, .6));cursor:pointer}.fly-emoji-picker__tab.is-active{color:var(--text-color, inherit);border-block-end-color:var(--primary-color)}.fly-emoji-picker__tab:focus-visible{outline:2px solid var(--primary-color);outline-offset:-2px}.fly-emoji-picker__stickers{flex:1 1 auto;min-block-size:0;overflow-y:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(72px,1fr));gap:6px;padding:4px}.fly-emoji-picker__sticker{appearance:none;display:flex;align-items:center;justify-content:center;padding:4px;border:none;border-radius:10px;background:transparent;cursor:pointer}.fly-emoji-picker__sticker:hover,.fly-emoji-picker__sticker:focus-visible{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__sticker:focus-visible{outline:2px solid var(--primary-color);outline-offset:-2px}\n"], dependencies: [{ kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled", "flyClickOutsideIgnore"], outputs: ["flyClickOutside"] }, { kind: "directive", type: FlyTooltipDirective, selector: "[flyTooltip], [data-tooltip]", inputs: ["flyTooltip", "flyTooltipPlacement", "flyTooltipDisabled", "flyTooltipDelay"] }, { kind: "component", type: FlyAnimatedEmojiComponent, selector: "fly-animated-emoji", inputs: ["id", "size", "autoplayOnFirstVisible", "playOnHover"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7949
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyEmojiPickerComponent, isStandalone: true, selector: "fly-emoji-picker", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, selectedIds: { classPropertyName: "selectedIds", publicName: "selectedIds", isSignal: true, isRequired: false, transformFunction: null }, categories: { classPropertyName: "categories", publicName: "categories", isSignal: true, isRequired: false, transformFunction: null }, defaultCategory: { classPropertyName: "defaultCategory", publicName: "defaultCategory", isSignal: true, isRequired: false, transformFunction: null }, skinTones: { classPropertyName: "skinTones", publicName: "skinTones", isSignal: true, isRequired: false, transformFunction: null }, skinTone: { classPropertyName: "skinTone", publicName: "skinTone", isSignal: true, isRequired: false, transformFunction: null }, showMore: { classPropertyName: "showMore", publicName: "showMore", isSignal: true, isRequired: false, transformFunction: null }, previewCount: { classPropertyName: "previewCount", publicName: "previewCount", isSignal: true, isRequired: false, transformFunction: null }, emojiAnimation: { classPropertyName: "emojiAnimation", publicName: "emojiAnimation", isSignal: true, isRequired: false, transformFunction: null }, dismissOnOutsidePress: { classPropertyName: "dismissOnOutsidePress", publicName: "dismissOnOutsidePress", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stickerPicked: "stickerPicked", toggled: "toggled", selectionChange: "selectionChange", skinToneChange: "skinToneChange", dismissed: "dismissed" }, host: { properties: { "class.fly-emoji-picker--small": "size() === 'small'", "class.fly-emoji-picker--medium": "size() === 'medium'", "class.fly-emoji-picker--large": "size() === 'large'" } }, viewQueries: [{ propertyName: "searchRef", first: true, predicate: ["searchRef"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\r\n class=\"fly-emoji-picker\"\r\n [flyClickOutsideEnabled]=\"dismissOnOutsidePress()\"\r\n (flyClickOutside)=\"dismissed.emit()\"\r\n [attr.aria-label]=\"'common.label.emoji_picker' | translate\">\r\n <!-- Stickers mode only: the emoji grid is unchanged, stickers are an ADDITIONAL surface. -->\r\n @if (showTabs()) {\r\n <div\r\n class=\"fly-emoji-picker__tabs\"\r\n role=\"tablist\"\r\n [attr.aria-label]=\"'common.label.emoji_tabs' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tab\"\r\n role=\"tab\"\r\n id=\"fly-emoji-tab-emoji\"\r\n aria-controls=\"fly-emoji-panel-emoji\"\r\n [class.is-active]=\"activeTab() === 'emoji'\"\r\n [attr.aria-selected]=\"activeTab() === 'emoji'\"\r\n [attr.tabindex]=\"activeTab() === 'emoji' ? 0 : -1\"\r\n (keydown)=\"onTabKeydown($event)\"\r\n (click)=\"selectTab('emoji')\">\r\n {{ 'common.label.emoji_tab_emoji' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tab\"\r\n role=\"tab\"\r\n id=\"fly-emoji-tab-stickers\"\r\n aria-controls=\"fly-emoji-panel-stickers\"\r\n [class.is-active]=\"activeTab() === 'stickers'\"\r\n [attr.aria-selected]=\"activeTab() === 'stickers'\"\r\n [attr.tabindex]=\"activeTab() === 'stickers' ? 0 : -1\"\r\n (keydown)=\"onTabKeydown($event)\"\r\n (click)=\"selectTab('stickers')\">\r\n {{ 'common.label.emoji_tab_stickers' | translate }}\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (showTabs() && activeTab() === 'stickers') {\r\n <div\r\n class=\"fly-emoji-picker__stickers\"\r\n id=\"fly-emoji-panel-stickers\"\r\n role=\"tabpanel\"\r\n aria-labelledby=\"fly-emoji-tab-stickers\">\r\n @for (entry of stickers(); track entry.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__sticker\"\r\n [flyTooltip]=\"entry.label\"\r\n [attr.aria-label]=\"entry.label\"\r\n (pointerenter)=\"onCellHover(sticker)\"\r\n (pointerleave)=\"cancelHover()\"\r\n (click)=\"pickSticker(entry)\">\r\n <fly-animated-emoji #sticker [id]=\"entry.id\" [size]=\"64\" />\r\n </button>\r\n } @empty {\r\n <p class=\"fly-emoji-picker__empty\">{{ 'agent.lookup.no_results' | translate }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n @if (!showTabs() || activeTab() === 'emoji') {\r\n <!-- Search + tone sit together as one chrome bar: the tone swatches are hands, and on their own row\r\n above the grid they read as pickable content rather than a setting. -->\r\n <div class=\"fly-emoji-picker__bar\">\r\n <input\r\n class=\"fly-emoji-picker__search\"\r\n type=\"text\"\r\n #searchRef\r\n [value]=\"query()\"\r\n (input)=\"onQueryInput(searchRef.value)\"\r\n [placeholder]=\"'common.label.search_emoji' | translate\"\r\n [attr.aria-label]=\"'common.label.search_emoji' | translate\"\r\n spellcheck=\"false\"\r\n autocomplete=\"off\" />\r\n\r\n @if (showToneStrip()) {\r\n <!-- Escape-to-close listener only \u2014 every actual control inside (trigger + options) is its\r\n own focusable button, so this wrapper itself doesn't need to be. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n class=\"fly-emoji-picker__tones\"\r\n [flyClickOutsideEnabled]=\"toneMenuOpen()\"\r\n (flyClickOutside)=\"toneMenuOpen.set(false)\"\r\n (keydown.escape)=\"toneMenuOpen.set(false)\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tone-trigger\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"toneMenuOpen()\"\r\n [attr.aria-label]=\"'common.label.skin_tone' | translate\"\r\n [flyTooltip]=\"toneLabelKey(effectiveTone()) | translate\"\r\n (click)=\"toneMenuOpen.set(!toneMenuOpen())\">\r\n <span class=\"fly-emoji-picker__tone-glyph\">{{ toneSwatch(effectiveTone()) }}</span>\r\n <i class=\"pi pi-chevron-down fly-emoji-picker__tone-caret\" aria-hidden=\"true\"></i>\r\n </button>\r\n\r\n @if (toneMenuOpen()) {\r\n <div\r\n class=\"fly-emoji-picker__tone-menu\"\r\n role=\"listbox\"\r\n [attr.aria-label]=\"'common.label.skin_tone' | translate\">\r\n @for (tone of tones; track tone) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tone-option\"\r\n role=\"option\"\r\n [class.is-active]=\"effectiveTone() === tone\"\r\n [attr.aria-selected]=\"effectiveTone() === tone\"\r\n [flyTooltip]=\"toneLabelKey(tone) | translate\"\r\n (click)=\"onToneOptionClick(tone)\">\r\n {{ toneSwatch(tone) }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- ONE scrolling list; each category is a separator label over its own grid. Tabs wrapped to three\r\n rows in a sidebar drawer and cost a click to reach any group. -->\r\n <div\r\n class=\"fly-emoji-picker__list\"\r\n role=\"listbox\"\r\n [attr.id]=\"showTabs() ? 'fly-emoji-panel-emoji' : null\"\r\n [attr.aria-labelledby]=\"showTabs() ? 'fly-emoji-tab-emoji' : null\"\r\n [attr.aria-multiselectable]=\"selectionMode() === 'multi'\">\r\n @for (section of sections(); track section.id) {\r\n <div class=\"fly-emoji-picker__section\" role=\"group\" [attr.aria-label]=\"sectionLabel(section)\">\r\n <h4 class=\"fly-emoji-picker__heading\">{{ sectionLabel(section) }}</h4>\r\n <div class=\"fly-emoji-picker__grid\">\r\n @for (cell of section.cells; track cell.entry.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__cell\"\r\n role=\"option\"\r\n [class.is-active]=\"cell.selected\"\r\n [attr.aria-selected]=\"cell.selected\"\r\n [flyTooltip]=\"cell.entry.label\"\r\n [attr.aria-label]=\"cell.entry.label\"\r\n (click)=\"pick(cell.entry)\">\r\n @if (section.animated) {\r\n <!-- Hover lives on the animated element, not the button: a template reference\r\n declared inside a control-flow block isn't visible to the block's parent. -->\r\n <fly-animated-emoji\r\n #anim\r\n class=\"fly-emoji-picker__glyph\"\r\n [id]=\"cell.entry.id\"\r\n [size]=\"20\"\r\n (pointerenter)=\"onCellHover(anim)\"\r\n (pointerleave)=\"cancelHover()\" />\r\n } @else {\r\n <span class=\"fly-emoji-picker__glyph\">{{ cell.glyph }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"fly-emoji-picker__empty\">{{ 'agent.lookup.no_results' | translate }}</p>\r\n }\r\n\r\n <!-- Lives INSIDE the scroller, as the last row, rather than pinned below it \u2014 a static\r\n footer row permanently ate into the vertical space actual emoji rows could use;\r\n scrolled into view instead, it only costs space once you reach the end. -->\r\n @if (hasMore()) {\r\n <button type=\"button\" class=\"fly-emoji-picker__more\" (click)=\"toggleExpanded()\">\r\n {{ (isExpanded() ? 'common.label.emoji_show_less' : 'common.label.emoji_show_more') | translate }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;block-size:100%;-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){:host{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}:host:before,:host:after{display:none}}@media(prefers-contrast:more){:host{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){:host:after{animation:none}}:host{--fly-emoji-cell: 36px;--fly-emoji-cell-gap: 6px;--fly-emoji-glyph: 17px;--fly-emoji-section-gap: 14px;--fly-emoji-bar-gap: 8px;--fly-emoji-search-font: 12px;--fly-emoji-search-padding: 8px 10px;--fly-emoji-heading-display: block}:host(.fly-emoji-picker--medium){--fly-emoji-cell: 30px;--fly-emoji-cell-gap: 5px;--fly-emoji-glyph: 16px;--fly-emoji-section-gap: 10px;--fly-emoji-bar-gap: 6px;--fly-emoji-search-font: 11.5px;--fly-emoji-search-padding: 6px 9px}:host(.fly-emoji-picker--small){--fly-emoji-cell: 24px;--fly-emoji-cell-gap: 3px;--fly-emoji-glyph: 15px;--fly-emoji-section-gap: 6px;--fly-emoji-bar-gap: 5px;--fly-emoji-search-font: 11px;--fly-emoji-search-padding: 4px 7px;--fly-emoji-heading-display: none;--fly-emoji-picker-list-max: 132px}.fly-emoji-picker{display:flex;flex-direction:column;gap:var(--fly-emoji-bar-gap);box-sizing:border-box;block-size:100%;color:var(--text-color, inherit)}.fly-emoji-picker__bar{display:flex;align-items:center;gap:10px}.fly-emoji-picker__search{flex:1 1 auto;min-inline-size:0;box-sizing:border-box;padding:var(--fly-emoji-search-padding);font:inherit;font-size:var(--fly-emoji-search-font);border:1px solid var(--surface-border, rgba(255, 255, 255, .12));border-radius:5px;background:transparent;color:var(--text-color, inherit);outline:none}.fly-emoji-picker__search:focus{border-color:var(--primary-color)}.fly-emoji-picker__list{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--fly-emoji-section-gap);min-block-size:0;max-block-size:var(--fly-emoji-picker-list-max, 320px);overflow-y:auto;padding-inline-end:4px}.fly-emoji-picker__section{display:flex;flex-direction:column;gap:6px}.fly-emoji-picker__heading{display:var(--fly-emoji-heading-display);position:sticky;inset-block-start:0;z-index:1;margin:0;padding-block:3px;font-size:10px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--text-color-secondary, rgba(235, 235, 245, .55));background:var(--surface-overlay, var(--surface-card, #1c1c1e))}.fly-emoji-picker__tones{position:relative;flex:0 0 auto}.fly-emoji-picker__tone-trigger{display:flex;align-items:center;gap:2px;inline-size:auto;block-size:22px;padding:0 4px;font-size:14px;line-height:1;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));border-radius:5px;background:transparent;color:var(--text-color-secondary, rgba(235, 235, 245, .55));cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__tone-trigger:hover{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__tone-trigger:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-1px}.fly-emoji-picker__tone-glyph{line-height:1}.fly-emoji-picker__tone-caret{font-size:8px}.fly-emoji-picker__tone-menu{position:absolute;inset-block-start:calc(100% + 4px);inset-inline-end:0;z-index:21;display:grid;grid-template-columns:repeat(3,1fr);gap:2px;padding:4px;border-radius:8px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-emoji-picker__tone-menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-emoji-picker__tone-menu:before,.fly-emoji-picker__tone-menu:after{display:none}}@media(prefers-contrast:more){.fly-emoji-picker__tone-menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-emoji-picker__tone-menu:after{animation:none}}.fly-emoji-picker__tone-option{display:grid;place-items:center;inline-size:26px;block-size:26px;padding:0;font-size:15px;line-height:1;border:1px solid transparent;border-radius:5px;background:transparent;cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__tone-option:hover{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__tone-option:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-1px}.fly-emoji-picker__tone-option.is-active{border-color:var(--primary-color);background:var(--surface-hover, rgba(255, 255, 255, .1))}.fly-emoji-picker__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--fly-emoji-cell),1fr));gap:var(--fly-emoji-cell-gap)}.fly-emoji-picker__cell{display:flex;align-items:center;justify-content:center;aspect-ratio:1;min-block-size:var(--fly-emoji-cell);padding:4px;border:1px solid transparent;border-radius:6px;background:transparent;color:var(--text-color, inherit);cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__cell:hover{background:var(--surface-hover, rgba(255, 255, 255, .08));border-color:var(--surface-border, rgba(255, 255, 255, .12))}.fly-emoji-picker__cell:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-1px}.fly-emoji-picker__cell.is-active{border-color:var(--primary-color);background:var(--selection-bg, rgba(0, 113, 227, .24))}.fly-emoji-picker__glyph{direction:ltr;font-size:var(--fly-emoji-glyph);line-height:1}.fly-emoji-picker__more{align-self:flex-start;padding:3px 8px;font:inherit;font-size:11px;border:none;border-radius:999px;background:transparent;color:var(--primary-color);cursor:pointer}.fly-emoji-picker__more:hover{background:var(--surface-hover, rgba(255, 255, 255, .06))}.fly-emoji-picker__more:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:1px}.fly-emoji-picker__empty{margin:0;padding:12px 4px;text-align:center;font-size:12px;color:var(--text-color-secondary, rgba(235, 235, 245, .5))}.fly-emoji-picker__tabs{display:flex;gap:4px;border-block-end:1px solid var(--surface-border, rgba(255, 255, 255, .12))}.fly-emoji-picker__tab{appearance:none;padding:6px 12px;font:inherit;font-size:12px;border:none;border-block-end:2px solid transparent;background:transparent;color:var(--text-color-secondary, rgba(235, 235, 245, .6));cursor:pointer}.fly-emoji-picker__tab.is-active{color:var(--text-color, inherit);border-block-end-color:var(--primary-color)}.fly-emoji-picker__tab:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-2px}.fly-emoji-picker__stickers{flex:1 1 auto;min-block-size:0;overflow-y:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(72px,1fr));gap:6px;padding:4px}.fly-emoji-picker__sticker{appearance:none;display:flex;align-items:center;justify-content:center;padding:4px;border:none;border-radius:10px;background:transparent;cursor:pointer}.fly-emoji-picker__sticker:hover,.fly-emoji-picker__sticker:focus-visible{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__sticker:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-2px}\n"], dependencies: [{ kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled", "flyClickOutsideIgnore"], outputs: ["flyClickOutside"] }, { kind: "directive", type: FlyTooltipDirective, selector: "[flyTooltip], [data-tooltip]", inputs: ["flyTooltip", "flyTooltipPlacement", "flyTooltipDisabled", "flyTooltipDelay"] }, { kind: "component", type: FlyAnimatedEmojiComponent, selector: "fly-animated-emoji", inputs: ["id", "size", "autoplayOnFirstVisible", "playOnHover"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7950
7950
  }
7951
7951
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyEmojiPickerComponent, decorators: [{
7952
7952
  type: Component,
@@ -7957,7 +7957,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
7957
7957
  '[class.fly-emoji-picker--small]': "size() === 'small'",
7958
7958
  '[class.fly-emoji-picker--medium]': "size() === 'medium'",
7959
7959
  '[class.fly-emoji-picker--large]': "size() === 'large'",
7960
- }, template: "<div\r\n class=\"fly-emoji-picker\"\r\n [flyClickOutsideEnabled]=\"dismissOnOutsidePress()\"\r\n (flyClickOutside)=\"dismissed.emit()\"\r\n [attr.aria-label]=\"'common.label.emoji_picker' | translate\">\r\n <!-- Stickers mode only: the emoji grid is unchanged, stickers are an ADDITIONAL surface. -->\r\n @if (showTabs()) {\r\n <div\r\n class=\"fly-emoji-picker__tabs\"\r\n role=\"tablist\"\r\n [attr.aria-label]=\"'common.label.emoji_tabs' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tab\"\r\n role=\"tab\"\r\n id=\"fly-emoji-tab-emoji\"\r\n aria-controls=\"fly-emoji-panel-emoji\"\r\n [class.is-active]=\"activeTab() === 'emoji'\"\r\n [attr.aria-selected]=\"activeTab() === 'emoji'\"\r\n [attr.tabindex]=\"activeTab() === 'emoji' ? 0 : -1\"\r\n (keydown)=\"onTabKeydown($event)\"\r\n (click)=\"selectTab('emoji')\">\r\n {{ 'common.label.emoji_tab_emoji' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tab\"\r\n role=\"tab\"\r\n id=\"fly-emoji-tab-stickers\"\r\n aria-controls=\"fly-emoji-panel-stickers\"\r\n [class.is-active]=\"activeTab() === 'stickers'\"\r\n [attr.aria-selected]=\"activeTab() === 'stickers'\"\r\n [attr.tabindex]=\"activeTab() === 'stickers' ? 0 : -1\"\r\n (keydown)=\"onTabKeydown($event)\"\r\n (click)=\"selectTab('stickers')\">\r\n {{ 'common.label.emoji_tab_stickers' | translate }}\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (showTabs() && activeTab() === 'stickers') {\r\n <div\r\n class=\"fly-emoji-picker__stickers\"\r\n id=\"fly-emoji-panel-stickers\"\r\n role=\"tabpanel\"\r\n aria-labelledby=\"fly-emoji-tab-stickers\">\r\n @for (entry of stickers(); track entry.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__sticker\"\r\n [flyTooltip]=\"entry.label\"\r\n [attr.aria-label]=\"entry.label\"\r\n (pointerenter)=\"onCellHover(sticker)\"\r\n (pointerleave)=\"cancelHover()\"\r\n (click)=\"pickSticker(entry)\">\r\n <fly-animated-emoji #sticker [id]=\"entry.id\" [size]=\"64\" />\r\n </button>\r\n } @empty {\r\n <p class=\"fly-emoji-picker__empty\">{{ 'agent.lookup.no_results' | translate }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n @if (!showTabs() || activeTab() === 'emoji') {\r\n <!-- Search + tone sit together as one chrome bar: the tone swatches are hands, and on their own row\r\n above the grid they read as pickable content rather than a setting. -->\r\n <div class=\"fly-emoji-picker__bar\">\r\n <input\r\n class=\"fly-emoji-picker__search\"\r\n type=\"text\"\r\n #searchRef\r\n [value]=\"query()\"\r\n (input)=\"onQueryInput(searchRef.value)\"\r\n [placeholder]=\"'common.label.search_emoji' | translate\"\r\n [attr.aria-label]=\"'common.label.search_emoji' | translate\"\r\n spellcheck=\"false\"\r\n autocomplete=\"off\" />\r\n\r\n @if (showToneStrip()) {\r\n <!-- Escape-to-close listener only \u2014 every actual control inside (trigger + options) is its\r\n own focusable button, so this wrapper itself doesn't need to be. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n class=\"fly-emoji-picker__tones\"\r\n [flyClickOutsideEnabled]=\"toneMenuOpen()\"\r\n (flyClickOutside)=\"toneMenuOpen.set(false)\"\r\n (keydown.escape)=\"toneMenuOpen.set(false)\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tone-trigger\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"toneMenuOpen()\"\r\n [attr.aria-label]=\"'common.label.skin_tone' | translate\"\r\n [flyTooltip]=\"toneLabelKey(effectiveTone()) | translate\"\r\n (click)=\"toneMenuOpen.set(!toneMenuOpen())\">\r\n <span class=\"fly-emoji-picker__tone-glyph\">{{ toneSwatch(effectiveTone()) }}</span>\r\n <i class=\"pi pi-chevron-down fly-emoji-picker__tone-caret\" aria-hidden=\"true\"></i>\r\n </button>\r\n\r\n @if (toneMenuOpen()) {\r\n <div\r\n class=\"fly-emoji-picker__tone-menu\"\r\n role=\"listbox\"\r\n [attr.aria-label]=\"'common.label.skin_tone' | translate\">\r\n @for (tone of tones; track tone) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tone-option\"\r\n role=\"option\"\r\n [class.is-active]=\"effectiveTone() === tone\"\r\n [attr.aria-selected]=\"effectiveTone() === tone\"\r\n [flyTooltip]=\"toneLabelKey(tone) | translate\"\r\n (click)=\"onToneOptionClick(tone)\">\r\n {{ toneSwatch(tone) }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- ONE scrolling list; each category is a separator label over its own grid. Tabs wrapped to three\r\n rows in a sidebar drawer and cost a click to reach any group. -->\r\n <div\r\n class=\"fly-emoji-picker__list\"\r\n role=\"listbox\"\r\n [attr.id]=\"showTabs() ? 'fly-emoji-panel-emoji' : null\"\r\n [attr.aria-labelledby]=\"showTabs() ? 'fly-emoji-tab-emoji' : null\"\r\n [attr.aria-multiselectable]=\"selectionMode() === 'multi'\">\r\n @for (section of sections(); track section.id) {\r\n <div class=\"fly-emoji-picker__section\" role=\"group\" [attr.aria-label]=\"sectionLabel(section)\">\r\n <h4 class=\"fly-emoji-picker__heading\">{{ sectionLabel(section) }}</h4>\r\n <div class=\"fly-emoji-picker__grid\">\r\n @for (cell of section.cells; track cell.entry.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__cell\"\r\n role=\"option\"\r\n [class.is-active]=\"cell.selected\"\r\n [attr.aria-selected]=\"cell.selected\"\r\n [flyTooltip]=\"cell.entry.label\"\r\n [attr.aria-label]=\"cell.entry.label\"\r\n (click)=\"pick(cell.entry)\">\r\n @if (section.animated) {\r\n <!-- Hover lives on the animated element, not the button: a template reference\r\n declared inside a control-flow block isn't visible to the block's parent. -->\r\n <fly-animated-emoji\r\n #anim\r\n class=\"fly-emoji-picker__glyph\"\r\n [id]=\"cell.entry.id\"\r\n [size]=\"20\"\r\n (pointerenter)=\"onCellHover(anim)\"\r\n (pointerleave)=\"cancelHover()\" />\r\n } @else {\r\n <span class=\"fly-emoji-picker__glyph\">{{ cell.glyph }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"fly-emoji-picker__empty\">{{ 'agent.lookup.no_results' | translate }}</p>\r\n }\r\n\r\n <!-- Lives INSIDE the scroller, as the last row, rather than pinned below it \u2014 a static\r\n footer row permanently ate into the vertical space actual emoji rows could use;\r\n scrolled into view instead, it only costs space once you reach the end. -->\r\n @if (hasMore()) {\r\n <button type=\"button\" class=\"fly-emoji-picker__more\" (click)=\"toggleExpanded()\">\r\n {{ (isExpanded() ? 'common.label.emoji_show_less' : 'common.label.emoji_show_more') | translate }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;block-size:100%;-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){:host{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}:host:before,:host:after{display:none}}@media(prefers-contrast:more){:host{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){:host:after{animation:none}}:host{--fly-emoji-cell: 36px;--fly-emoji-cell-gap: 6px;--fly-emoji-glyph: 17px;--fly-emoji-section-gap: 14px;--fly-emoji-bar-gap: 8px;--fly-emoji-search-font: 12px;--fly-emoji-search-padding: 8px 10px;--fly-emoji-heading-display: block}:host(.fly-emoji-picker--medium){--fly-emoji-cell: 30px;--fly-emoji-cell-gap: 5px;--fly-emoji-glyph: 16px;--fly-emoji-section-gap: 10px;--fly-emoji-bar-gap: 6px;--fly-emoji-search-font: 11.5px;--fly-emoji-search-padding: 6px 9px}:host(.fly-emoji-picker--small){--fly-emoji-cell: 24px;--fly-emoji-cell-gap: 3px;--fly-emoji-glyph: 15px;--fly-emoji-section-gap: 6px;--fly-emoji-bar-gap: 5px;--fly-emoji-search-font: 11px;--fly-emoji-search-padding: 4px 7px;--fly-emoji-heading-display: none;--fly-emoji-picker-list-max: 132px}.fly-emoji-picker{display:flex;flex-direction:column;gap:var(--fly-emoji-bar-gap);box-sizing:border-box;block-size:100%;color:var(--text-color, inherit)}.fly-emoji-picker__bar{display:flex;align-items:center;gap:10px}.fly-emoji-picker__search{flex:1 1 auto;min-inline-size:0;box-sizing:border-box;padding:var(--fly-emoji-search-padding);font:inherit;font-size:var(--fly-emoji-search-font);border:1px solid var(--surface-border, rgba(255, 255, 255, .12));border-radius:5px;background:transparent;color:var(--text-color, inherit);outline:none}.fly-emoji-picker__search:focus{border-color:var(--primary-color)}.fly-emoji-picker__list{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--fly-emoji-section-gap);min-block-size:0;max-block-size:var(--fly-emoji-picker-list-max, 320px);overflow-y:auto;padding-inline-end:4px}.fly-emoji-picker__section{display:flex;flex-direction:column;gap:6px}.fly-emoji-picker__heading{display:var(--fly-emoji-heading-display);position:sticky;inset-block-start:0;z-index:1;margin:0;padding-block:3px;font-size:10px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--text-color-secondary, rgba(235, 235, 245, .55));background:var(--surface-overlay, var(--surface-card, #1c1c1e))}.fly-emoji-picker__tones{position:relative;flex:0 0 auto}.fly-emoji-picker__tone-trigger{display:flex;align-items:center;gap:2px;inline-size:auto;block-size:22px;padding:0 4px;font-size:14px;line-height:1;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));border-radius:5px;background:transparent;color:var(--text-color-secondary, rgba(235, 235, 245, .55));cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__tone-trigger:hover{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__tone-trigger:focus-visible{outline:2px solid var(--primary-color);outline-offset:-1px}.fly-emoji-picker__tone-glyph{line-height:1}.fly-emoji-picker__tone-caret{font-size:8px}.fly-emoji-picker__tone-menu{position:absolute;inset-block-start:calc(100% + 4px);inset-inline-end:0;z-index:21;display:grid;grid-template-columns:repeat(3,1fr);gap:2px;padding:4px;border-radius:8px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-emoji-picker__tone-menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-emoji-picker__tone-menu:before,.fly-emoji-picker__tone-menu:after{display:none}}@media(prefers-contrast:more){.fly-emoji-picker__tone-menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-emoji-picker__tone-menu:after{animation:none}}.fly-emoji-picker__tone-option{display:grid;place-items:center;inline-size:26px;block-size:26px;padding:0;font-size:15px;line-height:1;border:1px solid transparent;border-radius:5px;background:transparent;cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__tone-option:hover{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__tone-option:focus-visible{outline:2px solid var(--primary-color);outline-offset:-1px}.fly-emoji-picker__tone-option.is-active{border-color:var(--primary-color);background:var(--surface-hover, rgba(255, 255, 255, .1))}.fly-emoji-picker__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--fly-emoji-cell),1fr));gap:var(--fly-emoji-cell-gap)}.fly-emoji-picker__cell{display:flex;align-items:center;justify-content:center;aspect-ratio:1;min-block-size:var(--fly-emoji-cell);padding:4px;border:1px solid transparent;border-radius:6px;background:transparent;color:var(--text-color, inherit);cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__cell:hover{background:var(--surface-hover, rgba(255, 255, 255, .08));border-color:var(--surface-border, rgba(255, 255, 255, .12))}.fly-emoji-picker__cell:focus-visible{outline:2px solid var(--primary-color);outline-offset:-1px}.fly-emoji-picker__cell.is-active{border-color:var(--primary-color);background:var(--selection-bg, rgba(0, 113, 227, .24))}.fly-emoji-picker__glyph{direction:ltr;font-size:var(--fly-emoji-glyph);line-height:1}.fly-emoji-picker__more{align-self:flex-start;padding:3px 8px;font:inherit;font-size:11px;border:none;border-radius:999px;background:transparent;color:var(--primary-color);cursor:pointer}.fly-emoji-picker__more:hover{background:var(--surface-hover, rgba(255, 255, 255, .06))}.fly-emoji-picker__more:focus-visible{outline:2px solid var(--primary-color);outline-offset:1px}.fly-emoji-picker__empty{margin:0;padding:12px 4px;text-align:center;font-size:12px;color:var(--text-color-secondary, rgba(235, 235, 245, .5))}.fly-emoji-picker__tabs{display:flex;gap:4px;border-block-end:1px solid var(--surface-border, rgba(255, 255, 255, .12))}.fly-emoji-picker__tab{appearance:none;padding:6px 12px;font:inherit;font-size:12px;border:none;border-block-end:2px solid transparent;background:transparent;color:var(--text-color-secondary, rgba(235, 235, 245, .6));cursor:pointer}.fly-emoji-picker__tab.is-active{color:var(--text-color, inherit);border-block-end-color:var(--primary-color)}.fly-emoji-picker__tab:focus-visible{outline:2px solid var(--primary-color);outline-offset:-2px}.fly-emoji-picker__stickers{flex:1 1 auto;min-block-size:0;overflow-y:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(72px,1fr));gap:6px;padding:4px}.fly-emoji-picker__sticker{appearance:none;display:flex;align-items:center;justify-content:center;padding:4px;border:none;border-radius:10px;background:transparent;cursor:pointer}.fly-emoji-picker__sticker:hover,.fly-emoji-picker__sticker:focus-visible{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__sticker:focus-visible{outline:2px solid var(--primary-color);outline-offset:-2px}\n"] }]
7960
+ }, template: "<div\r\n class=\"fly-emoji-picker\"\r\n [flyClickOutsideEnabled]=\"dismissOnOutsidePress()\"\r\n (flyClickOutside)=\"dismissed.emit()\"\r\n [attr.aria-label]=\"'common.label.emoji_picker' | translate\">\r\n <!-- Stickers mode only: the emoji grid is unchanged, stickers are an ADDITIONAL surface. -->\r\n @if (showTabs()) {\r\n <div\r\n class=\"fly-emoji-picker__tabs\"\r\n role=\"tablist\"\r\n [attr.aria-label]=\"'common.label.emoji_tabs' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tab\"\r\n role=\"tab\"\r\n id=\"fly-emoji-tab-emoji\"\r\n aria-controls=\"fly-emoji-panel-emoji\"\r\n [class.is-active]=\"activeTab() === 'emoji'\"\r\n [attr.aria-selected]=\"activeTab() === 'emoji'\"\r\n [attr.tabindex]=\"activeTab() === 'emoji' ? 0 : -1\"\r\n (keydown)=\"onTabKeydown($event)\"\r\n (click)=\"selectTab('emoji')\">\r\n {{ 'common.label.emoji_tab_emoji' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tab\"\r\n role=\"tab\"\r\n id=\"fly-emoji-tab-stickers\"\r\n aria-controls=\"fly-emoji-panel-stickers\"\r\n [class.is-active]=\"activeTab() === 'stickers'\"\r\n [attr.aria-selected]=\"activeTab() === 'stickers'\"\r\n [attr.tabindex]=\"activeTab() === 'stickers' ? 0 : -1\"\r\n (keydown)=\"onTabKeydown($event)\"\r\n (click)=\"selectTab('stickers')\">\r\n {{ 'common.label.emoji_tab_stickers' | translate }}\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (showTabs() && activeTab() === 'stickers') {\r\n <div\r\n class=\"fly-emoji-picker__stickers\"\r\n id=\"fly-emoji-panel-stickers\"\r\n role=\"tabpanel\"\r\n aria-labelledby=\"fly-emoji-tab-stickers\">\r\n @for (entry of stickers(); track entry.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__sticker\"\r\n [flyTooltip]=\"entry.label\"\r\n [attr.aria-label]=\"entry.label\"\r\n (pointerenter)=\"onCellHover(sticker)\"\r\n (pointerleave)=\"cancelHover()\"\r\n (click)=\"pickSticker(entry)\">\r\n <fly-animated-emoji #sticker [id]=\"entry.id\" [size]=\"64\" />\r\n </button>\r\n } @empty {\r\n <p class=\"fly-emoji-picker__empty\">{{ 'agent.lookup.no_results' | translate }}</p>\r\n }\r\n </div>\r\n }\r\n\r\n @if (!showTabs() || activeTab() === 'emoji') {\r\n <!-- Search + tone sit together as one chrome bar: the tone swatches are hands, and on their own row\r\n above the grid they read as pickable content rather than a setting. -->\r\n <div class=\"fly-emoji-picker__bar\">\r\n <input\r\n class=\"fly-emoji-picker__search\"\r\n type=\"text\"\r\n #searchRef\r\n [value]=\"query()\"\r\n (input)=\"onQueryInput(searchRef.value)\"\r\n [placeholder]=\"'common.label.search_emoji' | translate\"\r\n [attr.aria-label]=\"'common.label.search_emoji' | translate\"\r\n spellcheck=\"false\"\r\n autocomplete=\"off\" />\r\n\r\n @if (showToneStrip()) {\r\n <!-- Escape-to-close listener only \u2014 every actual control inside (trigger + options) is its\r\n own focusable button, so this wrapper itself doesn't need to be. -->\r\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\r\n <div\r\n class=\"fly-emoji-picker__tones\"\r\n [flyClickOutsideEnabled]=\"toneMenuOpen()\"\r\n (flyClickOutside)=\"toneMenuOpen.set(false)\"\r\n (keydown.escape)=\"toneMenuOpen.set(false)\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tone-trigger\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"toneMenuOpen()\"\r\n [attr.aria-label]=\"'common.label.skin_tone' | translate\"\r\n [flyTooltip]=\"toneLabelKey(effectiveTone()) | translate\"\r\n (click)=\"toneMenuOpen.set(!toneMenuOpen())\">\r\n <span class=\"fly-emoji-picker__tone-glyph\">{{ toneSwatch(effectiveTone()) }}</span>\r\n <i class=\"pi pi-chevron-down fly-emoji-picker__tone-caret\" aria-hidden=\"true\"></i>\r\n </button>\r\n\r\n @if (toneMenuOpen()) {\r\n <div\r\n class=\"fly-emoji-picker__tone-menu\"\r\n role=\"listbox\"\r\n [attr.aria-label]=\"'common.label.skin_tone' | translate\">\r\n @for (tone of tones; track tone) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__tone-option\"\r\n role=\"option\"\r\n [class.is-active]=\"effectiveTone() === tone\"\r\n [attr.aria-selected]=\"effectiveTone() === tone\"\r\n [flyTooltip]=\"toneLabelKey(tone) | translate\"\r\n (click)=\"onToneOptionClick(tone)\">\r\n {{ toneSwatch(tone) }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- ONE scrolling list; each category is a separator label over its own grid. Tabs wrapped to three\r\n rows in a sidebar drawer and cost a click to reach any group. -->\r\n <div\r\n class=\"fly-emoji-picker__list\"\r\n role=\"listbox\"\r\n [attr.id]=\"showTabs() ? 'fly-emoji-panel-emoji' : null\"\r\n [attr.aria-labelledby]=\"showTabs() ? 'fly-emoji-tab-emoji' : null\"\r\n [attr.aria-multiselectable]=\"selectionMode() === 'multi'\">\r\n @for (section of sections(); track section.id) {\r\n <div class=\"fly-emoji-picker__section\" role=\"group\" [attr.aria-label]=\"sectionLabel(section)\">\r\n <h4 class=\"fly-emoji-picker__heading\">{{ sectionLabel(section) }}</h4>\r\n <div class=\"fly-emoji-picker__grid\">\r\n @for (cell of section.cells; track cell.entry.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-emoji-picker__cell\"\r\n role=\"option\"\r\n [class.is-active]=\"cell.selected\"\r\n [attr.aria-selected]=\"cell.selected\"\r\n [flyTooltip]=\"cell.entry.label\"\r\n [attr.aria-label]=\"cell.entry.label\"\r\n (click)=\"pick(cell.entry)\">\r\n @if (section.animated) {\r\n <!-- Hover lives on the animated element, not the button: a template reference\r\n declared inside a control-flow block isn't visible to the block's parent. -->\r\n <fly-animated-emoji\r\n #anim\r\n class=\"fly-emoji-picker__glyph\"\r\n [id]=\"cell.entry.id\"\r\n [size]=\"20\"\r\n (pointerenter)=\"onCellHover(anim)\"\r\n (pointerleave)=\"cancelHover()\" />\r\n } @else {\r\n <span class=\"fly-emoji-picker__glyph\">{{ cell.glyph }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n } @empty {\r\n <p class=\"fly-emoji-picker__empty\">{{ 'agent.lookup.no_results' | translate }}</p>\r\n }\r\n\r\n <!-- Lives INSIDE the scroller, as the last row, rather than pinned below it \u2014 a static\r\n footer row permanently ate into the vertical space actual emoji rows could use;\r\n scrolled into view instead, it only costs space once you reach the end. -->\r\n @if (hasMore()) {\r\n <button type=\"button\" class=\"fly-emoji-picker__more\" (click)=\"toggleExpanded()\">\r\n {{ (isExpanded() ? 'common.label.emoji_show_less' : 'common.label.emoji_show_more') | translate }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;block-size:100%;-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){:host{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}:host:before,:host:after{display:none}}@media(prefers-contrast:more){:host{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){:host:after{animation:none}}:host{--fly-emoji-cell: 36px;--fly-emoji-cell-gap: 6px;--fly-emoji-glyph: 17px;--fly-emoji-section-gap: 14px;--fly-emoji-bar-gap: 8px;--fly-emoji-search-font: 12px;--fly-emoji-search-padding: 8px 10px;--fly-emoji-heading-display: block}:host(.fly-emoji-picker--medium){--fly-emoji-cell: 30px;--fly-emoji-cell-gap: 5px;--fly-emoji-glyph: 16px;--fly-emoji-section-gap: 10px;--fly-emoji-bar-gap: 6px;--fly-emoji-search-font: 11.5px;--fly-emoji-search-padding: 6px 9px}:host(.fly-emoji-picker--small){--fly-emoji-cell: 24px;--fly-emoji-cell-gap: 3px;--fly-emoji-glyph: 15px;--fly-emoji-section-gap: 6px;--fly-emoji-bar-gap: 5px;--fly-emoji-search-font: 11px;--fly-emoji-search-padding: 4px 7px;--fly-emoji-heading-display: none;--fly-emoji-picker-list-max: 132px}.fly-emoji-picker{display:flex;flex-direction:column;gap:var(--fly-emoji-bar-gap);box-sizing:border-box;block-size:100%;color:var(--text-color, inherit)}.fly-emoji-picker__bar{display:flex;align-items:center;gap:10px}.fly-emoji-picker__search{flex:1 1 auto;min-inline-size:0;box-sizing:border-box;padding:var(--fly-emoji-search-padding);font:inherit;font-size:var(--fly-emoji-search-font);border:1px solid var(--surface-border, rgba(255, 255, 255, .12));border-radius:5px;background:transparent;color:var(--text-color, inherit);outline:none}.fly-emoji-picker__search:focus{border-color:var(--primary-color)}.fly-emoji-picker__list{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--fly-emoji-section-gap);min-block-size:0;max-block-size:var(--fly-emoji-picker-list-max, 320px);overflow-y:auto;padding-inline-end:4px}.fly-emoji-picker__section{display:flex;flex-direction:column;gap:6px}.fly-emoji-picker__heading{display:var(--fly-emoji-heading-display);position:sticky;inset-block-start:0;z-index:1;margin:0;padding-block:3px;font-size:10px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--text-color-secondary, rgba(235, 235, 245, .55));background:var(--surface-overlay, var(--surface-card, #1c1c1e))}.fly-emoji-picker__tones{position:relative;flex:0 0 auto}.fly-emoji-picker__tone-trigger{display:flex;align-items:center;gap:2px;inline-size:auto;block-size:22px;padding:0 4px;font-size:14px;line-height:1;border:1px solid var(--surface-border, rgba(255, 255, 255, .12));border-radius:5px;background:transparent;color:var(--text-color-secondary, rgba(235, 235, 245, .55));cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__tone-trigger:hover{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__tone-trigger:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-1px}.fly-emoji-picker__tone-glyph{line-height:1}.fly-emoji-picker__tone-caret{font-size:8px}.fly-emoji-picker__tone-menu{position:absolute;inset-block-start:calc(100% + 4px);inset-inline-end:0;z-index:21;display:grid;grid-template-columns:repeat(3,1fr);gap:2px;padding:4px;border-radius:8px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-emoji-picker__tone-menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-emoji-picker__tone-menu:before,.fly-emoji-picker__tone-menu:after{display:none}}@media(prefers-contrast:more){.fly-emoji-picker__tone-menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-emoji-picker__tone-menu:after{animation:none}}.fly-emoji-picker__tone-option{display:grid;place-items:center;inline-size:26px;block-size:26px;padding:0;font-size:15px;line-height:1;border:1px solid transparent;border-radius:5px;background:transparent;cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__tone-option:hover{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__tone-option:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-1px}.fly-emoji-picker__tone-option.is-active{border-color:var(--primary-color);background:var(--surface-hover, rgba(255, 255, 255, .1))}.fly-emoji-picker__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--fly-emoji-cell),1fr));gap:var(--fly-emoji-cell-gap)}.fly-emoji-picker__cell{display:flex;align-items:center;justify-content:center;aspect-ratio:1;min-block-size:var(--fly-emoji-cell);padding:4px;border:1px solid transparent;border-radius:6px;background:transparent;color:var(--text-color, inherit);cursor:pointer;transition:background .1s ease,border-color .1s ease}.fly-emoji-picker__cell:hover{background:var(--surface-hover, rgba(255, 255, 255, .08));border-color:var(--surface-border, rgba(255, 255, 255, .12))}.fly-emoji-picker__cell:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-1px}.fly-emoji-picker__cell.is-active{border-color:var(--primary-color);background:var(--selection-bg, rgba(0, 113, 227, .24))}.fly-emoji-picker__glyph{direction:ltr;font-size:var(--fly-emoji-glyph);line-height:1}.fly-emoji-picker__more{align-self:flex-start;padding:3px 8px;font:inherit;font-size:11px;border:none;border-radius:999px;background:transparent;color:var(--primary-color);cursor:pointer}.fly-emoji-picker__more:hover{background:var(--surface-hover, rgba(255, 255, 255, .06))}.fly-emoji-picker__more:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:1px}.fly-emoji-picker__empty{margin:0;padding:12px 4px;text-align:center;font-size:12px;color:var(--text-color-secondary, rgba(235, 235, 245, .5))}.fly-emoji-picker__tabs{display:flex;gap:4px;border-block-end:1px solid var(--surface-border, rgba(255, 255, 255, .12))}.fly-emoji-picker__tab{appearance:none;padding:6px 12px;font:inherit;font-size:12px;border:none;border-block-end:2px solid transparent;background:transparent;color:var(--text-color-secondary, rgba(235, 235, 245, .6));cursor:pointer}.fly-emoji-picker__tab.is-active{color:var(--text-color, inherit);border-block-end-color:var(--primary-color)}.fly-emoji-picker__tab:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-2px}.fly-emoji-picker__stickers{flex:1 1 auto;min-block-size:0;overflow-y:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(72px,1fr));gap:6px;padding:4px}.fly-emoji-picker__sticker{appearance:none;display:flex;align-items:center;justify-content:center;padding:4px;border:none;border-radius:10px;background:transparent;cursor:pointer}.fly-emoji-picker__sticker:hover,.fly-emoji-picker__sticker:focus-visible{background:var(--surface-hover, rgba(255, 255, 255, .08))}.fly-emoji-picker__sticker:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-2px}\n"] }]
7961
7961
  }], ctorParameters: () => [], propDecorators: { searchRef: [{ type: i0.ViewChild, args: ['searchRef', { isSignal: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], selectedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIds", required: false }] }], categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], defaultCategory: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultCategory", required: false }] }], skinTones: [{ type: i0.Input, args: [{ isSignal: true, alias: "skinTones", required: false }] }], skinTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "skinTone", required: false }] }], showMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "showMore", required: false }] }], previewCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewCount", required: false }] }], emojiAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "emojiAnimation", required: false }] }], stickerPicked: [{ type: i0.Output, args: ["stickerPicked"] }], toggled: [{ type: i0.Output, args: ["toggled"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], skinToneChange: [{ type: i0.Output, args: ["skinToneChange"] }], dismissOnOutsidePress: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissOnOutsidePress", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }] } });
7962
7962
  /** Direction is inherited, so ask the rendered element rather than guessing from a locale. */
7963
7963
  function isRtl(el) {
@@ -8420,11 +8420,11 @@ class ContextMenuComponent {
8420
8420
  this.previouslyFocused = null;
8421
8421
  }
8422
8422
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ContextMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8423
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: ContextMenuComponent, isStandalone: true, selector: "fly-context-menu", inputs: { x: { classPropertyName: "x", publicName: "x", isSignal: true, isRequired: false, transformFunction: null }, y: { classPropertyName: "y", publicName: "y", isSignal: true, isRequired: false, transformFunction: null }, anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: true, transformFunction: null }, boundary: { classPropertyName: "boundary", publicName: "boundary", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action", closed: "closed" }, host: { listeners: { "document:mousedown": "onClickOutside($event)", "document:keydown.escape": "onEscape()", "document:contextmenu": "onContextMenu($event)", "document:keydown": "onKeydown($event)" } }, viewQueries: [{ propertyName: "menuEl", first: true, predicate: ["contextMenu"], descendants: true }, { propertyName: "childMenuRef", first: true, predicate: ["childMenu"], descendants: true }], ngImport: i0, template: "<div\r\n #contextMenu\r\n class=\"context-menu\"\r\n [style.left.px]=\"clampedPos().left\"\r\n [style.top.px]=\"clampedPos().top\"\r\n role=\"menu\"\r\n [attr.aria-label]=\"'shell.context_menu' | translate\">\r\n\r\n @for (section of sections(); track $index) {\r\n @if ($index > 0) {\r\n <div class=\"menu-divider\"></div>\r\n }\r\n @if (section.label) {\r\n <div class=\"menu-section-label\">{{ section.label }}</div>\r\n }\r\n @for (item of section.items; track item.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fos-btn sm rect menu-item\"\r\n [class.menu-item--has-children]=\"!!item.children?.length\"\r\n [class.menu-item--selected]=\"item.selected === true\"\r\n [attr.role]=\"item.selected === undefined ? 'menuitem' : 'menuitemradio'\"\r\n [attr.aria-checked]=\"item.selected === undefined ? null : item.selected\"\r\n [attr.aria-haspopup]=\"item.children?.length ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item.children?.length ? (openSubmenuId() === item.id) : null\"\r\n (click)=\"onItemActivate(item, $event)\"\r\n (mouseenter)=\"onItemMouseEnter(item, $event)\"\r\n (mouseleave)=\"onItemMouseLeave()\">\r\n <i [class]=\"'pi ' + item.icon\" aria-hidden=\"true\"></i>\r\n <span>{{ item.label }}</span>\r\n @if (item.children?.length) {\r\n <i\r\n class=\"pi pi-angle-right menu-item__submenu-caret\"\r\n [class.is-rtl]=\"anchorRtl()\"\r\n aria-hidden=\"true\"></i>\r\n } @else if (item.selected !== undefined) {\r\n <i\r\n class=\"pi pi-check menu-item__check\"\r\n [class.menu-item__check--visible]=\"item.selected\"\r\n aria-hidden=\"true\"></i>\r\n }\r\n </button>\r\n }\r\n }\r\n\r\n @if (openSubmenuSections().length > 0) {\r\n <fly-context-menu\r\n #childMenu\r\n [anchor]=\"openSubmenuAnchorEl()\"\r\n placement=\"side\"\r\n [sections]=\"openSubmenuSections()\"\r\n (action)=\"onSubmenuAction($event)\"\r\n (closed)=\"onSubmenuClosed()\" />\r\n }\r\n</div>\r\n", styles: [":host{display:contents}.context-menu{position:fixed;z-index:1000;inline-size:max-content;min-inline-size:14ch;max-inline-size:min(38ch,100vw - 32px);padding:6px;border-radius:14px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.context-menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.context-menu:before,.context-menu:after{display:none}}@media(prefers-contrast:more){.context-menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.context-menu:after{animation:none}}.context-menu{animation:menuIn .24s var(--nova-ease-structural) both;transform-origin:top left}.menu-section-label{padding:6px 12px 4px;font:var(--nova-font-eyebrow);letter-spacing:var(--nova-tracking-eyebrow);text-transform:uppercase;color:var(--w5);pointer-events:none}.menu-item{display:flex;align-items:center;gap:10px;width:100%;min-height:32px;padding:7px 9px;border-radius:8px;color:var(--w95);font:var(--nova-font-menu-item);letter-spacing:var(--nova-tracking-menu-item);justify-content:flex-start;text-align:start}.menu-item span{min-inline-size:0;overflow-wrap:break-word}.menu-item i{flex:0 0 18px;font-size:14px;width:18px;text-align:center;opacity:.7}.menu-item__submenu-caret{flex:0 0 14px;width:14px;font-size:11px;margin-inline-start:auto;opacity:.55}.menu-item__submenu-caret.is-rtl{transform:scaleX(-1)}.menu-item__check{flex:0 0 14px;width:14px;font-size:13px;margin-inline-start:auto;color:var(--accent);opacity:0}.menu-item__check--visible{opacity:1}.menu-item--selected{background:var(--w08);font-weight:600}.menu-item:hover,.menu-item:focus-visible{background:var(--w1)}.menu-item:hover i,.menu-item:focus-visible i{opacity:1}.menu-item:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}.menu-divider{height:1px;margin:4px 8px;background:var(--glass2-border)}@media(pointer:coarse){.menu-item{min-block-size:44px}}\n"], dependencies: [{ kind: "component", type: ContextMenuComponent, selector: "fly-context-menu", inputs: ["x", "y", "anchor", "align", "placement", "sections", "boundary"], outputs: ["action", "closed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8423
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: ContextMenuComponent, isStandalone: true, selector: "fly-context-menu", inputs: { x: { classPropertyName: "x", publicName: "x", isSignal: true, isRequired: false, transformFunction: null }, y: { classPropertyName: "y", publicName: "y", isSignal: true, isRequired: false, transformFunction: null }, anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: true, transformFunction: null }, boundary: { classPropertyName: "boundary", publicName: "boundary", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action", closed: "closed" }, host: { listeners: { "document:mousedown": "onClickOutside($event)", "document:keydown.escape": "onEscape()", "document:contextmenu": "onContextMenu($event)", "document:keydown": "onKeydown($event)" } }, viewQueries: [{ propertyName: "menuEl", first: true, predicate: ["contextMenu"], descendants: true }, { propertyName: "childMenuRef", first: true, predicate: ["childMenu"], descendants: true }], ngImport: i0, template: "<div\r\n #contextMenu\r\n class=\"context-menu\"\r\n [style.left.px]=\"clampedPos().left\"\r\n [style.top.px]=\"clampedPos().top\"\r\n role=\"menu\"\r\n [attr.aria-label]=\"'shell.context_menu' | translate\">\r\n\r\n @for (section of sections(); track $index) {\r\n @if ($index > 0) {\r\n <div class=\"menu-divider\"></div>\r\n }\r\n @if (section.label) {\r\n <div class=\"menu-section-label\">{{ section.label }}</div>\r\n }\r\n @for (item of section.items; track item.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fos-btn sm rect menu-item\"\r\n [class.menu-item--has-children]=\"!!item.children?.length\"\r\n [class.menu-item--selected]=\"item.selected === true\"\r\n [attr.role]=\"item.selected === undefined ? 'menuitem' : 'menuitemradio'\"\r\n [attr.aria-checked]=\"item.selected === undefined ? null : item.selected\"\r\n [attr.aria-haspopup]=\"item.children?.length ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item.children?.length ? (openSubmenuId() === item.id) : null\"\r\n (click)=\"onItemActivate(item, $event)\"\r\n (mouseenter)=\"onItemMouseEnter(item, $event)\"\r\n (mouseleave)=\"onItemMouseLeave()\">\r\n <i [class]=\"'pi menu-item__icon ' + item.icon\" aria-hidden=\"true\"></i>\r\n <span>{{ item.label }}</span>\r\n @if (item.children?.length) {\r\n <i\r\n class=\"pi pi-angle-right menu-item__submenu-caret\"\r\n [class.is-rtl]=\"anchorRtl()\"\r\n aria-hidden=\"true\"></i>\r\n } @else if (item.selected !== undefined) {\r\n <i\r\n class=\"pi pi-check menu-item__check\"\r\n [class.menu-item__check--visible]=\"item.selected\"\r\n aria-hidden=\"true\"></i>\r\n }\r\n </button>\r\n }\r\n }\r\n\r\n @if (openSubmenuSections().length > 0) {\r\n <fly-context-menu\r\n #childMenu\r\n [anchor]=\"openSubmenuAnchorEl()\"\r\n placement=\"side\"\r\n [sections]=\"openSubmenuSections()\"\r\n (action)=\"onSubmenuAction($event)\"\r\n (closed)=\"onSubmenuClosed()\" />\r\n }\r\n</div>\r\n", styles: [":host{display:contents}.context-menu{position:fixed;z-index:1000;inline-size:max-content;min-inline-size:14ch;max-inline-size:min(38ch,100vw - 32px);padding:6px;border-radius:14px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.context-menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.context-menu:before,.context-menu:after{display:none}}@media(prefers-contrast:more){.context-menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.context-menu:after{animation:none}}.context-menu{animation:menuIn .24s var(--nova-ease-structural) both;transform-origin:top left}.menu-section-label{padding:6px 12px 4px;font:var(--nova-font-eyebrow);letter-spacing:var(--nova-tracking-eyebrow);text-transform:uppercase;color:var(--w5);pointer-events:none}.menu-item{display:flex;align-items:center;gap:10px;width:100%;min-height:32px;padding:7px 9px;border-radius:8px;color:var(--w95);font:var(--nova-font-menu-item);letter-spacing:var(--nova-tracking-menu-item);justify-content:flex-start;text-align:start}.menu-item span{min-inline-size:0;overflow-wrap:break-word}.menu-item__icon{flex:0 0 18px;font-size:14px;width:18px;text-align:center;opacity:.7}.menu-item__submenu-caret{flex:0 0 14px;width:14px;font-size:11px;margin-inline-start:auto;opacity:.55}.menu-item__submenu-caret.is-rtl{transform:scaleX(-1)}.menu-item__check{flex:0 0 14px;width:14px;font-size:13px;margin-inline-start:auto;color:var(--accent);opacity:0}.menu-item__check--visible{opacity:1}.menu-item--selected{background:var(--w08);font-weight:600}.menu-item:hover,.menu-item:focus-visible{background:var(--w1)}.menu-item:hover .menu-item__icon,.menu-item:focus-visible .menu-item__icon{opacity:1}.menu-item:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:-2px}.menu-divider{height:1px;margin:4px 8px;background:var(--glass2-border)}@media(pointer:coarse){.menu-item{min-block-size:44px}}\n"], dependencies: [{ kind: "component", type: ContextMenuComponent, selector: "fly-context-menu", inputs: ["x", "y", "anchor", "align", "placement", "sections", "boundary"], outputs: ["action", "closed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8424
8424
  }
8425
8425
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ContextMenuComponent, decorators: [{
8426
8426
  type: Component,
8427
- args: [{ selector: 'fly-context-menu', standalone: true, imports: [TranslatePipe, ContextMenuComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n #contextMenu\r\n class=\"context-menu\"\r\n [style.left.px]=\"clampedPos().left\"\r\n [style.top.px]=\"clampedPos().top\"\r\n role=\"menu\"\r\n [attr.aria-label]=\"'shell.context_menu' | translate\">\r\n\r\n @for (section of sections(); track $index) {\r\n @if ($index > 0) {\r\n <div class=\"menu-divider\"></div>\r\n }\r\n @if (section.label) {\r\n <div class=\"menu-section-label\">{{ section.label }}</div>\r\n }\r\n @for (item of section.items; track item.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fos-btn sm rect menu-item\"\r\n [class.menu-item--has-children]=\"!!item.children?.length\"\r\n [class.menu-item--selected]=\"item.selected === true\"\r\n [attr.role]=\"item.selected === undefined ? 'menuitem' : 'menuitemradio'\"\r\n [attr.aria-checked]=\"item.selected === undefined ? null : item.selected\"\r\n [attr.aria-haspopup]=\"item.children?.length ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item.children?.length ? (openSubmenuId() === item.id) : null\"\r\n (click)=\"onItemActivate(item, $event)\"\r\n (mouseenter)=\"onItemMouseEnter(item, $event)\"\r\n (mouseleave)=\"onItemMouseLeave()\">\r\n <i [class]=\"'pi ' + item.icon\" aria-hidden=\"true\"></i>\r\n <span>{{ item.label }}</span>\r\n @if (item.children?.length) {\r\n <i\r\n class=\"pi pi-angle-right menu-item__submenu-caret\"\r\n [class.is-rtl]=\"anchorRtl()\"\r\n aria-hidden=\"true\"></i>\r\n } @else if (item.selected !== undefined) {\r\n <i\r\n class=\"pi pi-check menu-item__check\"\r\n [class.menu-item__check--visible]=\"item.selected\"\r\n aria-hidden=\"true\"></i>\r\n }\r\n </button>\r\n }\r\n }\r\n\r\n @if (openSubmenuSections().length > 0) {\r\n <fly-context-menu\r\n #childMenu\r\n [anchor]=\"openSubmenuAnchorEl()\"\r\n placement=\"side\"\r\n [sections]=\"openSubmenuSections()\"\r\n (action)=\"onSubmenuAction($event)\"\r\n (closed)=\"onSubmenuClosed()\" />\r\n }\r\n</div>\r\n", styles: [":host{display:contents}.context-menu{position:fixed;z-index:1000;inline-size:max-content;min-inline-size:14ch;max-inline-size:min(38ch,100vw - 32px);padding:6px;border-radius:14px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.context-menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.context-menu:before,.context-menu:after{display:none}}@media(prefers-contrast:more){.context-menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.context-menu:after{animation:none}}.context-menu{animation:menuIn .24s var(--nova-ease-structural) both;transform-origin:top left}.menu-section-label{padding:6px 12px 4px;font:var(--nova-font-eyebrow);letter-spacing:var(--nova-tracking-eyebrow);text-transform:uppercase;color:var(--w5);pointer-events:none}.menu-item{display:flex;align-items:center;gap:10px;width:100%;min-height:32px;padding:7px 9px;border-radius:8px;color:var(--w95);font:var(--nova-font-menu-item);letter-spacing:var(--nova-tracking-menu-item);justify-content:flex-start;text-align:start}.menu-item span{min-inline-size:0;overflow-wrap:break-word}.menu-item i{flex:0 0 18px;font-size:14px;width:18px;text-align:center;opacity:.7}.menu-item__submenu-caret{flex:0 0 14px;width:14px;font-size:11px;margin-inline-start:auto;opacity:.55}.menu-item__submenu-caret.is-rtl{transform:scaleX(-1)}.menu-item__check{flex:0 0 14px;width:14px;font-size:13px;margin-inline-start:auto;color:var(--accent);opacity:0}.menu-item__check--visible{opacity:1}.menu-item--selected{background:var(--w08);font-weight:600}.menu-item:hover,.menu-item:focus-visible{background:var(--w1)}.menu-item:hover i,.menu-item:focus-visible i{opacity:1}.menu-item:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}.menu-divider{height:1px;margin:4px 8px;background:var(--glass2-border)}@media(pointer:coarse){.menu-item{min-block-size:44px}}\n"] }]
8427
+ args: [{ selector: 'fly-context-menu', standalone: true, imports: [TranslatePipe, ContextMenuComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n #contextMenu\r\n class=\"context-menu\"\r\n [style.left.px]=\"clampedPos().left\"\r\n [style.top.px]=\"clampedPos().top\"\r\n role=\"menu\"\r\n [attr.aria-label]=\"'shell.context_menu' | translate\">\r\n\r\n @for (section of sections(); track $index) {\r\n @if ($index > 0) {\r\n <div class=\"menu-divider\"></div>\r\n }\r\n @if (section.label) {\r\n <div class=\"menu-section-label\">{{ section.label }}</div>\r\n }\r\n @for (item of section.items; track item.id) {\r\n <button\r\n type=\"button\"\r\n class=\"fos-btn sm rect menu-item\"\r\n [class.menu-item--has-children]=\"!!item.children?.length\"\r\n [class.menu-item--selected]=\"item.selected === true\"\r\n [attr.role]=\"item.selected === undefined ? 'menuitem' : 'menuitemradio'\"\r\n [attr.aria-checked]=\"item.selected === undefined ? null : item.selected\"\r\n [attr.aria-haspopup]=\"item.children?.length ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item.children?.length ? (openSubmenuId() === item.id) : null\"\r\n (click)=\"onItemActivate(item, $event)\"\r\n (mouseenter)=\"onItemMouseEnter(item, $event)\"\r\n (mouseleave)=\"onItemMouseLeave()\">\r\n <i [class]=\"'pi menu-item__icon ' + item.icon\" aria-hidden=\"true\"></i>\r\n <span>{{ item.label }}</span>\r\n @if (item.children?.length) {\r\n <i\r\n class=\"pi pi-angle-right menu-item__submenu-caret\"\r\n [class.is-rtl]=\"anchorRtl()\"\r\n aria-hidden=\"true\"></i>\r\n } @else if (item.selected !== undefined) {\r\n <i\r\n class=\"pi pi-check menu-item__check\"\r\n [class.menu-item__check--visible]=\"item.selected\"\r\n aria-hidden=\"true\"></i>\r\n }\r\n </button>\r\n }\r\n }\r\n\r\n @if (openSubmenuSections().length > 0) {\r\n <fly-context-menu\r\n #childMenu\r\n [anchor]=\"openSubmenuAnchorEl()\"\r\n placement=\"side\"\r\n [sections]=\"openSubmenuSections()\"\r\n (action)=\"onSubmenuAction($event)\"\r\n (closed)=\"onSubmenuClosed()\" />\r\n }\r\n</div>\r\n", styles: [":host{display:contents}.context-menu{position:fixed;z-index:1000;inline-size:max-content;min-inline-size:14ch;max-inline-size:min(38ch,100vw - 32px);padding:6px;border-radius:14px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.context-menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.context-menu:before,.context-menu:after{display:none}}@media(prefers-contrast:more){.context-menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.context-menu:after{animation:none}}.context-menu{animation:menuIn .24s var(--nova-ease-structural) both;transform-origin:top left}.menu-section-label{padding:6px 12px 4px;font:var(--nova-font-eyebrow);letter-spacing:var(--nova-tracking-eyebrow);text-transform:uppercase;color:var(--w5);pointer-events:none}.menu-item{display:flex;align-items:center;gap:10px;width:100%;min-height:32px;padding:7px 9px;border-radius:8px;color:var(--w95);font:var(--nova-font-menu-item);letter-spacing:var(--nova-tracking-menu-item);justify-content:flex-start;text-align:start}.menu-item span{min-inline-size:0;overflow-wrap:break-word}.menu-item__icon{flex:0 0 18px;font-size:14px;width:18px;text-align:center;opacity:.7}.menu-item__submenu-caret{flex:0 0 14px;width:14px;font-size:11px;margin-inline-start:auto;opacity:.55}.menu-item__submenu-caret.is-rtl{transform:scaleX(-1)}.menu-item__check{flex:0 0 14px;width:14px;font-size:13px;margin-inline-start:auto;color:var(--accent);opacity:0}.menu-item__check--visible{opacity:1}.menu-item--selected{background:var(--w08);font-weight:600}.menu-item:hover,.menu-item:focus-visible{background:var(--w1)}.menu-item:hover .menu-item__icon,.menu-item:focus-visible .menu-item__icon{opacity:1}.menu-item:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:-2px}.menu-divider{height:1px;margin:4px 8px;background:var(--glass2-border)}@media(pointer:coarse){.menu-item{min-block-size:44px}}\n"] }]
8428
8428
  }], propDecorators: { menuEl: [{
8429
8429
  type: ViewChild,
8430
8430
  args: ['contextMenu']
@@ -9771,7 +9771,7 @@ class AudienceBuilderComponent {
9771
9771
  useExisting: forwardRef(() => AudienceBuilderComponent),
9772
9772
  multi: true,
9773
9773
  },
9774
- ], 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);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:color-mix(in srgb,var(--accent) 12%,transparent);border-color:var(--primary-color);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)}.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);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)}.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 });
9774
+ ], 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);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:color-mix(in srgb,var(--accent) 12%,transparent);border-color:var(--primary-color);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)}.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;outline-color:var(--primary-color);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)}.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 });
9775
9775
  }
9776
9776
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: AudienceBuilderComponent, decorators: [{
9777
9777
  type: Component,
@@ -9786,7 +9786,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
9786
9786
  useExisting: forwardRef(() => AudienceBuilderComponent),
9787
9787
  multi: true,
9788
9788
  },
9789
- ], 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);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:color-mix(in srgb,var(--accent) 12%,transparent);border-color:var(--primary-color);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)}.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);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)}.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"] }]
9789
+ ], 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);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:color-mix(in srgb,var(--accent) 12%,transparent);border-color:var(--primary-color);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)}.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;outline-color:var(--primary-color);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)}.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"] }]
9790
9790
  }], propDecorators: { value: [{
9791
9791
  type: Input
9792
9792
  }], showExcludes: [{
@@ -10038,13 +10038,13 @@ class FlyBreadcrumbComponent {
10038
10038
  this.navigate.emit(item);
10039
10039
  }
10040
10040
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyBreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10041
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyBreadcrumbComponent, isStandalone: true, selector: "fly-breadcrumb", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, maxVisible: { classPropertyName: "maxVisible", publicName: "maxVisible", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hasCurrentPage: { classPropertyName: "hasCurrentPage", publicName: "hasCurrentPage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { navigate: "navigate" }, host: { properties: { "attr.dir": "i18n.direction()" } }, ngImport: i0, template: "<!--\r\n The CURRENT-PAGE crumb is ALWAYS plain text with aria-current=\"page\" \u2014 never an <a>\r\n or <button>, even when it carries an href. With [hasCurrentPage]=\"false\" the trail\r\n lists ancestors only, so no crumb is the current page and every one stays a link.\r\n The separator is decorative (aria-hidden) and drawn as a CSS mask so it mirrors\r\n under RTL with no directional glyph baked in.\r\n-->\r\n<nav class=\"fly-breadcrumb\" [attr.aria-label]=\"resolvedAriaLabel()\">\r\n @for (entry of renderItems(); track entry.kind === 'item' ? entry.item.id : 'overflow'; let i = $index) {\r\n @if (i > 0) {\r\n <svg class=\"fly-breadcrumb__separator\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\">\r\n <path d=\"M9 5l7 7-7 7\" />\r\n </svg>\r\n }\r\n @if (entry.kind === 'overflow') {\r\n <span class=\"fly-breadcrumb__crumb fly-breadcrumb__crumb--overflow\">\u2026</span>\r\n } @else if (entry.isCurrent) {\r\n <span class=\"fly-breadcrumb__crumb fly-breadcrumb__crumb--current\" aria-current=\"page\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </span>\r\n } @else {\r\n <span class=\"fly-breadcrumb__crumb\">\r\n @if (entry.item.href) {\r\n <a class=\"fly-breadcrumb__link\" [attr.href]=\"entry.item.href\"\r\n (click)=\"onActivate(entry.item)\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </a>\r\n } @else {\r\n <button type=\"button\" class=\"fly-breadcrumb__link fly-breadcrumb__link--button\"\r\n (click)=\"onActivate(entry.item)\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </button>\r\n }\r\n </span>\r\n }\r\n }\r\n</nav>\r\n", styles: [":host{display:block;min-inline-size:0}.fly-breadcrumb{display:flex;align-items:center;gap:2px;min-inline-size:0}.fly-breadcrumb__crumb{display:flex;align-items:center;flex:none;min-inline-size:0;font-size:12.5px;line-height:1.4}.fly-breadcrumb__crumb--current{flex:1 1 auto;min-inline-size:0;gap:6px;block-size:26px;padding-inline:4px;font-weight:600;letter-spacing:-.006em;color:var(--text-color);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host([dir=rtl]) .fly-breadcrumb__crumb--current{letter-spacing:normal}.fly-breadcrumb__crumb--overflow{color:var(--text-color-secondary);-webkit-user-select:none;user-select:none}.fly-breadcrumb__link{display:inline-flex;align-items:center;gap:6px;block-size:26px;padding-inline:8px;margin:0;border:0;border-radius:8px;background:transparent;color:var(--text-color-secondary);font-family:inherit;font-size:12.5px;font-weight:500;line-height:1;text-decoration:none;cursor:pointer;max-inline-size:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-breadcrumb__link:hover{background:var(--w08);color:var(--text-color)}.fly-breadcrumb__link:focus-visible{outline:2px solid var(--primary-color);outline-offset:1px}.fly-breadcrumb__link--button{display:inline-flex}.fly-breadcrumb__icon{flex:none}.fly-breadcrumb__separator{flex:none;color:var(--w28)}:host([dir=rtl]) .fly-breadcrumb__separator{transform:scaleX(-1)}@media(forced-colors:active){.fly-breadcrumb__separator{color:CanvasText}.fly-breadcrumb__link:focus-visible{outline-color:Highlight}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10041
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyBreadcrumbComponent, isStandalone: true, selector: "fly-breadcrumb", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, maxVisible: { classPropertyName: "maxVisible", publicName: "maxVisible", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hasCurrentPage: { classPropertyName: "hasCurrentPage", publicName: "hasCurrentPage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { navigate: "navigate" }, host: { properties: { "attr.dir": "i18n.direction()" } }, ngImport: i0, template: "<!--\r\n The CURRENT-PAGE crumb is ALWAYS plain text with aria-current=\"page\" \u2014 never an <a>\r\n or <button>, even when it carries an href. With [hasCurrentPage]=\"false\" the trail\r\n lists ancestors only, so no crumb is the current page and every one stays a link.\r\n The separator is decorative (aria-hidden) and drawn as a CSS mask so it mirrors\r\n under RTL with no directional glyph baked in.\r\n-->\r\n<nav class=\"fly-breadcrumb\" [attr.aria-label]=\"resolvedAriaLabel()\">\r\n @for (entry of renderItems(); track entry.kind === 'item' ? entry.item.id : 'overflow'; let i = $index) {\r\n @if (i > 0) {\r\n <svg class=\"fly-breadcrumb__separator\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\">\r\n <path d=\"M9 5l7 7-7 7\" />\r\n </svg>\r\n }\r\n @if (entry.kind === 'overflow') {\r\n <span class=\"fly-breadcrumb__crumb fly-breadcrumb__crumb--overflow\">\u2026</span>\r\n } @else if (entry.isCurrent) {\r\n <span class=\"fly-breadcrumb__crumb fly-breadcrumb__crumb--current\" aria-current=\"page\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </span>\r\n } @else {\r\n <span class=\"fly-breadcrumb__crumb\">\r\n @if (entry.item.href) {\r\n <a class=\"fly-breadcrumb__link\" [attr.href]=\"entry.item.href\"\r\n (click)=\"onActivate(entry.item)\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </a>\r\n } @else {\r\n <button type=\"button\" class=\"fly-breadcrumb__link fly-breadcrumb__link--button\"\r\n (click)=\"onActivate(entry.item)\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </button>\r\n }\r\n </span>\r\n }\r\n }\r\n</nav>\r\n", styles: [":host{display:block;min-inline-size:0}.fly-breadcrumb{display:flex;align-items:center;gap:2px;min-inline-size:0}.fly-breadcrumb__crumb{display:flex;align-items:center;flex:none;min-inline-size:0;font-size:12.5px;line-height:1.4}.fly-breadcrumb__crumb--current{flex:1 1 auto;min-inline-size:0;gap:6px;block-size:26px;padding-inline:4px;font-weight:600;letter-spacing:-.006em;color:var(--text-color);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host([dir=rtl]) .fly-breadcrumb__crumb--current{letter-spacing:normal}.fly-breadcrumb__crumb--overflow{color:var(--text-color-secondary);-webkit-user-select:none;user-select:none}.fly-breadcrumb__link{display:inline-flex;align-items:center;gap:6px;block-size:26px;padding-inline:8px;margin:0;border:0;border-radius:8px;background:transparent;color:var(--text-color-secondary);font-family:inherit;font-size:12.5px;font-weight:500;line-height:1;text-decoration:none;cursor:pointer;max-inline-size:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-breadcrumb__link:hover{background:var(--w08);color:var(--text-color)}.fly-breadcrumb__link:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:1px}.fly-breadcrumb__link--button{display:inline-flex}.fly-breadcrumb__icon{flex:none}.fly-breadcrumb__separator{flex:none;color:var(--w28)}:host([dir=rtl]) .fly-breadcrumb__separator{transform:scaleX(-1)}@media(forced-colors:active){.fly-breadcrumb__separator{color:CanvasText}.fly-breadcrumb__link:focus-visible{outline-color:Highlight}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10042
10042
  }
10043
10043
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyBreadcrumbComponent, decorators: [{
10044
10044
  type: Component,
10045
10045
  args: [{ selector: 'fly-breadcrumb', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
10046
10046
  '[attr.dir]': 'i18n.direction()',
10047
- }, template: "<!--\r\n The CURRENT-PAGE crumb is ALWAYS plain text with aria-current=\"page\" \u2014 never an <a>\r\n or <button>, even when it carries an href. With [hasCurrentPage]=\"false\" the trail\r\n lists ancestors only, so no crumb is the current page and every one stays a link.\r\n The separator is decorative (aria-hidden) and drawn as a CSS mask so it mirrors\r\n under RTL with no directional glyph baked in.\r\n-->\r\n<nav class=\"fly-breadcrumb\" [attr.aria-label]=\"resolvedAriaLabel()\">\r\n @for (entry of renderItems(); track entry.kind === 'item' ? entry.item.id : 'overflow'; let i = $index) {\r\n @if (i > 0) {\r\n <svg class=\"fly-breadcrumb__separator\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\">\r\n <path d=\"M9 5l7 7-7 7\" />\r\n </svg>\r\n }\r\n @if (entry.kind === 'overflow') {\r\n <span class=\"fly-breadcrumb__crumb fly-breadcrumb__crumb--overflow\">\u2026</span>\r\n } @else if (entry.isCurrent) {\r\n <span class=\"fly-breadcrumb__crumb fly-breadcrumb__crumb--current\" aria-current=\"page\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </span>\r\n } @else {\r\n <span class=\"fly-breadcrumb__crumb\">\r\n @if (entry.item.href) {\r\n <a class=\"fly-breadcrumb__link\" [attr.href]=\"entry.item.href\"\r\n (click)=\"onActivate(entry.item)\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </a>\r\n } @else {\r\n <button type=\"button\" class=\"fly-breadcrumb__link fly-breadcrumb__link--button\"\r\n (click)=\"onActivate(entry.item)\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </button>\r\n }\r\n </span>\r\n }\r\n }\r\n</nav>\r\n", styles: [":host{display:block;min-inline-size:0}.fly-breadcrumb{display:flex;align-items:center;gap:2px;min-inline-size:0}.fly-breadcrumb__crumb{display:flex;align-items:center;flex:none;min-inline-size:0;font-size:12.5px;line-height:1.4}.fly-breadcrumb__crumb--current{flex:1 1 auto;min-inline-size:0;gap:6px;block-size:26px;padding-inline:4px;font-weight:600;letter-spacing:-.006em;color:var(--text-color);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host([dir=rtl]) .fly-breadcrumb__crumb--current{letter-spacing:normal}.fly-breadcrumb__crumb--overflow{color:var(--text-color-secondary);-webkit-user-select:none;user-select:none}.fly-breadcrumb__link{display:inline-flex;align-items:center;gap:6px;block-size:26px;padding-inline:8px;margin:0;border:0;border-radius:8px;background:transparent;color:var(--text-color-secondary);font-family:inherit;font-size:12.5px;font-weight:500;line-height:1;text-decoration:none;cursor:pointer;max-inline-size:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-breadcrumb__link:hover{background:var(--w08);color:var(--text-color)}.fly-breadcrumb__link:focus-visible{outline:2px solid var(--primary-color);outline-offset:1px}.fly-breadcrumb__link--button{display:inline-flex}.fly-breadcrumb__icon{flex:none}.fly-breadcrumb__separator{flex:none;color:var(--w28)}:host([dir=rtl]) .fly-breadcrumb__separator{transform:scaleX(-1)}@media(forced-colors:active){.fly-breadcrumb__separator{color:CanvasText}.fly-breadcrumb__link:focus-visible{outline-color:Highlight}}\n"] }]
10047
+ }, template: "<!--\r\n The CURRENT-PAGE crumb is ALWAYS plain text with aria-current=\"page\" \u2014 never an <a>\r\n or <button>, even when it carries an href. With [hasCurrentPage]=\"false\" the trail\r\n lists ancestors only, so no crumb is the current page and every one stays a link.\r\n The separator is decorative (aria-hidden) and drawn as a CSS mask so it mirrors\r\n under RTL with no directional glyph baked in.\r\n-->\r\n<nav class=\"fly-breadcrumb\" [attr.aria-label]=\"resolvedAriaLabel()\">\r\n @for (entry of renderItems(); track entry.kind === 'item' ? entry.item.id : 'overflow'; let i = $index) {\r\n @if (i > 0) {\r\n <svg class=\"fly-breadcrumb__separator\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\">\r\n <path d=\"M9 5l7 7-7 7\" />\r\n </svg>\r\n }\r\n @if (entry.kind === 'overflow') {\r\n <span class=\"fly-breadcrumb__crumb fly-breadcrumb__crumb--overflow\">\u2026</span>\r\n } @else if (entry.isCurrent) {\r\n <span class=\"fly-breadcrumb__crumb fly-breadcrumb__crumb--current\" aria-current=\"page\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </span>\r\n } @else {\r\n <span class=\"fly-breadcrumb__crumb\">\r\n @if (entry.item.href) {\r\n <a class=\"fly-breadcrumb__link\" [attr.href]=\"entry.item.href\"\r\n (click)=\"onActivate(entry.item)\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </a>\r\n } @else {\r\n <button type=\"button\" class=\"fly-breadcrumb__link fly-breadcrumb__link--button\"\r\n (click)=\"onActivate(entry.item)\">\r\n @if (entry.item.iconPath; as d) {\r\n <svg class=\"fly-breadcrumb__icon\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"><path [attr.d]=\"d\" /></svg>\r\n }\r\n {{ entry.item.label }}\r\n </button>\r\n }\r\n </span>\r\n }\r\n }\r\n</nav>\r\n", styles: [":host{display:block;min-inline-size:0}.fly-breadcrumb{display:flex;align-items:center;gap:2px;min-inline-size:0}.fly-breadcrumb__crumb{display:flex;align-items:center;flex:none;min-inline-size:0;font-size:12.5px;line-height:1.4}.fly-breadcrumb__crumb--current{flex:1 1 auto;min-inline-size:0;gap:6px;block-size:26px;padding-inline:4px;font-weight:600;letter-spacing:-.006em;color:var(--text-color);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host([dir=rtl]) .fly-breadcrumb__crumb--current{letter-spacing:normal}.fly-breadcrumb__crumb--overflow{color:var(--text-color-secondary);-webkit-user-select:none;user-select:none}.fly-breadcrumb__link{display:inline-flex;align-items:center;gap:6px;block-size:26px;padding-inline:8px;margin:0;border:0;border-radius:8px;background:transparent;color:var(--text-color-secondary);font-family:inherit;font-size:12.5px;font-weight:500;line-height:1;text-decoration:none;cursor:pointer;max-inline-size:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-breadcrumb__link:hover{background:var(--w08);color:var(--text-color)}.fly-breadcrumb__link:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:1px}.fly-breadcrumb__link--button{display:inline-flex}.fly-breadcrumb__icon{flex:none}.fly-breadcrumb__separator{flex:none;color:var(--w28)}:host([dir=rtl]) .fly-breadcrumb__separator{transform:scaleX(-1)}@media(forced-colors:active){.fly-breadcrumb__separator{color:CanvasText}.fly-breadcrumb__link:focus-visible{outline-color:Highlight}}\n"] }]
10048
10048
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], maxVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxVisible", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hasCurrentPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasCurrentPage", required: false }] }], navigate: [{ type: i0.Output, args: ["navigate"] }] } });
10049
10049
 
10050
10050
  /** Cross-bundle store key + sync event — same shape as `FLY_MAGIC_BAR_STORE_KEY`. */
@@ -10454,13 +10454,13 @@ class FlyTreeNavComponent {
10454
10454
  this.rowEls()[idx]?.nativeElement.focus();
10455
10455
  }
10456
10456
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyTreeNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10457
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyTreeNavComponent, isStandalone: true, selector: "fly-tree-nav", inputs: { nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: true, isRequired: false, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedId: "selectedIdChange" }, host: { properties: { "class.fly-tree-nav--rtl": "rtl()" } }, viewQueries: [{ propertyName: "rowEls", predicate: ["navRow"], descendants: true, isSignal: true }], ngImport: i0, template: "<nav class=\"fly-tree-nav\" [attr.aria-label]=\"resolvedAriaLabel()\">\r\n <ul class=\"fly-tree-nav__list\">\r\n @for (node of nodes(); track node.id) {\r\n <li class=\"fly-tree-nav__section\">\r\n @if (node.children && node.children.length > 0) {\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--section\"\r\n [attr.aria-expanded]=\"isExpanded(node.id)\"\r\n [attr.aria-controls]=\"'fly-tree-nav-group-' + node.id\"\r\n [attr.tabindex]=\"tabIndexFor(node.id)\"\r\n (click)=\"toggle(node.id)\"\r\n (keydown)=\"onKeydown($event, node.id)\"\r\n >\r\n <i class=\"pi pi-chevron-right fly-tree-nav__chevron\" aria-hidden=\"true\"></i>\r\n <span class=\"fly-tree-nav__label\">{{ node.label }}</span>\r\n @if (node.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ node.badge }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--item\"\r\n [class.fly-tree-nav__row--selected]=\"selectedId() === node.id\"\r\n [attr.aria-current]=\"selectedId() === node.id ? 'page' : null\"\r\n [attr.tabindex]=\"tabIndexFor(node.id)\"\r\n (click)=\"select(node.id)\"\r\n (keydown)=\"onKeydown($event, node.id)\"\r\n >\r\n <span class=\"fly-tree-nav__label\">{{ node.label }}</span>\r\n @if (node.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ node.badge }}</span>\r\n }\r\n </button>\r\n }\r\n\r\n @if (node.children && node.children.length > 0 && isExpanded(node.id)) {\r\n <ul class=\"fly-tree-nav__group\" [id]=\"'fly-tree-nav-group-' + node.id\">\r\n @for (child of node.children; track child.id) {\r\n <li>\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--item fly-tree-nav__row--child\"\r\n [class.fly-tree-nav__row--selected]=\"selectedId() === child.id\"\r\n [attr.aria-current]=\"selectedId() === child.id ? 'page' : null\"\r\n [attr.tabindex]=\"tabIndexFor(child.id)\"\r\n (click)=\"select(child.id)\"\r\n (keydown)=\"onKeydown($event, child.id)\"\r\n >\r\n <span class=\"fly-tree-nav__label\">{{ child.label }}</span>\r\n @if (child.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ child.badge }}</span>\r\n }\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n</nav>\r\n", styles: [":host{--fly-tree-nav-row-size: 32px;--fly-tree-nav-radius: 7px;--fly-tree-nav-indent: 22px;--fly-tree-nav-font: 13px;display:block}.fly-tree-nav__list,.fly-tree-nav__group{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1px}.fly-tree-nav__group{padding-inline-start:var(--fly-tree-nav-indent)}.fly-tree-nav__row{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:var(--fly-tree-nav-row-size);padding-inline:8px;border:0;border-inline-start:2px solid transparent;border-radius:var(--fly-tree-nav-radius);background:transparent;color:inherit;font-size:var(--fly-tree-nav-font);text-align:start;cursor:pointer;transition:background-color .15s ease}.fly-tree-nav__row:hover{background:var(--surface-hover)}.fly-tree-nav__row:focus-visible{outline:2px solid var(--primary-color);outline-offset:-2px}.fly-tree-nav__row--section{font-weight:600}.fly-tree-nav__row--child{font-weight:400}.fly-tree-nav__row--selected{background:var(--surface-hover);border-inline-start-color:var(--primary-color);color:var(--primary-color);font-weight:600}.fly-tree-nav__label{flex:1 1 auto;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-tree-nav__badge{flex-shrink:0;padding:1px 7px;border-radius:999px;background:var(--surface-hover);color:var(--text-color-secondary);font-size:10.5px;font-weight:600;line-height:1.6}.fly-tree-nav__chevron{flex-shrink:0;font-size:10px;color:var(--text-color-secondary);--fly-tn-flip: 1;--fly-tn-rotate: 0deg;transform:scaleX(var(--fly-tn-flip)) rotate(var(--fly-tn-rotate));transition:transform .15s ease}:host(.fly-tree-nav--rtl) .fly-tree-nav__chevron{--fly-tn-flip: -1}.fly-tree-nav__row--section[aria-expanded=true] .fly-tree-nav__chevron{--fly-tn-rotate: 90deg}@media(prefers-reduced-motion:reduce){.fly-tree-nav__row,.fly-tree-nav__chevron{transition:none}}@media(forced-colors:active){.fly-tree-nav__row--selected{border-inline-start-color:Highlight;color:LinkText}.fly-tree-nav__row:focus-visible{outline-color:Highlight}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10457
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyTreeNavComponent, isStandalone: true, selector: "fly-tree-nav", inputs: { nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: true, isRequired: false, transformFunction: null }, selectedId: { classPropertyName: "selectedId", publicName: "selectedId", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedId: "selectedIdChange" }, host: { properties: { "class.fly-tree-nav--rtl": "rtl()" } }, viewQueries: [{ propertyName: "rowEls", predicate: ["navRow"], descendants: true, isSignal: true }], ngImport: i0, template: "<nav class=\"fly-tree-nav\" [attr.aria-label]=\"resolvedAriaLabel()\">\r\n <ul class=\"fly-tree-nav__list\">\r\n @for (node of nodes(); track node.id) {\r\n <li class=\"fly-tree-nav__section\">\r\n @if (node.children && node.children.length > 0) {\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--section\"\r\n [attr.aria-expanded]=\"isExpanded(node.id)\"\r\n [attr.aria-controls]=\"'fly-tree-nav-group-' + node.id\"\r\n [attr.tabindex]=\"tabIndexFor(node.id)\"\r\n (click)=\"toggle(node.id)\"\r\n (keydown)=\"onKeydown($event, node.id)\"\r\n >\r\n <i class=\"pi pi-chevron-right fly-tree-nav__chevron\" aria-hidden=\"true\"></i>\r\n <span class=\"fly-tree-nav__label\">{{ node.label }}</span>\r\n @if (node.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ node.badge }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--item\"\r\n [class.fly-tree-nav__row--selected]=\"selectedId() === node.id\"\r\n [attr.aria-current]=\"selectedId() === node.id ? 'page' : null\"\r\n [attr.tabindex]=\"tabIndexFor(node.id)\"\r\n (click)=\"select(node.id)\"\r\n (keydown)=\"onKeydown($event, node.id)\"\r\n >\r\n <span class=\"fly-tree-nav__label\">{{ node.label }}</span>\r\n @if (node.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ node.badge }}</span>\r\n }\r\n </button>\r\n }\r\n\r\n @if (node.children && node.children.length > 0 && isExpanded(node.id)) {\r\n <ul class=\"fly-tree-nav__group\" [id]=\"'fly-tree-nav-group-' + node.id\">\r\n @for (child of node.children; track child.id) {\r\n <li>\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--item fly-tree-nav__row--child\"\r\n [class.fly-tree-nav__row--selected]=\"selectedId() === child.id\"\r\n [attr.aria-current]=\"selectedId() === child.id ? 'page' : null\"\r\n [attr.tabindex]=\"tabIndexFor(child.id)\"\r\n (click)=\"select(child.id)\"\r\n (keydown)=\"onKeydown($event, child.id)\"\r\n >\r\n <span class=\"fly-tree-nav__label\">{{ child.label }}</span>\r\n @if (child.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ child.badge }}</span>\r\n }\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n</nav>\r\n", styles: [":host{--fly-tree-nav-row-size: 32px;--fly-tree-nav-radius: 7px;--fly-tree-nav-indent: 22px;--fly-tree-nav-font: 13px;display:block}.fly-tree-nav__list,.fly-tree-nav__group{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1px}.fly-tree-nav__group{padding-inline-start:var(--fly-tree-nav-indent)}.fly-tree-nav__row{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:var(--fly-tree-nav-row-size);padding-inline:8px;border:0;border-inline-start:2px solid transparent;border-radius:var(--fly-tree-nav-radius);background:transparent;color:inherit;font-size:var(--fly-tree-nav-font);text-align:start;cursor:pointer;transition:background-color .15s ease}.fly-tree-nav__row:hover{background:var(--surface-hover)}.fly-tree-nav__row:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-2px}.fly-tree-nav__row--section{font-weight:600}.fly-tree-nav__row--child{font-weight:400}.fly-tree-nav__row--selected{background:var(--surface-hover);border-inline-start-color:var(--primary-color);color:var(--primary-color);font-weight:600}.fly-tree-nav__label{flex:1 1 auto;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-tree-nav__badge{flex-shrink:0;padding:1px 7px;border-radius:999px;background:var(--surface-hover);color:var(--text-color-secondary);font-size:10.5px;font-weight:600;line-height:1.6}.fly-tree-nav__chevron{flex-shrink:0;font-size:10px;color:var(--text-color-secondary);--fly-tn-flip: 1;--fly-tn-rotate: 0deg;transform:scaleX(var(--fly-tn-flip)) rotate(var(--fly-tn-rotate));transition:transform .15s ease}:host(.fly-tree-nav--rtl) .fly-tree-nav__chevron{--fly-tn-flip: -1}.fly-tree-nav__row--section[aria-expanded=true] .fly-tree-nav__chevron{--fly-tn-rotate: 90deg}@media(prefers-reduced-motion:reduce){.fly-tree-nav__row,.fly-tree-nav__chevron{transition:none}}@media(forced-colors:active){.fly-tree-nav__row--selected{border-inline-start-color:Highlight;color:LinkText}.fly-tree-nav__row:focus-visible{outline-color:Highlight}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10458
10458
  }
10459
10459
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyTreeNavComponent, decorators: [{
10460
10460
  type: Component,
10461
10461
  args: [{ selector: 'fly-tree-nav', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
10462
10462
  '[class.fly-tree-nav--rtl]': 'rtl()',
10463
- }, template: "<nav class=\"fly-tree-nav\" [attr.aria-label]=\"resolvedAriaLabel()\">\r\n <ul class=\"fly-tree-nav__list\">\r\n @for (node of nodes(); track node.id) {\r\n <li class=\"fly-tree-nav__section\">\r\n @if (node.children && node.children.length > 0) {\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--section\"\r\n [attr.aria-expanded]=\"isExpanded(node.id)\"\r\n [attr.aria-controls]=\"'fly-tree-nav-group-' + node.id\"\r\n [attr.tabindex]=\"tabIndexFor(node.id)\"\r\n (click)=\"toggle(node.id)\"\r\n (keydown)=\"onKeydown($event, node.id)\"\r\n >\r\n <i class=\"pi pi-chevron-right fly-tree-nav__chevron\" aria-hidden=\"true\"></i>\r\n <span class=\"fly-tree-nav__label\">{{ node.label }}</span>\r\n @if (node.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ node.badge }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--item\"\r\n [class.fly-tree-nav__row--selected]=\"selectedId() === node.id\"\r\n [attr.aria-current]=\"selectedId() === node.id ? 'page' : null\"\r\n [attr.tabindex]=\"tabIndexFor(node.id)\"\r\n (click)=\"select(node.id)\"\r\n (keydown)=\"onKeydown($event, node.id)\"\r\n >\r\n <span class=\"fly-tree-nav__label\">{{ node.label }}</span>\r\n @if (node.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ node.badge }}</span>\r\n }\r\n </button>\r\n }\r\n\r\n @if (node.children && node.children.length > 0 && isExpanded(node.id)) {\r\n <ul class=\"fly-tree-nav__group\" [id]=\"'fly-tree-nav-group-' + node.id\">\r\n @for (child of node.children; track child.id) {\r\n <li>\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--item fly-tree-nav__row--child\"\r\n [class.fly-tree-nav__row--selected]=\"selectedId() === child.id\"\r\n [attr.aria-current]=\"selectedId() === child.id ? 'page' : null\"\r\n [attr.tabindex]=\"tabIndexFor(child.id)\"\r\n (click)=\"select(child.id)\"\r\n (keydown)=\"onKeydown($event, child.id)\"\r\n >\r\n <span class=\"fly-tree-nav__label\">{{ child.label }}</span>\r\n @if (child.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ child.badge }}</span>\r\n }\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n</nav>\r\n", styles: [":host{--fly-tree-nav-row-size: 32px;--fly-tree-nav-radius: 7px;--fly-tree-nav-indent: 22px;--fly-tree-nav-font: 13px;display:block}.fly-tree-nav__list,.fly-tree-nav__group{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1px}.fly-tree-nav__group{padding-inline-start:var(--fly-tree-nav-indent)}.fly-tree-nav__row{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:var(--fly-tree-nav-row-size);padding-inline:8px;border:0;border-inline-start:2px solid transparent;border-radius:var(--fly-tree-nav-radius);background:transparent;color:inherit;font-size:var(--fly-tree-nav-font);text-align:start;cursor:pointer;transition:background-color .15s ease}.fly-tree-nav__row:hover{background:var(--surface-hover)}.fly-tree-nav__row:focus-visible{outline:2px solid var(--primary-color);outline-offset:-2px}.fly-tree-nav__row--section{font-weight:600}.fly-tree-nav__row--child{font-weight:400}.fly-tree-nav__row--selected{background:var(--surface-hover);border-inline-start-color:var(--primary-color);color:var(--primary-color);font-weight:600}.fly-tree-nav__label{flex:1 1 auto;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-tree-nav__badge{flex-shrink:0;padding:1px 7px;border-radius:999px;background:var(--surface-hover);color:var(--text-color-secondary);font-size:10.5px;font-weight:600;line-height:1.6}.fly-tree-nav__chevron{flex-shrink:0;font-size:10px;color:var(--text-color-secondary);--fly-tn-flip: 1;--fly-tn-rotate: 0deg;transform:scaleX(var(--fly-tn-flip)) rotate(var(--fly-tn-rotate));transition:transform .15s ease}:host(.fly-tree-nav--rtl) .fly-tree-nav__chevron{--fly-tn-flip: -1}.fly-tree-nav__row--section[aria-expanded=true] .fly-tree-nav__chevron{--fly-tn-rotate: 90deg}@media(prefers-reduced-motion:reduce){.fly-tree-nav__row,.fly-tree-nav__chevron{transition:none}}@media(forced-colors:active){.fly-tree-nav__row--selected{border-inline-start-color:Highlight;color:LinkText}.fly-tree-nav__row:focus-visible{outline-color:Highlight}}\n"] }]
10463
+ }, template: "<nav class=\"fly-tree-nav\" [attr.aria-label]=\"resolvedAriaLabel()\">\r\n <ul class=\"fly-tree-nav__list\">\r\n @for (node of nodes(); track node.id) {\r\n <li class=\"fly-tree-nav__section\">\r\n @if (node.children && node.children.length > 0) {\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--section\"\r\n [attr.aria-expanded]=\"isExpanded(node.id)\"\r\n [attr.aria-controls]=\"'fly-tree-nav-group-' + node.id\"\r\n [attr.tabindex]=\"tabIndexFor(node.id)\"\r\n (click)=\"toggle(node.id)\"\r\n (keydown)=\"onKeydown($event, node.id)\"\r\n >\r\n <i class=\"pi pi-chevron-right fly-tree-nav__chevron\" aria-hidden=\"true\"></i>\r\n <span class=\"fly-tree-nav__label\">{{ node.label }}</span>\r\n @if (node.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ node.badge }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--item\"\r\n [class.fly-tree-nav__row--selected]=\"selectedId() === node.id\"\r\n [attr.aria-current]=\"selectedId() === node.id ? 'page' : null\"\r\n [attr.tabindex]=\"tabIndexFor(node.id)\"\r\n (click)=\"select(node.id)\"\r\n (keydown)=\"onKeydown($event, node.id)\"\r\n >\r\n <span class=\"fly-tree-nav__label\">{{ node.label }}</span>\r\n @if (node.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ node.badge }}</span>\r\n }\r\n </button>\r\n }\r\n\r\n @if (node.children && node.children.length > 0 && isExpanded(node.id)) {\r\n <ul class=\"fly-tree-nav__group\" [id]=\"'fly-tree-nav-group-' + node.id\">\r\n @for (child of node.children; track child.id) {\r\n <li>\r\n <button\r\n #navRow\r\n type=\"button\"\r\n class=\"fly-tree-nav__row fly-tree-nav__row--item fly-tree-nav__row--child\"\r\n [class.fly-tree-nav__row--selected]=\"selectedId() === child.id\"\r\n [attr.aria-current]=\"selectedId() === child.id ? 'page' : null\"\r\n [attr.tabindex]=\"tabIndexFor(child.id)\"\r\n (click)=\"select(child.id)\"\r\n (keydown)=\"onKeydown($event, child.id)\"\r\n >\r\n <span class=\"fly-tree-nav__label\">{{ child.label }}</span>\r\n @if (child.badge) {\r\n <span class=\"fly-tree-nav__badge\">{{ child.badge }}</span>\r\n }\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n</nav>\r\n", styles: [":host{--fly-tree-nav-row-size: 32px;--fly-tree-nav-radius: 7px;--fly-tree-nav-indent: 22px;--fly-tree-nav-font: 13px;display:block}.fly-tree-nav__list,.fly-tree-nav__group{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1px}.fly-tree-nav__group{padding-inline-start:var(--fly-tree-nav-indent)}.fly-tree-nav__row{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:var(--fly-tree-nav-row-size);padding-inline:8px;border:0;border-inline-start:2px solid transparent;border-radius:var(--fly-tree-nav-radius);background:transparent;color:inherit;font-size:var(--fly-tree-nav-font);text-align:start;cursor:pointer;transition:background-color .15s ease}.fly-tree-nav__row:hover{background:var(--surface-hover)}.fly-tree-nav__row:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:-2px}.fly-tree-nav__row--section{font-weight:600}.fly-tree-nav__row--child{font-weight:400}.fly-tree-nav__row--selected{background:var(--surface-hover);border-inline-start-color:var(--primary-color);color:var(--primary-color);font-weight:600}.fly-tree-nav__label{flex:1 1 auto;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-tree-nav__badge{flex-shrink:0;padding:1px 7px;border-radius:999px;background:var(--surface-hover);color:var(--text-color-secondary);font-size:10.5px;font-weight:600;line-height:1.6}.fly-tree-nav__chevron{flex-shrink:0;font-size:10px;color:var(--text-color-secondary);--fly-tn-flip: 1;--fly-tn-rotate: 0deg;transform:scaleX(var(--fly-tn-flip)) rotate(var(--fly-tn-rotate));transition:transform .15s ease}:host(.fly-tree-nav--rtl) .fly-tree-nav__chevron{--fly-tn-flip: -1}.fly-tree-nav__row--section[aria-expanded=true] .fly-tree-nav__chevron{--fly-tn-rotate: 90deg}@media(prefers-reduced-motion:reduce){.fly-tree-nav__row,.fly-tree-nav__chevron{transition:none}}@media(forced-colors:active){.fly-tree-nav__row--selected{border-inline-start-color:Highlight;color:LinkText}.fly-tree-nav__row:focus-visible{outline-color:Highlight}}\n"] }]
10464
10464
  }], ctorParameters: () => [], propDecorators: { nodes: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodes", required: false }] }], selectedId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedId", required: false }] }, { type: i0.Output, args: ["selectedIdChange"] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], rowEls: [{ type: i0.ViewChildren, args: ['navRow', { isSignal: true }] }] } });
10465
10465
 
10466
10466
  /**
@@ -11750,7 +11750,7 @@ class FlySelectComponent {
11750
11750
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlySelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11751
11751
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlySelectComponent, isStandalone: true, selector: "fly-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, showSelectAll: { classPropertyName: "showSelectAll", publicName: "showSelectAll", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, noResultsLabel: { classPropertyName: "noResultsLabel", publicName: "noResultsLabel", isSignal: true, isRequired: false, transformFunction: null }, selectAllLabel: { classPropertyName: "selectAllLabel", publicName: "selectAllLabel", isSignal: true, isRequired: false, transformFunction: null }, deselectAllLabel: { classPropertyName: "deselectAllLabel", publicName: "deselectAllLabel", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, summaryFormatter: { classPropertyName: "summaryFormatter", publicName: "summaryFormatter", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", openedChange: "openedChange" }, host: { properties: { "class.fly-select--open": "isOpen()", "class.fly-select--disabled": "effectiveDisabled()" }, classAttribute: "fly-select" }, providers: [
11752
11752
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => FlySelectComponent), multi: true },
11753
- ], viewQueries: [{ propertyName: "panelEl", first: true, predicate: ["panelRef"], descendants: true, isSignal: true }, { propertyName: "searchEl", first: true, predicate: ["searchRef"], descendants: true }, { propertyName: "triggerEl", first: true, predicate: ["triggerRef"], descendants: true }], ngImport: i0, template: "<!-- \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<button\r\n #triggerRef\r\n type=\"button\"\r\n [id]=\"triggerId\"\r\n class=\"fly-select__trigger\"\r\n role=\"combobox\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [class.fly-select__trigger--placeholder]=\"!hasSelection()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleOpen()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n>\r\n <span class=\"fly-select__trigger-label\">{{ triggerLabel() }}</span>\r\n\r\n @if (clearable() && hasSelection() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-select__clear\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"clearText()\"\r\n [title]=\"clearText()\"\r\n (click)=\"clear($event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n\r\n <span class=\"fly-select__chevron\" aria-hidden=\"true\">\u25BE</span>\r\n</button>\r\n\r\n<!-- \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<!-- Portaled to <body> by the component (see class docblock) \u2014 position: fixed, computed from\r\n the trigger. [style.*] bindings null out the unused axis (top XOR bottom, left XOR right)\r\n rather than leaving a stale 0, which is what lets the flip-above / RTL cases each win\r\n outright instead of fighting a leftover declaration from the other branch. -->\r\n@if (isOpen()) {\r\n <div\r\n #panelRef\r\n class=\"fly-select__panel\"\r\n [class.fly-select__panel--flip]=\"panelPosition()?.flipAbove\"\r\n [style.top.px]=\"panelPosition()?.top\"\r\n [style.bottom.px]=\"panelPosition()?.bottom\"\r\n [style.left.px]=\"panelPosition()?.left\"\r\n [style.right.px]=\"panelPosition()?.right\"\r\n [style.min-width.px]=\"panelPosition()?.minWidth\"\r\n [style.max-height.px]=\"panelPosition()?.maxHeight\"\r\n tabindex=\"-1\"\r\n (keydown)=\"onPanelKeydown($event)\"\r\n >\r\n @if (searchable()) {\r\n <div class=\"fly-select__search\">\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-select__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"true\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"searchPlaceholderText()\"\r\n [placeholder]=\"searchPlaceholderText()\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @if (multiple() && showSelectAll() && navigableOptions().length > 0) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-select__select-all\"\r\n (click)=\"toggleSelectAll()\"\r\n >\r\n {{ allVisibleSelected() ? deselectAllText() : selectAllText() }}\r\n </button>\r\n }\r\n\r\n <div\r\n class=\"fly-select__listbox\"\r\n role=\"listbox\"\r\n [id]=\"listboxId\"\r\n [attr.tabindex]=\"searchable() ? null : 0\"\r\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n >\r\n @for (group of renderGroups(); track group.key) {\r\n @if (group.key !== null) {\r\n <div class=\"fly-select__group-label\" role=\"presentation\">{{ group.key }}</div>\r\n }\r\n @for (opt of group.options; track opt.value) {\r\n <div\r\n class=\"fly-select__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"opt.disabled ? null : optionId(navIndexOf(opt.value))\"\r\n [attr.aria-selected]=\"isSelected(opt.value)\"\r\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\r\n [class.fly-select__option--selected]=\"isSelected(opt.value)\"\r\n [class.fly-select__option--active]=\"!opt.disabled && navIndexOf(opt.value) === activeNavIndex()\"\r\n [class.fly-select__option--disabled]=\"opt.disabled\"\r\n (click)=\"onOptionClick(opt)\"\r\n (keydown.enter)=\"onOptionClick(opt)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(opt.value))\"\r\n >\r\n @if (multiple()) {\r\n <span class=\"fly-select__checkbox\" aria-hidden=\"true\">\r\n @if (isSelected(opt.value)) { <span class=\"fly-select__checkbox-tick\">\u2713</span> }\r\n </span>\r\n } @else {\r\n <span class=\"fly-select__check\" aria-hidden=\"true\">\r\n @if (isSelected(opt.value)) { \u2713 }\r\n </span>\r\n }\r\n <span class=\"fly-select__option-label\">{{ opt.label }}</span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (filteredOptions().length === 0) {\r\n <div class=\"fly-select__empty\" role=\"presentation\">{{ noResultsText() }}</div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after,.fly-select__panel,.fly-select__panel *,.fly-select__panel *:before,.fly-select__panel *:after{box-sizing:border-box}:host{display:inline-block;inline-size:100%;min-inline-size:12rem}.fly-select__trigger{display:flex;align-items:center;gap:8px;inline-size:100%;block-size:36px;padding-inline:11px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family);text-align:start;cursor:pointer;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__trigger:hover:not(:disabled){background:var(--w07)}.fly-select__trigger:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:inherit}.fly-select__trigger:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}:host(.fly-select--open) .fly-select__trigger{border-color:var(--accent);background:var(--w08)}.fly-select__trigger--placeholder .fly-select__trigger-label{color:var(--w42)}.fly-select__trigger-label{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-select__clear{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;border-radius:50%;color:var(--w42);font-size:11px;line-height:1;cursor:pointer;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__clear:hover{background:var(--w1);color:var(--w85)}.fly-select__chevron{flex:0 0 auto;color:var(--w45);font-size:10px;transition:transform .22s var(--nova-ease-structural)}:host(.fly-select--open) .fly-select__chevron{transform:rotate(180deg)}@media(pointer:coarse){.fly-select__trigger{min-block-size:44px}.fly-select__clear{inline-size:24px;block-size:24px}}.fly-select__panel{position:fixed;z-index:1000;display:flex;flex-direction:column;inline-size:max-content;max-inline-size:min(420px,90vw);overflow:hidden;padding:6px;border-radius:14px;animation:menuIn .24s var(--nova-ease-structural) both;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.fly-select__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-select__panel:before,.fly-select__panel:after{display:none}}@media(prefers-contrast:more){.fly-select__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-select__panel:after{animation:none}}.fly-select__search{padding:6px;border-block-end:1px solid var(--w08)}.fly-select__search-input{inline-size:100%;block-size:30px;padding-inline:9px;border:1px solid var(--w14);border-radius:8px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family)}.fly-select__search-input::placeholder{color:var(--w42)}.fly-select__search-input:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.fly-select__select-all{display:block;inline-size:100%;padding:7px 9px;border:0;border-block-end:1px solid var(--w08);background:transparent;color:var(--accent);font:600 12.5px/1.3 var(--font-family);text-align:start;cursor:pointer}.fly-select__select-all:hover{background:var(--w1)}.fly-select__listbox{flex:1 1 auto;min-block-size:0;overflow-y:auto;padding-block:4px}.fly-select__listbox:focus-visible{outline:none}.fly-select__group-label{padding:6px 9px 2px;color:var(--w5);font:var(--nova-font-eyebrow);letter-spacing:var(--nova-tracking-eyebrow);text-transform:uppercase}.fly-select__option{display:flex;align-items:center;gap:8px;min-block-size:32px;padding:7px 9px;border-radius:8px;color:var(--w85);font:500 13px/1.3 var(--font-family);cursor:pointer;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__option--active{background:var(--w1)}.fly-select__option--selected{background:var(--w08);font-weight:600}.fly-select__option--selected.fly-select__option--active{background:var(--w08);box-shadow:inset 0 0 0 1px var(--accent)}.fly-select__option--disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed;pointer-events:none}.fly-select__option-label{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-select__check{flex:0 0 auto;inline-size:16px;color:var(--accent);font-size:14px;font-weight:600;text-align:center}.fly-select__checkbox{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;inline-size:16px;block-size:16px;border:1.5px solid var(--w22);border-radius:4px;transition:background var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__option--selected .fly-select__checkbox{background:var(--accent);border-color:var(--accent)}.fly-select__checkbox-tick{color:var(--on-accent);font-size:10px;line-height:1}.fly-select__empty{padding:16px 9px;text-align:center;color:var(--w42);font:400 12.5px/1.4 var(--font-family)}@media(pointer:coarse){.fly-select__option{min-block-size:44px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11753
+ ], viewQueries: [{ propertyName: "panelEl", first: true, predicate: ["panelRef"], descendants: true, isSignal: true }, { propertyName: "searchEl", first: true, predicate: ["searchRef"], descendants: true }, { propertyName: "triggerEl", first: true, predicate: ["triggerRef"], descendants: true }], ngImport: i0, template: "<!-- \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<button\r\n #triggerRef\r\n type=\"button\"\r\n [id]=\"triggerId\"\r\n class=\"fly-select__trigger\"\r\n role=\"combobox\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [class.fly-select__trigger--placeholder]=\"!hasSelection()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleOpen()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n>\r\n <span class=\"fly-select__trigger-label\">{{ triggerLabel() }}</span>\r\n\r\n @if (clearable() && hasSelection() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-select__clear\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"clearText()\"\r\n [title]=\"clearText()\"\r\n (click)=\"clear($event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n\r\n <span class=\"fly-select__chevron\" aria-hidden=\"true\">\u25BE</span>\r\n</button>\r\n\r\n<!-- \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<!-- Portaled to <body> by the component (see class docblock) \u2014 position: fixed, computed from\r\n the trigger. [style.*] bindings null out the unused axis (top XOR bottom, left XOR right)\r\n rather than leaving a stale 0, which is what lets the flip-above / RTL cases each win\r\n outright instead of fighting a leftover declaration from the other branch. -->\r\n@if (isOpen()) {\r\n <div\r\n #panelRef\r\n class=\"fly-select__panel\"\r\n [class.fly-select__panel--flip]=\"panelPosition()?.flipAbove\"\r\n [style.top.px]=\"panelPosition()?.top\"\r\n [style.bottom.px]=\"panelPosition()?.bottom\"\r\n [style.left.px]=\"panelPosition()?.left\"\r\n [style.right.px]=\"panelPosition()?.right\"\r\n [style.min-width.px]=\"panelPosition()?.minWidth\"\r\n [style.max-height.px]=\"panelPosition()?.maxHeight\"\r\n tabindex=\"-1\"\r\n (keydown)=\"onPanelKeydown($event)\"\r\n >\r\n @if (searchable()) {\r\n <div class=\"fly-select__search\">\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-select__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"true\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"searchPlaceholderText()\"\r\n [placeholder]=\"searchPlaceholderText()\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @if (multiple() && showSelectAll() && navigableOptions().length > 0) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-select__select-all\"\r\n (click)=\"toggleSelectAll()\"\r\n >\r\n {{ allVisibleSelected() ? deselectAllText() : selectAllText() }}\r\n </button>\r\n }\r\n\r\n <div\r\n class=\"fly-select__listbox\"\r\n role=\"listbox\"\r\n [id]=\"listboxId\"\r\n [attr.tabindex]=\"searchable() ? null : 0\"\r\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n >\r\n @for (group of renderGroups(); track group.key) {\r\n @if (group.key !== null) {\r\n <div class=\"fly-select__group-label\" role=\"presentation\">{{ group.key }}</div>\r\n }\r\n @for (opt of group.options; track opt.value) {\r\n <div\r\n class=\"fly-select__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"opt.disabled ? null : optionId(navIndexOf(opt.value))\"\r\n [attr.aria-selected]=\"isSelected(opt.value)\"\r\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\r\n [class.fly-select__option--selected]=\"isSelected(opt.value)\"\r\n [class.fly-select__option--active]=\"!opt.disabled && navIndexOf(opt.value) === activeNavIndex()\"\r\n [class.fly-select__option--disabled]=\"opt.disabled\"\r\n (click)=\"onOptionClick(opt)\"\r\n (keydown.enter)=\"onOptionClick(opt)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(opt.value))\"\r\n >\r\n @if (multiple()) {\r\n <span class=\"fly-select__checkbox\" aria-hidden=\"true\">\r\n @if (isSelected(opt.value)) { <span class=\"fly-select__checkbox-tick\">\u2713</span> }\r\n </span>\r\n } @else {\r\n <span class=\"fly-select__check\" aria-hidden=\"true\">\r\n @if (isSelected(opt.value)) { \u2713 }\r\n </span>\r\n }\r\n <span class=\"fly-select__option-label\">{{ opt.label }}</span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (filteredOptions().length === 0) {\r\n <div class=\"fly-select__empty\" role=\"presentation\">{{ noResultsText() }}</div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after,.fly-select__panel,.fly-select__panel *,.fly-select__panel *:before,.fly-select__panel *:after{box-sizing:border-box}:host{display:inline-block;inline-size:100%;min-inline-size:12rem}.fly-select__trigger{display:flex;align-items:center;gap:8px;inline-size:100%;block-size:36px;padding-inline:11px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family);text-align:start;cursor:pointer;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__trigger:hover:not(:disabled){background:var(--w07)}.fly-select__trigger:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px;border-radius:inherit}.fly-select__trigger:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}:host(.fly-select--open) .fly-select__trigger{border-color:var(--accent);background:var(--w08)}.fly-select__trigger--placeholder .fly-select__trigger-label{color:var(--w42)}.fly-select__trigger-label{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-select__clear{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;border-radius:50%;color:var(--w42);font-size:11px;line-height:1;cursor:pointer;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__clear:hover{background:var(--w1);color:var(--w85)}.fly-select__chevron{flex:0 0 auto;color:var(--w45);font-size:10px;transition:transform .22s var(--nova-ease-structural)}:host(.fly-select--open) .fly-select__chevron{transform:rotate(180deg)}@media(pointer:coarse){.fly-select__trigger{min-block-size:44px}.fly-select__clear{inline-size:24px;block-size:24px}}.fly-select__panel{position:fixed;z-index:1000;display:flex;flex-direction:column;inline-size:max-content;max-inline-size:min(420px,90vw);overflow:hidden;padding:6px;border-radius:14px;animation:menuIn .24s var(--nova-ease-structural) both;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.fly-select__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-select__panel:before,.fly-select__panel:after{display:none}}@media(prefers-contrast:more){.fly-select__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-select__panel:after{animation:none}}.fly-select__search{padding:6px;border-block-end:1px solid var(--w08)}.fly-select__search-input{inline-size:100%;block-size:30px;padding-inline:9px;border:1px solid var(--w14);border-radius:8px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family)}.fly-select__search-input::placeholder{color:var(--w42)}.fly-select__search-input:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.fly-select__select-all{display:block;inline-size:100%;padding:7px 9px;border:0;border-block-end:1px solid var(--w08);background:transparent;color:var(--accent);font:600 12.5px/1.3 var(--font-family);text-align:start;cursor:pointer}.fly-select__select-all:hover{background:var(--w1)}.fly-select__listbox{flex:1 1 auto;min-block-size:0;overflow-y:auto;padding-block:4px}.fly-select__listbox:focus-visible{outline:none}.fly-select__group-label{padding:6px 9px 2px;color:var(--w5);font:var(--nova-font-eyebrow);letter-spacing:var(--nova-tracking-eyebrow);text-transform:uppercase}.fly-select__option{display:flex;align-items:center;gap:8px;min-block-size:32px;padding:7px 9px;border-radius:8px;color:var(--w85);font:500 13px/1.3 var(--font-family);cursor:pointer;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__option--active{background:var(--w1)}.fly-select__option--selected{background:var(--w08);font-weight:600}.fly-select__option--selected.fly-select__option--active{background:var(--w08);box-shadow:inset 0 0 0 1px var(--accent)}.fly-select__option--disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed;pointer-events:none}.fly-select__option-label{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-select__check{flex:0 0 auto;inline-size:16px;color:var(--accent);font-size:14px;font-weight:600;text-align:center}.fly-select__checkbox{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;inline-size:16px;block-size:16px;border:1.5px solid var(--w22);border-radius:4px;transition:background var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__option--selected .fly-select__checkbox{background:var(--accent);border-color:var(--accent)}.fly-select__checkbox-tick{color:var(--on-accent);font-size:10px;line-height:1}.fly-select__empty{padding:16px 9px;text-align:center;color:var(--w42);font:400 12.5px/1.4 var(--font-family)}@media(pointer:coarse){.fly-select__option{min-block-size:44px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11754
11754
  }
11755
11755
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlySelectComponent, decorators: [{
11756
11756
  type: Component,
@@ -11760,7 +11760,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
11760
11760
  class: 'fly-select',
11761
11761
  '[class.fly-select--open]': 'isOpen()',
11762
11762
  '[class.fly-select--disabled]': 'effectiveDisabled()',
11763
- }, template: "<!-- \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<button\r\n #triggerRef\r\n type=\"button\"\r\n [id]=\"triggerId\"\r\n class=\"fly-select__trigger\"\r\n role=\"combobox\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [class.fly-select__trigger--placeholder]=\"!hasSelection()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleOpen()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n>\r\n <span class=\"fly-select__trigger-label\">{{ triggerLabel() }}</span>\r\n\r\n @if (clearable() && hasSelection() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-select__clear\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"clearText()\"\r\n [title]=\"clearText()\"\r\n (click)=\"clear($event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n\r\n <span class=\"fly-select__chevron\" aria-hidden=\"true\">\u25BE</span>\r\n</button>\r\n\r\n<!-- \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<!-- Portaled to <body> by the component (see class docblock) \u2014 position: fixed, computed from\r\n the trigger. [style.*] bindings null out the unused axis (top XOR bottom, left XOR right)\r\n rather than leaving a stale 0, which is what lets the flip-above / RTL cases each win\r\n outright instead of fighting a leftover declaration from the other branch. -->\r\n@if (isOpen()) {\r\n <div\r\n #panelRef\r\n class=\"fly-select__panel\"\r\n [class.fly-select__panel--flip]=\"panelPosition()?.flipAbove\"\r\n [style.top.px]=\"panelPosition()?.top\"\r\n [style.bottom.px]=\"panelPosition()?.bottom\"\r\n [style.left.px]=\"panelPosition()?.left\"\r\n [style.right.px]=\"panelPosition()?.right\"\r\n [style.min-width.px]=\"panelPosition()?.minWidth\"\r\n [style.max-height.px]=\"panelPosition()?.maxHeight\"\r\n tabindex=\"-1\"\r\n (keydown)=\"onPanelKeydown($event)\"\r\n >\r\n @if (searchable()) {\r\n <div class=\"fly-select__search\">\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-select__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"true\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"searchPlaceholderText()\"\r\n [placeholder]=\"searchPlaceholderText()\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @if (multiple() && showSelectAll() && navigableOptions().length > 0) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-select__select-all\"\r\n (click)=\"toggleSelectAll()\"\r\n >\r\n {{ allVisibleSelected() ? deselectAllText() : selectAllText() }}\r\n </button>\r\n }\r\n\r\n <div\r\n class=\"fly-select__listbox\"\r\n role=\"listbox\"\r\n [id]=\"listboxId\"\r\n [attr.tabindex]=\"searchable() ? null : 0\"\r\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n >\r\n @for (group of renderGroups(); track group.key) {\r\n @if (group.key !== null) {\r\n <div class=\"fly-select__group-label\" role=\"presentation\">{{ group.key }}</div>\r\n }\r\n @for (opt of group.options; track opt.value) {\r\n <div\r\n class=\"fly-select__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"opt.disabled ? null : optionId(navIndexOf(opt.value))\"\r\n [attr.aria-selected]=\"isSelected(opt.value)\"\r\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\r\n [class.fly-select__option--selected]=\"isSelected(opt.value)\"\r\n [class.fly-select__option--active]=\"!opt.disabled && navIndexOf(opt.value) === activeNavIndex()\"\r\n [class.fly-select__option--disabled]=\"opt.disabled\"\r\n (click)=\"onOptionClick(opt)\"\r\n (keydown.enter)=\"onOptionClick(opt)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(opt.value))\"\r\n >\r\n @if (multiple()) {\r\n <span class=\"fly-select__checkbox\" aria-hidden=\"true\">\r\n @if (isSelected(opt.value)) { <span class=\"fly-select__checkbox-tick\">\u2713</span> }\r\n </span>\r\n } @else {\r\n <span class=\"fly-select__check\" aria-hidden=\"true\">\r\n @if (isSelected(opt.value)) { \u2713 }\r\n </span>\r\n }\r\n <span class=\"fly-select__option-label\">{{ opt.label }}</span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (filteredOptions().length === 0) {\r\n <div class=\"fly-select__empty\" role=\"presentation\">{{ noResultsText() }}</div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after,.fly-select__panel,.fly-select__panel *,.fly-select__panel *:before,.fly-select__panel *:after{box-sizing:border-box}:host{display:inline-block;inline-size:100%;min-inline-size:12rem}.fly-select__trigger{display:flex;align-items:center;gap:8px;inline-size:100%;block-size:36px;padding-inline:11px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family);text-align:start;cursor:pointer;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__trigger:hover:not(:disabled){background:var(--w07)}.fly-select__trigger:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:inherit}.fly-select__trigger:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}:host(.fly-select--open) .fly-select__trigger{border-color:var(--accent);background:var(--w08)}.fly-select__trigger--placeholder .fly-select__trigger-label{color:var(--w42)}.fly-select__trigger-label{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-select__clear{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;border-radius:50%;color:var(--w42);font-size:11px;line-height:1;cursor:pointer;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__clear:hover{background:var(--w1);color:var(--w85)}.fly-select__chevron{flex:0 0 auto;color:var(--w45);font-size:10px;transition:transform .22s var(--nova-ease-structural)}:host(.fly-select--open) .fly-select__chevron{transform:rotate(180deg)}@media(pointer:coarse){.fly-select__trigger{min-block-size:44px}.fly-select__clear{inline-size:24px;block-size:24px}}.fly-select__panel{position:fixed;z-index:1000;display:flex;flex-direction:column;inline-size:max-content;max-inline-size:min(420px,90vw);overflow:hidden;padding:6px;border-radius:14px;animation:menuIn .24s var(--nova-ease-structural) both;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.fly-select__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-select__panel:before,.fly-select__panel:after{display:none}}@media(prefers-contrast:more){.fly-select__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-select__panel:after{animation:none}}.fly-select__search{padding:6px;border-block-end:1px solid var(--w08)}.fly-select__search-input{inline-size:100%;block-size:30px;padding-inline:9px;border:1px solid var(--w14);border-radius:8px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family)}.fly-select__search-input::placeholder{color:var(--w42)}.fly-select__search-input:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.fly-select__select-all{display:block;inline-size:100%;padding:7px 9px;border:0;border-block-end:1px solid var(--w08);background:transparent;color:var(--accent);font:600 12.5px/1.3 var(--font-family);text-align:start;cursor:pointer}.fly-select__select-all:hover{background:var(--w1)}.fly-select__listbox{flex:1 1 auto;min-block-size:0;overflow-y:auto;padding-block:4px}.fly-select__listbox:focus-visible{outline:none}.fly-select__group-label{padding:6px 9px 2px;color:var(--w5);font:var(--nova-font-eyebrow);letter-spacing:var(--nova-tracking-eyebrow);text-transform:uppercase}.fly-select__option{display:flex;align-items:center;gap:8px;min-block-size:32px;padding:7px 9px;border-radius:8px;color:var(--w85);font:500 13px/1.3 var(--font-family);cursor:pointer;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__option--active{background:var(--w1)}.fly-select__option--selected{background:var(--w08);font-weight:600}.fly-select__option--selected.fly-select__option--active{background:var(--w08);box-shadow:inset 0 0 0 1px var(--accent)}.fly-select__option--disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed;pointer-events:none}.fly-select__option-label{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-select__check{flex:0 0 auto;inline-size:16px;color:var(--accent);font-size:14px;font-weight:600;text-align:center}.fly-select__checkbox{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;inline-size:16px;block-size:16px;border:1.5px solid var(--w22);border-radius:4px;transition:background var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__option--selected .fly-select__checkbox{background:var(--accent);border-color:var(--accent)}.fly-select__checkbox-tick{color:var(--on-accent);font-size:10px;line-height:1}.fly-select__empty{padding:16px 9px;text-align:center;color:var(--w42);font:400 12.5px/1.4 var(--font-family)}@media(pointer:coarse){.fly-select__option{min-block-size:44px}}\n"] }]
11763
+ }, template: "<!-- \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<button\r\n #triggerRef\r\n type=\"button\"\r\n [id]=\"triggerId\"\r\n class=\"fly-select__trigger\"\r\n role=\"combobox\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n [class.fly-select__trigger--placeholder]=\"!hasSelection()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleOpen()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n>\r\n <span class=\"fly-select__trigger-label\">{{ triggerLabel() }}</span>\r\n\r\n @if (clearable() && hasSelection() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-select__clear\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"clearText()\"\r\n [title]=\"clearText()\"\r\n (click)=\"clear($event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n\r\n <span class=\"fly-select__chevron\" aria-hidden=\"true\">\u25BE</span>\r\n</button>\r\n\r\n<!-- \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<!-- Portaled to <body> by the component (see class docblock) \u2014 position: fixed, computed from\r\n the trigger. [style.*] bindings null out the unused axis (top XOR bottom, left XOR right)\r\n rather than leaving a stale 0, which is what lets the flip-above / RTL cases each win\r\n outright instead of fighting a leftover declaration from the other branch. -->\r\n@if (isOpen()) {\r\n <div\r\n #panelRef\r\n class=\"fly-select__panel\"\r\n [class.fly-select__panel--flip]=\"panelPosition()?.flipAbove\"\r\n [style.top.px]=\"panelPosition()?.top\"\r\n [style.bottom.px]=\"panelPosition()?.bottom\"\r\n [style.left.px]=\"panelPosition()?.left\"\r\n [style.right.px]=\"panelPosition()?.right\"\r\n [style.min-width.px]=\"panelPosition()?.minWidth\"\r\n [style.max-height.px]=\"panelPosition()?.maxHeight\"\r\n tabindex=\"-1\"\r\n (keydown)=\"onPanelKeydown($event)\"\r\n >\r\n @if (searchable()) {\r\n <div class=\"fly-select__search\">\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-select__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"true\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"searchPlaceholderText()\"\r\n [placeholder]=\"searchPlaceholderText()\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @if (multiple() && showSelectAll() && navigableOptions().length > 0) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-select__select-all\"\r\n (click)=\"toggleSelectAll()\"\r\n >\r\n {{ allVisibleSelected() ? deselectAllText() : selectAllText() }}\r\n </button>\r\n }\r\n\r\n <div\r\n class=\"fly-select__listbox\"\r\n role=\"listbox\"\r\n [id]=\"listboxId\"\r\n [attr.tabindex]=\"searchable() ? null : 0\"\r\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n >\r\n @for (group of renderGroups(); track group.key) {\r\n @if (group.key !== null) {\r\n <div class=\"fly-select__group-label\" role=\"presentation\">{{ group.key }}</div>\r\n }\r\n @for (opt of group.options; track opt.value) {\r\n <div\r\n class=\"fly-select__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"opt.disabled ? null : optionId(navIndexOf(opt.value))\"\r\n [attr.aria-selected]=\"isSelected(opt.value)\"\r\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\r\n [class.fly-select__option--selected]=\"isSelected(opt.value)\"\r\n [class.fly-select__option--active]=\"!opt.disabled && navIndexOf(opt.value) === activeNavIndex()\"\r\n [class.fly-select__option--disabled]=\"opt.disabled\"\r\n (click)=\"onOptionClick(opt)\"\r\n (keydown.enter)=\"onOptionClick(opt)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(opt.value))\"\r\n >\r\n @if (multiple()) {\r\n <span class=\"fly-select__checkbox\" aria-hidden=\"true\">\r\n @if (isSelected(opt.value)) { <span class=\"fly-select__checkbox-tick\">\u2713</span> }\r\n </span>\r\n } @else {\r\n <span class=\"fly-select__check\" aria-hidden=\"true\">\r\n @if (isSelected(opt.value)) { \u2713 }\r\n </span>\r\n }\r\n <span class=\"fly-select__option-label\">{{ opt.label }}</span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (filteredOptions().length === 0) {\r\n <div class=\"fly-select__empty\" role=\"presentation\">{{ noResultsText() }}</div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after,.fly-select__panel,.fly-select__panel *,.fly-select__panel *:before,.fly-select__panel *:after{box-sizing:border-box}:host{display:inline-block;inline-size:100%;min-inline-size:12rem}.fly-select__trigger{display:flex;align-items:center;gap:8px;inline-size:100%;block-size:36px;padding-inline:11px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family);text-align:start;cursor:pointer;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__trigger:hover:not(:disabled){background:var(--w07)}.fly-select__trigger:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px;border-radius:inherit}.fly-select__trigger:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}:host(.fly-select--open) .fly-select__trigger{border-color:var(--accent);background:var(--w08)}.fly-select__trigger--placeholder .fly-select__trigger-label{color:var(--w42)}.fly-select__trigger-label{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-select__clear{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;border-radius:50%;color:var(--w42);font-size:11px;line-height:1;cursor:pointer;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__clear:hover{background:var(--w1);color:var(--w85)}.fly-select__chevron{flex:0 0 auto;color:var(--w45);font-size:10px;transition:transform .22s var(--nova-ease-structural)}:host(.fly-select--open) .fly-select__chevron{transform:rotate(180deg)}@media(pointer:coarse){.fly-select__trigger{min-block-size:44px}.fly-select__clear{inline-size:24px;block-size:24px}}.fly-select__panel{position:fixed;z-index:1000;display:flex;flex-direction:column;inline-size:max-content;max-inline-size:min(420px,90vw);overflow:hidden;padding:6px;border-radius:14px;animation:menuIn .24s var(--nova-ease-structural) both;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.fly-select__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-select__panel:before,.fly-select__panel:after{display:none}}@media(prefers-contrast:more){.fly-select__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-select__panel:after{animation:none}}.fly-select__search{padding:6px;border-block-end:1px solid var(--w08)}.fly-select__search-input{inline-size:100%;block-size:30px;padding-inline:9px;border:1px solid var(--w14);border-radius:8px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family)}.fly-select__search-input::placeholder{color:var(--w42)}.fly-select__search-input:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.fly-select__select-all{display:block;inline-size:100%;padding:7px 9px;border:0;border-block-end:1px solid var(--w08);background:transparent;color:var(--accent);font:600 12.5px/1.3 var(--font-family);text-align:start;cursor:pointer}.fly-select__select-all:hover{background:var(--w1)}.fly-select__listbox{flex:1 1 auto;min-block-size:0;overflow-y:auto;padding-block:4px}.fly-select__listbox:focus-visible{outline:none}.fly-select__group-label{padding:6px 9px 2px;color:var(--w5);font:var(--nova-font-eyebrow);letter-spacing:var(--nova-tracking-eyebrow);text-transform:uppercase}.fly-select__option{display:flex;align-items:center;gap:8px;min-block-size:32px;padding:7px 9px;border-radius:8px;color:var(--w85);font:500 13px/1.3 var(--font-family);cursor:pointer;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__option--active{background:var(--w1)}.fly-select__option--selected{background:var(--w08);font-weight:600}.fly-select__option--selected.fly-select__option--active{background:var(--w08);box-shadow:inset 0 0 0 1px var(--accent)}.fly-select__option--disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed;pointer-events:none}.fly-select__option-label{flex:1 1 auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-select__check{flex:0 0 auto;inline-size:16px;color:var(--accent);font-size:14px;font-weight:600;text-align:center}.fly-select__checkbox{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;inline-size:16px;block-size:16px;border:1.5px solid var(--w22);border-radius:4px;transition:background var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.fly-select__option--selected .fly-select__checkbox{background:var(--accent);border-color:var(--accent)}.fly-select__checkbox-tick{color:var(--on-accent);font-size:10px;line-height:1}.fly-select__empty{padding:16px 9px;text-align:center;color:var(--w42);font:400 12.5px/1.4 var(--font-family)}@media(pointer:coarse){.fly-select__option{min-block-size:44px}}\n"] }]
11764
11764
  }], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], showSelectAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSelectAll", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], noResultsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsLabel", required: false }] }], selectAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllLabel", required: false }] }], deselectAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "deselectAllLabel", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], summaryFormatter: [{ type: i0.Input, args: [{ isSignal: true, alias: "summaryFormatter", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], openedChange: [{ type: i0.Output, args: ["openedChange"] }], searchEl: [{
11765
11765
  type: ViewChild,
11766
11766
  args: ['searchRef']
@@ -11996,14 +11996,14 @@ class FlyTypeaheadComponent {
11996
11996
  });
11997
11997
  }
11998
11998
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyTypeaheadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11999
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyTypeaheadComponent, isStandalone: true, selector: "fly-typeahead", inputs: { searchFn: { classPropertyName: "searchFn", publicName: "searchFn", isSignal: true, isRequired: true, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, allowFreeText: { classPropertyName: "allowFreeText", publicName: "allowFreeText", isSignal: true, isRequired: false, transformFunction: null }, openOnFocus: { classPropertyName: "openOnFocus", publicName: "openOnFocus", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", selected: "selected", cleared: "cleared" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)" }, properties: { "class.fly-typeahead--open": "open()" }, classAttribute: "fly-typeahead" }, ngImport: i0, template: "<div class=\"fly-typeahead__control\">\r\n <i class=\"pi pi-search fly-typeahead__icon\" aria-hidden=\"true\"></i>\r\n <input\r\n #inputRef\r\n type=\"text\"\r\n class=\"fly-typeahead__input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-activedescendant]=\"open() ? activeDescendant() || null : null\"\r\n [attr.aria-label]=\"ariaLabel() || placeholder() || ('typeahead.search_label' | translate)\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onInput($event)\"\r\n (focus)=\"onFocus()\"\r\n (keydown)=\"onKeydown($event)\"\r\n [placeholder]=\"placeholder()\" />\r\n @if (query()) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-typeahead__clear\"\r\n (click)=\"clear()\"\r\n [attr.aria-label]=\"'typeahead.clear' | translate\">\r\n \u2715\r\n </button>\r\n }\r\n</div>\r\n\r\n@if (open()) {\r\n <ul [id]=\"listboxId\" class=\"fly-typeahead__menu\" role=\"listbox\">\r\n @if (loading()) {\r\n <li class=\"fly-typeahead__status\" role=\"status\">{{ 'typeahead.loading' | translate }}</li>\r\n } @else if (options().length === 0) {\r\n <li class=\"fly-typeahead__status\" role=\"status\">{{ 'typeahead.no_results' | translate }}</li>\r\n } @else {\r\n @for (o of options(); track o.value; let i = $index) {\r\n <li\r\n class=\"fly-typeahead__opt\"\r\n [class.is-active]=\"i === activeIndex()\"\r\n [id]=\"optionId(i)\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"i === activeIndex()\"\r\n [title]=\"o.label\"\r\n (mouseenter)=\"onOptionHover(i)\"\r\n (mousedown)=\"onOptionMousedown($event, o)\">\r\n {{ o.label }}\r\n </li>\r\n }\r\n }\r\n </ul>\r\n}\r\n", styles: [":host{display:block;position:relative}.fly-typeahead__control{display:flex;align-items:center;gap:8px;padding-block:6px;padding-inline:10px;border-radius:8px;background:var(--surface-hover, rgba(0, 0, 0, .04));border:1px solid var(--surface-border, rgba(0, 0, 0, .12))}.fly-typeahead__control:focus-within{border-color:var(--primary-color)}.fly-typeahead__icon{flex-shrink:0;color:var(--text-color-secondary, rgba(17, 24, 39, .55));font-size:13px}.fly-typeahead__input{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-size:13px;font-family:inherit}.fly-typeahead__input::placeholder{color:var(--text-color-secondary, rgba(17, 24, 39, .45))}.fly-typeahead__clear{flex-shrink:0;border:none;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:12px;line-height:1;padding:2px;border-radius:4px}.fly-typeahead__clear:hover,.fly-typeahead__clear:focus-visible{color:inherit;background:var(--surface-hover, rgba(0, 0, 0, .06));outline:none}.fly-typeahead__clear:focus-visible{outline:2px solid var(--primary-color);outline-offset:1px}.fly-typeahead__menu{position:absolute;inset-inline:0;inset-block-start:calc(100% + 4px);z-index:20;max-block-size:240px;overflow-y:auto;margin:0;padding:4px;list-style:none;border-radius:8px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-typeahead__menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-typeahead__menu:before,.fly-typeahead__menu:after{display:none}}@media(prefers-contrast:more){.fly-typeahead__menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-typeahead__menu:after{animation:none}}.fly-typeahead__status{padding-block:10px;padding-inline:12px;text-align:center;font-size:12px;color:var(--text-color-secondary, rgba(17, 24, 39, .55))}.fly-typeahead__opt{padding-block:7px;padding-inline:10px;border-radius:6px;font-size:13px;color:inherit;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:background .12s ease}.fly-typeahead__opt.is-active,.fly-typeahead__opt:hover{background:var(--w1)}@media(prefers-reduced-motion:reduce){.fly-typeahead__opt{transition:none}}@media(forced-colors:active){.fly-typeahead__menu{border-color:CanvasText}.fly-typeahead__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 });
11999
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyTypeaheadComponent, isStandalone: true, selector: "fly-typeahead", inputs: { searchFn: { classPropertyName: "searchFn", publicName: "searchFn", isSignal: true, isRequired: true, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, allowFreeText: { classPropertyName: "allowFreeText", publicName: "allowFreeText", isSignal: true, isRequired: false, transformFunction: null }, openOnFocus: { classPropertyName: "openOnFocus", publicName: "openOnFocus", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", selected: "selected", cleared: "cleared" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)" }, properties: { "class.fly-typeahead--open": "open()" }, classAttribute: "fly-typeahead" }, ngImport: i0, template: "<div class=\"fly-typeahead__control\">\r\n <i class=\"pi pi-search fly-typeahead__icon\" aria-hidden=\"true\"></i>\r\n <input\r\n #inputRef\r\n type=\"text\"\r\n class=\"fly-typeahead__input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-activedescendant]=\"open() ? activeDescendant() || null : null\"\r\n [attr.aria-label]=\"ariaLabel() || placeholder() || ('typeahead.search_label' | translate)\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onInput($event)\"\r\n (focus)=\"onFocus()\"\r\n (keydown)=\"onKeydown($event)\"\r\n [placeholder]=\"placeholder()\" />\r\n @if (query()) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-typeahead__clear\"\r\n (click)=\"clear()\"\r\n [attr.aria-label]=\"'typeahead.clear' | translate\">\r\n \u2715\r\n </button>\r\n }\r\n</div>\r\n\r\n@if (open()) {\r\n <ul [id]=\"listboxId\" class=\"fly-typeahead__menu\" role=\"listbox\">\r\n @if (loading()) {\r\n <li class=\"fly-typeahead__status\" role=\"status\">{{ 'typeahead.loading' | translate }}</li>\r\n } @else if (options().length === 0) {\r\n <li class=\"fly-typeahead__status\" role=\"status\">{{ 'typeahead.no_results' | translate }}</li>\r\n } @else {\r\n @for (o of options(); track o.value; let i = $index) {\r\n <li\r\n class=\"fly-typeahead__opt\"\r\n [class.is-active]=\"i === activeIndex()\"\r\n [id]=\"optionId(i)\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"i === activeIndex()\"\r\n [title]=\"o.label\"\r\n (mouseenter)=\"onOptionHover(i)\"\r\n (mousedown)=\"onOptionMousedown($event, o)\">\r\n {{ o.label }}\r\n </li>\r\n }\r\n }\r\n </ul>\r\n}\r\n", styles: [":host{display:block;position:relative}.fly-typeahead__control{display:flex;align-items:center;gap:8px;padding-block:6px;padding-inline:10px;border-radius:8px;background:var(--surface-hover, rgba(0, 0, 0, .04));border:1px solid var(--surface-border, rgba(0, 0, 0, .12))}.fly-typeahead__control:focus-within{border-color:var(--primary-color)}.fly-typeahead__icon{flex-shrink:0;color:var(--text-color-secondary, rgba(17, 24, 39, .55));font-size:13px}.fly-typeahead__input{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-size:13px;font-family:inherit}.fly-typeahead__input::placeholder{color:var(--text-color-secondary, rgba(17, 24, 39, .45))}.fly-typeahead__clear{flex-shrink:0;border:none;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:12px;line-height:1;padding:2px;border-radius:4px}.fly-typeahead__clear:hover,.fly-typeahead__clear:focus-visible{color:inherit;background:var(--surface-hover, rgba(0, 0, 0, .06));outline:none}.fly-typeahead__clear:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:1px}.fly-typeahead__menu{position:absolute;inset-inline:0;inset-block-start:calc(100% + 4px);z-index:20;max-block-size:240px;overflow-y:auto;margin:0;padding:4px;list-style:none;border-radius:8px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-typeahead__menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-typeahead__menu:before,.fly-typeahead__menu:after{display:none}}@media(prefers-contrast:more){.fly-typeahead__menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-typeahead__menu:after{animation:none}}.fly-typeahead__status{padding-block:10px;padding-inline:12px;text-align:center;font-size:12px;color:var(--text-color-secondary, rgba(17, 24, 39, .55))}.fly-typeahead__opt{padding-block:7px;padding-inline:10px;border-radius:6px;font-size:13px;color:inherit;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:background .12s ease}.fly-typeahead__opt.is-active,.fly-typeahead__opt:hover{background:var(--w1)}@media(prefers-reduced-motion:reduce){.fly-typeahead__opt{transition:none}}@media(forced-colors:active){.fly-typeahead__menu{border-color:CanvasText}.fly-typeahead__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 });
12000
12000
  }
12001
12001
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyTypeaheadComponent, decorators: [{
12002
12002
  type: Component,
12003
12003
  args: [{ selector: 'fly-typeahead', standalone: true, imports: [CommonModule, FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: {
12004
12004
  class: 'fly-typeahead',
12005
12005
  '[class.fly-typeahead--open]': 'open()',
12006
- }, template: "<div class=\"fly-typeahead__control\">\r\n <i class=\"pi pi-search fly-typeahead__icon\" aria-hidden=\"true\"></i>\r\n <input\r\n #inputRef\r\n type=\"text\"\r\n class=\"fly-typeahead__input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-activedescendant]=\"open() ? activeDescendant() || null : null\"\r\n [attr.aria-label]=\"ariaLabel() || placeholder() || ('typeahead.search_label' | translate)\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onInput($event)\"\r\n (focus)=\"onFocus()\"\r\n (keydown)=\"onKeydown($event)\"\r\n [placeholder]=\"placeholder()\" />\r\n @if (query()) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-typeahead__clear\"\r\n (click)=\"clear()\"\r\n [attr.aria-label]=\"'typeahead.clear' | translate\">\r\n \u2715\r\n </button>\r\n }\r\n</div>\r\n\r\n@if (open()) {\r\n <ul [id]=\"listboxId\" class=\"fly-typeahead__menu\" role=\"listbox\">\r\n @if (loading()) {\r\n <li class=\"fly-typeahead__status\" role=\"status\">{{ 'typeahead.loading' | translate }}</li>\r\n } @else if (options().length === 0) {\r\n <li class=\"fly-typeahead__status\" role=\"status\">{{ 'typeahead.no_results' | translate }}</li>\r\n } @else {\r\n @for (o of options(); track o.value; let i = $index) {\r\n <li\r\n class=\"fly-typeahead__opt\"\r\n [class.is-active]=\"i === activeIndex()\"\r\n [id]=\"optionId(i)\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"i === activeIndex()\"\r\n [title]=\"o.label\"\r\n (mouseenter)=\"onOptionHover(i)\"\r\n (mousedown)=\"onOptionMousedown($event, o)\">\r\n {{ o.label }}\r\n </li>\r\n }\r\n }\r\n </ul>\r\n}\r\n", styles: [":host{display:block;position:relative}.fly-typeahead__control{display:flex;align-items:center;gap:8px;padding-block:6px;padding-inline:10px;border-radius:8px;background:var(--surface-hover, rgba(0, 0, 0, .04));border:1px solid var(--surface-border, rgba(0, 0, 0, .12))}.fly-typeahead__control:focus-within{border-color:var(--primary-color)}.fly-typeahead__icon{flex-shrink:0;color:var(--text-color-secondary, rgba(17, 24, 39, .55));font-size:13px}.fly-typeahead__input{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-size:13px;font-family:inherit}.fly-typeahead__input::placeholder{color:var(--text-color-secondary, rgba(17, 24, 39, .45))}.fly-typeahead__clear{flex-shrink:0;border:none;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:12px;line-height:1;padding:2px;border-radius:4px}.fly-typeahead__clear:hover,.fly-typeahead__clear:focus-visible{color:inherit;background:var(--surface-hover, rgba(0, 0, 0, .06));outline:none}.fly-typeahead__clear:focus-visible{outline:2px solid var(--primary-color);outline-offset:1px}.fly-typeahead__menu{position:absolute;inset-inline:0;inset-block-start:calc(100% + 4px);z-index:20;max-block-size:240px;overflow-y:auto;margin:0;padding:4px;list-style:none;border-radius:8px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-typeahead__menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-typeahead__menu:before,.fly-typeahead__menu:after{display:none}}@media(prefers-contrast:more){.fly-typeahead__menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-typeahead__menu:after{animation:none}}.fly-typeahead__status{padding-block:10px;padding-inline:12px;text-align:center;font-size:12px;color:var(--text-color-secondary, rgba(17, 24, 39, .55))}.fly-typeahead__opt{padding-block:7px;padding-inline:10px;border-radius:6px;font-size:13px;color:inherit;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:background .12s ease}.fly-typeahead__opt.is-active,.fly-typeahead__opt:hover{background:var(--w1)}@media(prefers-reduced-motion:reduce){.fly-typeahead__opt{transition:none}}@media(forced-colors:active){.fly-typeahead__menu{border-color:CanvasText}.fly-typeahead__opt.is-active{outline:1px solid Highlight;outline-offset:-1px}}\n"] }]
12006
+ }, template: "<div class=\"fly-typeahead__control\">\r\n <i class=\"pi pi-search fly-typeahead__icon\" aria-hidden=\"true\"></i>\r\n <input\r\n #inputRef\r\n type=\"text\"\r\n class=\"fly-typeahead__input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-activedescendant]=\"open() ? activeDescendant() || null : null\"\r\n [attr.aria-label]=\"ariaLabel() || placeholder() || ('typeahead.search_label' | translate)\"\r\n [ngModel]=\"query()\"\r\n (ngModelChange)=\"onInput($event)\"\r\n (focus)=\"onFocus()\"\r\n (keydown)=\"onKeydown($event)\"\r\n [placeholder]=\"placeholder()\" />\r\n @if (query()) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-typeahead__clear\"\r\n (click)=\"clear()\"\r\n [attr.aria-label]=\"'typeahead.clear' | translate\">\r\n \u2715\r\n </button>\r\n }\r\n</div>\r\n\r\n@if (open()) {\r\n <ul [id]=\"listboxId\" class=\"fly-typeahead__menu\" role=\"listbox\">\r\n @if (loading()) {\r\n <li class=\"fly-typeahead__status\" role=\"status\">{{ 'typeahead.loading' | translate }}</li>\r\n } @else if (options().length === 0) {\r\n <li class=\"fly-typeahead__status\" role=\"status\">{{ 'typeahead.no_results' | translate }}</li>\r\n } @else {\r\n @for (o of options(); track o.value; let i = $index) {\r\n <li\r\n class=\"fly-typeahead__opt\"\r\n [class.is-active]=\"i === activeIndex()\"\r\n [id]=\"optionId(i)\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"i === activeIndex()\"\r\n [title]=\"o.label\"\r\n (mouseenter)=\"onOptionHover(i)\"\r\n (mousedown)=\"onOptionMousedown($event, o)\">\r\n {{ o.label }}\r\n </li>\r\n }\r\n }\r\n </ul>\r\n}\r\n", styles: [":host{display:block;position:relative}.fly-typeahead__control{display:flex;align-items:center;gap:8px;padding-block:6px;padding-inline:10px;border-radius:8px;background:var(--surface-hover, rgba(0, 0, 0, .04));border:1px solid var(--surface-border, rgba(0, 0, 0, .12))}.fly-typeahead__control:focus-within{border-color:var(--primary-color)}.fly-typeahead__icon{flex-shrink:0;color:var(--text-color-secondary, rgba(17, 24, 39, .55));font-size:13px}.fly-typeahead__input{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-size:13px;font-family:inherit}.fly-typeahead__input::placeholder{color:var(--text-color-secondary, rgba(17, 24, 39, .45))}.fly-typeahead__clear{flex-shrink:0;border:none;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:12px;line-height:1;padding:2px;border-radius:4px}.fly-typeahead__clear:hover,.fly-typeahead__clear:focus-visible{color:inherit;background:var(--surface-hover, rgba(0, 0, 0, .06));outline:none}.fly-typeahead__clear:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:1px}.fly-typeahead__menu{position:absolute;inset-inline:0;inset-block-start:calc(100% + 4px);z-index:20;max-block-size:240px;overflow-y:auto;margin:0;padding:4px;list-style:none;border-radius:8px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-typeahead__menu{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-typeahead__menu:before,.fly-typeahead__menu:after{display:none}}@media(prefers-contrast:more){.fly-typeahead__menu{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-typeahead__menu:after{animation:none}}.fly-typeahead__status{padding-block:10px;padding-inline:12px;text-align:center;font-size:12px;color:var(--text-color-secondary, rgba(17, 24, 39, .55))}.fly-typeahead__opt{padding-block:7px;padding-inline:10px;border-radius:6px;font-size:13px;color:inherit;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:background .12s ease}.fly-typeahead__opt.is-active,.fly-typeahead__opt:hover{background:var(--w1)}@media(prefers-reduced-motion:reduce){.fly-typeahead__opt{transition:none}}@media(forced-colors:active){.fly-typeahead__menu{border-color:CanvasText}.fly-typeahead__opt.is-active{outline:1px solid Highlight;outline-offset:-1px}}\n"] }]
12007
12007
  }], ctorParameters: () => [], propDecorators: { searchFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchFn", required: true }] }], debounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceMs", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], allowFreeText: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowFreeText", required: false }] }], openOnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "openOnFocus", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }], cleared: [{ type: i0.Output, args: ["cleared"] }], onDocumentMouseDown: [{
12008
12008
  type: HostListener,
12009
12009
  args: ['document:mousedown', ['$event']]
@@ -12659,7 +12659,7 @@ class FlyCronBuilderComponent {
12659
12659
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyCronBuilderComponent, isStandalone: true, selector: "fly-cron-builder", inputs: { seconds: { classPropertyName: "seconds", publicName: "seconds", isSignal: true, isRequired: false, transformFunction: null }, allowNone: { classPropertyName: "allowNone", publicName: "allowNone", isSignal: true, isRequired: false, transformFunction: null }, modes: { classPropertyName: "modes", publicName: "modes", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cronChange: "cronChange", validityChange: "validityChange" }, host: { properties: { "class.fly-cron-builder--disabled": "effectiveDisabled()" }, classAttribute: "fly-cron-builder" }, providers: [
12660
12660
  { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => FlyCronBuilderComponent), multi: true },
12661
12661
  { provide: NG_VALIDATORS, useExisting: forwardRef(() => FlyCronBuilderComponent), multi: true },
12662
- ], viewQueries: [{ propertyName: "modeSelectRef", first: true, predicate: ["modeSelect"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- \u2500\u2500 Frequency selector \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"modeSelectId\">{{ 'cron.frequency_label' | translate }}</label>\r\n <!-- Selection is synced imperatively by an effect() (see the component) \u2014 a [value] /\r\n [selected] binding is applied before the @for options exist on cold render and falls\r\n back to the first option. The #modeSelect ref is what the effect drives. -->\r\n <select\r\n #modeSelect\r\n class=\"fly-cron__select\"\r\n [id]=\"modeSelectId\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (change)=\"onModeChange($any($event.target).value)\"\r\n >\r\n @for (m of availableModes(); track m) {\r\n <option [value]=\"m\">{{ ('cron.mode.' + m) | translate }}</option>\r\n }\r\n </select>\r\n</div>\r\n\r\n<!-- \u2500\u2500 Mode-specific editor \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@switch (mode()) {\r\n @case ('minutes') {\r\n <div class=\"fly-cron__row\">\r\n <span class=\"fly-cron__label\">{{ 'cron.every_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"59\"\r\n [value]=\"everyN()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onEveryN($any($event.target).value)\"\r\n />\r\n <span class=\"fly-cron__suffix\">{{ 'cron.unit_minutes' | translate }}</span>\r\n </div>\r\n }\r\n\r\n @case ('hourly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.every_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"23\"\r\n [value]=\"everyN()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onEveryN($any($event.target).value)\"\r\n />\r\n <span class=\"fly-cron__suffix\">{{ 'cron.unit_hours' | translate }}</span>\r\n <span class=\"fly-cron__suffix\">{{ 'cron.at_minute_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"0\"\r\n max=\"59\"\r\n [value]=\"minute()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onMinute($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('daily') {\r\n <div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('weekly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.on_days_label' | translate }}</span>\r\n <div class=\"fly-cron__weekdays\" role=\"group\" [attr.aria-label]=\"'cron.on_days_label' | translate\">\r\n @for (d of weekdayOrder(); track d) {\r\n <button\r\n type=\"button\"\r\n role=\"checkbox\"\r\n class=\"fly-cron__chip\"\r\n [class.fly-cron__chip--on]=\"isWeekday(d)\"\r\n [attr.aria-checked]=\"isWeekday(d)\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleWeekday(d)\"\r\n >{{ ('cron.weekday_short.' + d) | translate }}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('monthly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.day_of_month_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"31\"\r\n [value]=\"dayOfMonth()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onDayOfMonth($any($event.target).value)\"\r\n />\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('advanced') {\r\n <div class=\"fly-cron__advanced\">\r\n @for (f of advancedFieldDefs(); track f.index) {\r\n <div class=\"fly-cron__field\">\r\n <label class=\"fly-cron__field-label\" [attr.for]=\"fieldInputId(f.index)\">{{ f.labelKey | translate }}</label>\r\n <input\r\n [id]=\"fieldInputId(f.index)\"\r\n class=\"fly-cron__field-input fly-cron__mono\"\r\n type=\"text\"\r\n inputmode=\"text\"\r\n autocomplete=\"off\"\r\n spellcheck=\"false\"\r\n placeholder=\"*\"\r\n [value]=\"fields()[f.index]\"\r\n [disabled]=\"effectiveDisabled()\"\r\n [attr.aria-invalid]=\"!fieldValid(f.index)\"\r\n [attr.aria-label]=\"f.labelKey | translate\"\r\n (input)=\"onFieldInput(f.index, $any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n <p class=\"fly-cron__hint\">{{ 'cron.advanced.hint' | translate }}</p>\r\n }\r\n}\r\n\r\n<!-- \u2500\u2500 Summary + resulting expression \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@if (mode() !== 'none') {\r\n <div class=\"fly-cron__summary\" [class.fly-cron__summary--error]=\"!valid()\" aria-live=\"polite\">\r\n <span class=\"fly-cron__summary-text\">{{ summary() }}</span>\r\n @if (expression(); as expr) {\r\n <code class=\"fly-cron__expr fly-cron__mono\">{{ expr }}</code>\r\n }\r\n </div>\r\n}\r\n\r\n@if (errorKey(); as ek) {\r\n <p class=\"fly-cron__error\" role=\"alert\">{{ ek | translate }}</p>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_surface-active: var(--surface-active, #eef2ff);--_surface-muted: var(--surface-section, #f8fafc);--_border: var(--surface-border, #e2e8f0);--_text: var(--text-color, #0f172a);--_text-subtle: var(--text-color-secondary, #64748b);--_primary: var(--primary-color);--_primary-contrast: var(--primary-color-text, #fff);--_danger: var(--red-500, #ef4444);--_radius: 8px;display:block;inline-size:100%;font-size:13px;color:var(--_text)}:host(.fly-cron-builder--disabled){opacity:.6}.fly-cron__row{display:flex;align-items:center;gap:8px;margin-block-end:10px}.fly-cron__row--wrap{flex-wrap:wrap}.fly-cron__label{flex:0 0 auto;color:var(--_text-subtle);font-weight:600}.fly-cron__suffix{flex:0 0 auto;color:var(--_text-subtle)}.fly-cron__select,.fly-cron__num,.fly-cron__time{block-size:2.25rem;padding-inline:10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-cron__select{flex:1 1 auto;min-inline-size:10rem;cursor:pointer}.fly-cron__num{inline-size:4.5rem;text-align:end}.fly-cron__time{inline-size:auto}.fly-cron__select:focus-visible,.fly-cron__num:focus-visible,.fly-cron__time:focus-visible,.fly-cron__field-input:focus-visible{outline:2px solid var(--_primary);outline-offset:1px}.fly-cron__select:disabled,.fly-cron__num:disabled,.fly-cron__time:disabled,.fly-cron__field-input:disabled{opacity:.55;cursor:not-allowed}.fly-cron__weekdays{display:flex;flex-wrap:wrap;gap:6px}.fly-cron__chip{min-inline-size:2.5rem;block-size:2rem;padding-inline:10px;border:1px solid var(--_border);border-radius:999px;background:var(--_surface);color:var(--_text);font:inherit;cursor:pointer;transition:background .12s ease,border-color .12s ease,color .12s ease}.fly-cron__chip:hover:not(:disabled){background:var(--_surface-hover)}.fly-cron__chip--on{background:var(--_primary);border-color:var(--_primary);color:var(--_primary-contrast);font-weight:600}.fly-cron__chip:focus-visible{outline:2px solid var(--_primary);outline-offset:2px}.fly-cron__chip:disabled{cursor:not-allowed}.fly-cron__advanced{display:flex;flex-wrap:wrap;gap:8px;margin-block-end:6px}.fly-cron__field{display:flex;flex-direction:column;gap:4px}.fly-cron__field-label{color:var(--_text-subtle);font-size:11px;font-weight:600}.fly-cron__field-input{inline-size:5rem;block-size:2.25rem;padding-inline:8px;border:1px solid var(--_border);border-radius:6px;background:var(--_surface);color:var(--_text);font:inherit;text-align:center}.fly-cron__field-input[aria-invalid=true]{border-color:var(--_danger)}.fly-cron__hint{margin:0 0 8px;color:var(--_text-subtle);font-size:11px}.fly-cron__summary{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px 10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-muted)}.fly-cron__summary--error{border-color:var(--_danger)}.fly-cron__summary-text{flex:1 1 auto}.fly-cron__expr{flex:0 0 auto;padding:2px 8px;border-radius:6px;background:var(--_surface);border:1px solid var(--_border);color:var(--_text-subtle);font-size:12px;direction:ltr;unicode-bidi:isolate}.fly-cron__mono{font-family:var(--font-family-mono, ui-monospace, \"SFMono-Regular\", \"Menlo\", \"Consolas\", monospace)}.fly-cron__error{margin:6px 0 0;color:var(--_danger);font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
12662
+ ], viewQueries: [{ propertyName: "modeSelectRef", first: true, predicate: ["modeSelect"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- \u2500\u2500 Frequency selector \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"modeSelectId\">{{ 'cron.frequency_label' | translate }}</label>\r\n <!-- Selection is synced imperatively by an effect() (see the component) \u2014 a [value] /\r\n [selected] binding is applied before the @for options exist on cold render and falls\r\n back to the first option. The #modeSelect ref is what the effect drives. -->\r\n <select\r\n #modeSelect\r\n class=\"fly-cron__select\"\r\n [id]=\"modeSelectId\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (change)=\"onModeChange($any($event.target).value)\"\r\n >\r\n @for (m of availableModes(); track m) {\r\n <option [value]=\"m\">{{ ('cron.mode.' + m) | translate }}</option>\r\n }\r\n </select>\r\n</div>\r\n\r\n<!-- \u2500\u2500 Mode-specific editor \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@switch (mode()) {\r\n @case ('minutes') {\r\n <div class=\"fly-cron__row\">\r\n <span class=\"fly-cron__label\">{{ 'cron.every_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"59\"\r\n [value]=\"everyN()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onEveryN($any($event.target).value)\"\r\n />\r\n <span class=\"fly-cron__suffix\">{{ 'cron.unit_minutes' | translate }}</span>\r\n </div>\r\n }\r\n\r\n @case ('hourly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.every_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"23\"\r\n [value]=\"everyN()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onEveryN($any($event.target).value)\"\r\n />\r\n <span class=\"fly-cron__suffix\">{{ 'cron.unit_hours' | translate }}</span>\r\n <span class=\"fly-cron__suffix\">{{ 'cron.at_minute_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"0\"\r\n max=\"59\"\r\n [value]=\"minute()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onMinute($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('daily') {\r\n <div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('weekly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.on_days_label' | translate }}</span>\r\n <div class=\"fly-cron__weekdays\" role=\"group\" [attr.aria-label]=\"'cron.on_days_label' | translate\">\r\n @for (d of weekdayOrder(); track d) {\r\n <button\r\n type=\"button\"\r\n role=\"checkbox\"\r\n class=\"fly-cron__chip\"\r\n [class.fly-cron__chip--on]=\"isWeekday(d)\"\r\n [attr.aria-checked]=\"isWeekday(d)\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleWeekday(d)\"\r\n >{{ ('cron.weekday_short.' + d) | translate }}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('monthly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.day_of_month_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"31\"\r\n [value]=\"dayOfMonth()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onDayOfMonth($any($event.target).value)\"\r\n />\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('advanced') {\r\n <div class=\"fly-cron__advanced\">\r\n @for (f of advancedFieldDefs(); track f.index) {\r\n <div class=\"fly-cron__field\">\r\n <label class=\"fly-cron__field-label\" [attr.for]=\"fieldInputId(f.index)\">{{ f.labelKey | translate }}</label>\r\n <input\r\n [id]=\"fieldInputId(f.index)\"\r\n class=\"fly-cron__field-input fly-cron__mono\"\r\n type=\"text\"\r\n inputmode=\"text\"\r\n autocomplete=\"off\"\r\n spellcheck=\"false\"\r\n placeholder=\"*\"\r\n [value]=\"fields()[f.index]\"\r\n [disabled]=\"effectiveDisabled()\"\r\n [attr.aria-invalid]=\"!fieldValid(f.index)\"\r\n [attr.aria-label]=\"f.labelKey | translate\"\r\n (input)=\"onFieldInput(f.index, $any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n <p class=\"fly-cron__hint\">{{ 'cron.advanced.hint' | translate }}</p>\r\n }\r\n}\r\n\r\n<!-- \u2500\u2500 Summary + resulting expression \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@if (mode() !== 'none') {\r\n <div class=\"fly-cron__summary\" [class.fly-cron__summary--error]=\"!valid()\" aria-live=\"polite\">\r\n <span class=\"fly-cron__summary-text\">{{ summary() }}</span>\r\n @if (expression(); as expr) {\r\n <code class=\"fly-cron__expr fly-cron__mono\">{{ expr }}</code>\r\n }\r\n </div>\r\n}\r\n\r\n@if (errorKey(); as ek) {\r\n <p class=\"fly-cron__error\" role=\"alert\">{{ ek | translate }}</p>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_surface-active: var(--surface-active, #eef2ff);--_surface-muted: var(--surface-section, #f8fafc);--_border: var(--surface-border, #e2e8f0);--_text: var(--text-color, #0f172a);--_text-subtle: var(--text-color-secondary, #64748b);--_primary: var(--primary-color);--_primary-contrast: var(--primary-color-text, #fff);--_danger: var(--red-500, #ef4444);--_radius: 8px;display:block;inline-size:100%;font-size:13px;color:var(--_text)}:host(.fly-cron-builder--disabled){opacity:.6}.fly-cron__row{display:flex;align-items:center;gap:8px;margin-block-end:10px}.fly-cron__row--wrap{flex-wrap:wrap}.fly-cron__label{flex:0 0 auto;color:var(--_text-subtle);font-weight:600}.fly-cron__suffix{flex:0 0 auto;color:var(--_text-subtle)}.fly-cron__select,.fly-cron__num,.fly-cron__time{block-size:2.25rem;padding-inline:10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-cron__select{flex:1 1 auto;min-inline-size:10rem;cursor:pointer}.fly-cron__num{inline-size:4.5rem;text-align:end}.fly-cron__time{inline-size:auto}.fly-cron__select:focus-visible,.fly-cron__num:focus-visible,.fly-cron__time:focus-visible,.fly-cron__field-input:focus-visible{outline:2px solid;outline-color:var(--_primary);outline-offset:1px}.fly-cron__select:disabled,.fly-cron__num:disabled,.fly-cron__time:disabled,.fly-cron__field-input:disabled{opacity:.55;cursor:not-allowed}.fly-cron__weekdays{display:flex;flex-wrap:wrap;gap:6px}.fly-cron__chip{min-inline-size:2.5rem;block-size:2rem;padding-inline:10px;border:1px solid var(--_border);border-radius:999px;background:var(--_surface);color:var(--_text);font:inherit;cursor:pointer;transition:background .12s ease,border-color .12s ease,color .12s ease}.fly-cron__chip:hover:not(:disabled){background:var(--_surface-hover)}.fly-cron__chip--on{background:var(--_primary);border-color:var(--_primary);color:var(--_primary-contrast);font-weight:600}.fly-cron__chip:focus-visible{outline:2px solid;outline-color:var(--_primary);outline-offset:2px}.fly-cron__chip:disabled{cursor:not-allowed}.fly-cron__advanced{display:flex;flex-wrap:wrap;gap:8px;margin-block-end:6px}.fly-cron__field{display:flex;flex-direction:column;gap:4px}.fly-cron__field-label{color:var(--_text-subtle);font-size:11px;font-weight:600}.fly-cron__field-input{inline-size:5rem;block-size:2.25rem;padding-inline:8px;border:1px solid var(--_border);border-radius:6px;background:var(--_surface);color:var(--_text);font:inherit;text-align:center}.fly-cron__field-input[aria-invalid=true]{border-color:var(--_danger)}.fly-cron__hint{margin:0 0 8px;color:var(--_text-subtle);font-size:11px}.fly-cron__summary{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px 10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-muted)}.fly-cron__summary--error{border-color:var(--_danger)}.fly-cron__summary-text{flex:1 1 auto}.fly-cron__expr{flex:0 0 auto;padding:2px 8px;border-radius:6px;background:var(--_surface);border:1px solid var(--_border);color:var(--_text-subtle);font-size:12px;direction:ltr;unicode-bidi:isolate}.fly-cron__mono{font-family:var(--font-family-mono, ui-monospace, \"SFMono-Regular\", \"Menlo\", \"Consolas\", monospace)}.fly-cron__error{margin:6px 0 0;color:var(--_danger);font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
12663
12663
  }
12664
12664
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyCronBuilderComponent, decorators: [{
12665
12665
  type: Component,
@@ -12669,7 +12669,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
12669
12669
  ], host: {
12670
12670
  class: 'fly-cron-builder',
12671
12671
  '[class.fly-cron-builder--disabled]': 'effectiveDisabled()',
12672
- }, template: "<!-- \u2500\u2500 Frequency selector \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"modeSelectId\">{{ 'cron.frequency_label' | translate }}</label>\r\n <!-- Selection is synced imperatively by an effect() (see the component) \u2014 a [value] /\r\n [selected] binding is applied before the @for options exist on cold render and falls\r\n back to the first option. The #modeSelect ref is what the effect drives. -->\r\n <select\r\n #modeSelect\r\n class=\"fly-cron__select\"\r\n [id]=\"modeSelectId\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (change)=\"onModeChange($any($event.target).value)\"\r\n >\r\n @for (m of availableModes(); track m) {\r\n <option [value]=\"m\">{{ ('cron.mode.' + m) | translate }}</option>\r\n }\r\n </select>\r\n</div>\r\n\r\n<!-- \u2500\u2500 Mode-specific editor \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@switch (mode()) {\r\n @case ('minutes') {\r\n <div class=\"fly-cron__row\">\r\n <span class=\"fly-cron__label\">{{ 'cron.every_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"59\"\r\n [value]=\"everyN()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onEveryN($any($event.target).value)\"\r\n />\r\n <span class=\"fly-cron__suffix\">{{ 'cron.unit_minutes' | translate }}</span>\r\n </div>\r\n }\r\n\r\n @case ('hourly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.every_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"23\"\r\n [value]=\"everyN()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onEveryN($any($event.target).value)\"\r\n />\r\n <span class=\"fly-cron__suffix\">{{ 'cron.unit_hours' | translate }}</span>\r\n <span class=\"fly-cron__suffix\">{{ 'cron.at_minute_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"0\"\r\n max=\"59\"\r\n [value]=\"minute()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onMinute($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('daily') {\r\n <div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('weekly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.on_days_label' | translate }}</span>\r\n <div class=\"fly-cron__weekdays\" role=\"group\" [attr.aria-label]=\"'cron.on_days_label' | translate\">\r\n @for (d of weekdayOrder(); track d) {\r\n <button\r\n type=\"button\"\r\n role=\"checkbox\"\r\n class=\"fly-cron__chip\"\r\n [class.fly-cron__chip--on]=\"isWeekday(d)\"\r\n [attr.aria-checked]=\"isWeekday(d)\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleWeekday(d)\"\r\n >{{ ('cron.weekday_short.' + d) | translate }}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('monthly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.day_of_month_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"31\"\r\n [value]=\"dayOfMonth()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onDayOfMonth($any($event.target).value)\"\r\n />\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('advanced') {\r\n <div class=\"fly-cron__advanced\">\r\n @for (f of advancedFieldDefs(); track f.index) {\r\n <div class=\"fly-cron__field\">\r\n <label class=\"fly-cron__field-label\" [attr.for]=\"fieldInputId(f.index)\">{{ f.labelKey | translate }}</label>\r\n <input\r\n [id]=\"fieldInputId(f.index)\"\r\n class=\"fly-cron__field-input fly-cron__mono\"\r\n type=\"text\"\r\n inputmode=\"text\"\r\n autocomplete=\"off\"\r\n spellcheck=\"false\"\r\n placeholder=\"*\"\r\n [value]=\"fields()[f.index]\"\r\n [disabled]=\"effectiveDisabled()\"\r\n [attr.aria-invalid]=\"!fieldValid(f.index)\"\r\n [attr.aria-label]=\"f.labelKey | translate\"\r\n (input)=\"onFieldInput(f.index, $any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n <p class=\"fly-cron__hint\">{{ 'cron.advanced.hint' | translate }}</p>\r\n }\r\n}\r\n\r\n<!-- \u2500\u2500 Summary + resulting expression \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@if (mode() !== 'none') {\r\n <div class=\"fly-cron__summary\" [class.fly-cron__summary--error]=\"!valid()\" aria-live=\"polite\">\r\n <span class=\"fly-cron__summary-text\">{{ summary() }}</span>\r\n @if (expression(); as expr) {\r\n <code class=\"fly-cron__expr fly-cron__mono\">{{ expr }}</code>\r\n }\r\n </div>\r\n}\r\n\r\n@if (errorKey(); as ek) {\r\n <p class=\"fly-cron__error\" role=\"alert\">{{ ek | translate }}</p>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_surface-active: var(--surface-active, #eef2ff);--_surface-muted: var(--surface-section, #f8fafc);--_border: var(--surface-border, #e2e8f0);--_text: var(--text-color, #0f172a);--_text-subtle: var(--text-color-secondary, #64748b);--_primary: var(--primary-color);--_primary-contrast: var(--primary-color-text, #fff);--_danger: var(--red-500, #ef4444);--_radius: 8px;display:block;inline-size:100%;font-size:13px;color:var(--_text)}:host(.fly-cron-builder--disabled){opacity:.6}.fly-cron__row{display:flex;align-items:center;gap:8px;margin-block-end:10px}.fly-cron__row--wrap{flex-wrap:wrap}.fly-cron__label{flex:0 0 auto;color:var(--_text-subtle);font-weight:600}.fly-cron__suffix{flex:0 0 auto;color:var(--_text-subtle)}.fly-cron__select,.fly-cron__num,.fly-cron__time{block-size:2.25rem;padding-inline:10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-cron__select{flex:1 1 auto;min-inline-size:10rem;cursor:pointer}.fly-cron__num{inline-size:4.5rem;text-align:end}.fly-cron__time{inline-size:auto}.fly-cron__select:focus-visible,.fly-cron__num:focus-visible,.fly-cron__time:focus-visible,.fly-cron__field-input:focus-visible{outline:2px solid var(--_primary);outline-offset:1px}.fly-cron__select:disabled,.fly-cron__num:disabled,.fly-cron__time:disabled,.fly-cron__field-input:disabled{opacity:.55;cursor:not-allowed}.fly-cron__weekdays{display:flex;flex-wrap:wrap;gap:6px}.fly-cron__chip{min-inline-size:2.5rem;block-size:2rem;padding-inline:10px;border:1px solid var(--_border);border-radius:999px;background:var(--_surface);color:var(--_text);font:inherit;cursor:pointer;transition:background .12s ease,border-color .12s ease,color .12s ease}.fly-cron__chip:hover:not(:disabled){background:var(--_surface-hover)}.fly-cron__chip--on{background:var(--_primary);border-color:var(--_primary);color:var(--_primary-contrast);font-weight:600}.fly-cron__chip:focus-visible{outline:2px solid var(--_primary);outline-offset:2px}.fly-cron__chip:disabled{cursor:not-allowed}.fly-cron__advanced{display:flex;flex-wrap:wrap;gap:8px;margin-block-end:6px}.fly-cron__field{display:flex;flex-direction:column;gap:4px}.fly-cron__field-label{color:var(--_text-subtle);font-size:11px;font-weight:600}.fly-cron__field-input{inline-size:5rem;block-size:2.25rem;padding-inline:8px;border:1px solid var(--_border);border-radius:6px;background:var(--_surface);color:var(--_text);font:inherit;text-align:center}.fly-cron__field-input[aria-invalid=true]{border-color:var(--_danger)}.fly-cron__hint{margin:0 0 8px;color:var(--_text-subtle);font-size:11px}.fly-cron__summary{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px 10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-muted)}.fly-cron__summary--error{border-color:var(--_danger)}.fly-cron__summary-text{flex:1 1 auto}.fly-cron__expr{flex:0 0 auto;padding:2px 8px;border-radius:6px;background:var(--_surface);border:1px solid var(--_border);color:var(--_text-subtle);font-size:12px;direction:ltr;unicode-bidi:isolate}.fly-cron__mono{font-family:var(--font-family-mono, ui-monospace, \"SFMono-Regular\", \"Menlo\", \"Consolas\", monospace)}.fly-cron__error{margin:6px 0 0;color:var(--_danger);font-size:12px}\n"] }]
12672
+ }, template: "<!-- \u2500\u2500 Frequency selector \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"modeSelectId\">{{ 'cron.frequency_label' | translate }}</label>\r\n <!-- Selection is synced imperatively by an effect() (see the component) \u2014 a [value] /\r\n [selected] binding is applied before the @for options exist on cold render and falls\r\n back to the first option. The #modeSelect ref is what the effect drives. -->\r\n <select\r\n #modeSelect\r\n class=\"fly-cron__select\"\r\n [id]=\"modeSelectId\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (change)=\"onModeChange($any($event.target).value)\"\r\n >\r\n @for (m of availableModes(); track m) {\r\n <option [value]=\"m\">{{ ('cron.mode.' + m) | translate }}</option>\r\n }\r\n </select>\r\n</div>\r\n\r\n<!-- \u2500\u2500 Mode-specific editor \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@switch (mode()) {\r\n @case ('minutes') {\r\n <div class=\"fly-cron__row\">\r\n <span class=\"fly-cron__label\">{{ 'cron.every_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"59\"\r\n [value]=\"everyN()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onEveryN($any($event.target).value)\"\r\n />\r\n <span class=\"fly-cron__suffix\">{{ 'cron.unit_minutes' | translate }}</span>\r\n </div>\r\n }\r\n\r\n @case ('hourly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.every_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"23\"\r\n [value]=\"everyN()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onEveryN($any($event.target).value)\"\r\n />\r\n <span class=\"fly-cron__suffix\">{{ 'cron.unit_hours' | translate }}</span>\r\n <span class=\"fly-cron__suffix\">{{ 'cron.at_minute_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"0\"\r\n max=\"59\"\r\n [value]=\"minute()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onMinute($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('daily') {\r\n <div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('weekly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.on_days_label' | translate }}</span>\r\n <div class=\"fly-cron__weekdays\" role=\"group\" [attr.aria-label]=\"'cron.on_days_label' | translate\">\r\n @for (d of weekdayOrder(); track d) {\r\n <button\r\n type=\"button\"\r\n role=\"checkbox\"\r\n class=\"fly-cron__chip\"\r\n [class.fly-cron__chip--on]=\"isWeekday(d)\"\r\n [attr.aria-checked]=\"isWeekday(d)\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleWeekday(d)\"\r\n >{{ ('cron.weekday_short.' + d) | translate }}</button>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"fly-cron__row\">\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('monthly') {\r\n <div class=\"fly-cron__row fly-cron__row--wrap\">\r\n <span class=\"fly-cron__label\">{{ 'cron.day_of_month_label' | translate }}</span>\r\n <input\r\n class=\"fly-cron__num\"\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"31\"\r\n [value]=\"dayOfMonth()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onDayOfMonth($any($event.target).value)\"\r\n />\r\n <label class=\"fly-cron__label\" [attr.for]=\"timeInputId\">{{ 'cron.time_label' | translate }}</label>\r\n <input\r\n class=\"fly-cron__time\"\r\n type=\"time\"\r\n [id]=\"timeInputId\"\r\n [value]=\"timeValue()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (input)=\"onTime($any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n\r\n @case ('advanced') {\r\n <div class=\"fly-cron__advanced\">\r\n @for (f of advancedFieldDefs(); track f.index) {\r\n <div class=\"fly-cron__field\">\r\n <label class=\"fly-cron__field-label\" [attr.for]=\"fieldInputId(f.index)\">{{ f.labelKey | translate }}</label>\r\n <input\r\n [id]=\"fieldInputId(f.index)\"\r\n class=\"fly-cron__field-input fly-cron__mono\"\r\n type=\"text\"\r\n inputmode=\"text\"\r\n autocomplete=\"off\"\r\n spellcheck=\"false\"\r\n placeholder=\"*\"\r\n [value]=\"fields()[f.index]\"\r\n [disabled]=\"effectiveDisabled()\"\r\n [attr.aria-invalid]=\"!fieldValid(f.index)\"\r\n [attr.aria-label]=\"f.labelKey | translate\"\r\n (input)=\"onFieldInput(f.index, $any($event.target).value)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n <p class=\"fly-cron__hint\">{{ 'cron.advanced.hint' | translate }}</p>\r\n }\r\n}\r\n\r\n<!-- \u2500\u2500 Summary + resulting expression \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n@if (mode() !== 'none') {\r\n <div class=\"fly-cron__summary\" [class.fly-cron__summary--error]=\"!valid()\" aria-live=\"polite\">\r\n <span class=\"fly-cron__summary-text\">{{ summary() }}</span>\r\n @if (expression(); as expr) {\r\n <code class=\"fly-cron__expr fly-cron__mono\">{{ expr }}</code>\r\n }\r\n </div>\r\n}\r\n\r\n@if (errorKey(); as ek) {\r\n <p class=\"fly-cron__error\" role=\"alert\">{{ ek | translate }}</p>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_surface-active: var(--surface-active, #eef2ff);--_surface-muted: var(--surface-section, #f8fafc);--_border: var(--surface-border, #e2e8f0);--_text: var(--text-color, #0f172a);--_text-subtle: var(--text-color-secondary, #64748b);--_primary: var(--primary-color);--_primary-contrast: var(--primary-color-text, #fff);--_danger: var(--red-500, #ef4444);--_radius: 8px;display:block;inline-size:100%;font-size:13px;color:var(--_text)}:host(.fly-cron-builder--disabled){opacity:.6}.fly-cron__row{display:flex;align-items:center;gap:8px;margin-block-end:10px}.fly-cron__row--wrap{flex-wrap:wrap}.fly-cron__label{flex:0 0 auto;color:var(--_text-subtle);font-weight:600}.fly-cron__suffix{flex:0 0 auto;color:var(--_text-subtle)}.fly-cron__select,.fly-cron__num,.fly-cron__time{block-size:2.25rem;padding-inline:10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-cron__select{flex:1 1 auto;min-inline-size:10rem;cursor:pointer}.fly-cron__num{inline-size:4.5rem;text-align:end}.fly-cron__time{inline-size:auto}.fly-cron__select:focus-visible,.fly-cron__num:focus-visible,.fly-cron__time:focus-visible,.fly-cron__field-input:focus-visible{outline:2px solid;outline-color:var(--_primary);outline-offset:1px}.fly-cron__select:disabled,.fly-cron__num:disabled,.fly-cron__time:disabled,.fly-cron__field-input:disabled{opacity:.55;cursor:not-allowed}.fly-cron__weekdays{display:flex;flex-wrap:wrap;gap:6px}.fly-cron__chip{min-inline-size:2.5rem;block-size:2rem;padding-inline:10px;border:1px solid var(--_border);border-radius:999px;background:var(--_surface);color:var(--_text);font:inherit;cursor:pointer;transition:background .12s ease,border-color .12s ease,color .12s ease}.fly-cron__chip:hover:not(:disabled){background:var(--_surface-hover)}.fly-cron__chip--on{background:var(--_primary);border-color:var(--_primary);color:var(--_primary-contrast);font-weight:600}.fly-cron__chip:focus-visible{outline:2px solid;outline-color:var(--_primary);outline-offset:2px}.fly-cron__chip:disabled{cursor:not-allowed}.fly-cron__advanced{display:flex;flex-wrap:wrap;gap:8px;margin-block-end:6px}.fly-cron__field{display:flex;flex-direction:column;gap:4px}.fly-cron__field-label{color:var(--_text-subtle);font-size:11px;font-weight:600}.fly-cron__field-input{inline-size:5rem;block-size:2.25rem;padding-inline:8px;border:1px solid var(--_border);border-radius:6px;background:var(--_surface);color:var(--_text);font:inherit;text-align:center}.fly-cron__field-input[aria-invalid=true]{border-color:var(--_danger)}.fly-cron__hint{margin:0 0 8px;color:var(--_text-subtle);font-size:11px}.fly-cron__summary{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px 10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-muted)}.fly-cron__summary--error{border-color:var(--_danger)}.fly-cron__summary-text{flex:1 1 auto}.fly-cron__expr{flex:0 0 auto;padding:2px 8px;border-radius:6px;background:var(--_surface);border:1px solid var(--_border);color:var(--_text-subtle);font-size:12px;direction:ltr;unicode-bidi:isolate}.fly-cron__mono{font-family:var(--font-family-mono, ui-monospace, \"SFMono-Regular\", \"Menlo\", \"Consolas\", monospace)}.fly-cron__error{margin:6px 0 0;color:var(--_danger);font-size:12px}\n"] }]
12673
12673
  }], propDecorators: { seconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "seconds", required: false }] }], allowNone: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowNone", required: false }] }], modes: [{ type: i0.Input, args: [{ isSignal: true, alias: "modes", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], cronChange: [{ type: i0.Output, args: ["cronChange"] }], validityChange: [{ type: i0.Output, args: ["validityChange"] }], modeSelectRef: [{ type: i0.ViewChild, args: ['modeSelect', { isSignal: true }] }] } });
12674
12674
 
12675
12675
  /**
@@ -13885,7 +13885,7 @@ class FlyGanttComponent {
13885
13885
  : t('gantt.aria.bar', { label: row.label, start: toIsoDate(start), end: toIsoDate(end), progress });
13886
13886
  }
13887
13887
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyGanttComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13888
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyGanttComponent, isStandalone: true, selector: "fly-gantt", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, dependencies: { classPropertyName: "dependencies", publicName: "dependencies", isSignal: true, isRequired: false, transformFunction: null }, zoom: { classPropertyName: "zoom", publicName: "zoom", isSignal: true, isRequired: false, transformFunction: null }, showToday: { classPropertyName: "showToday", publicName: "showToday", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, labelWidth: { classPropertyName: "labelWidth", publicName: "labelWidth", isSignal: true, isRequired: false, transformFunction: null }, resizableLabels: { classPropertyName: "resizableLabels", publicName: "resizableLabels", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowDatesChange: "rowDatesChange", dependencyCreate: "dependencyCreate", dependencyDelete: "dependencyDelete", rowClick: "rowClick", rowDblClick: "rowDblClick", labelWidthChange: "labelWidthChange" }, host: { properties: { "class.fly-gantt--rtl": "rtl()", "class.fly-gantt--readonly": "readonly()", "class.fly-gantt--resizing": "resizingLabels()", "attr.dir": "i18n.direction()" }, classAttribute: "fly-gantt" }, viewQueries: [{ propertyName: "bodyRef", first: true, predicate: ["bodySvg"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Cross-scrolling canvas: a CSS grid whose header row and label column are sticky, so the\r\n time grid scrolls under a pinned header + label tree. All SVG geometry is pre-mirrored for\r\n RTL in the component (see gantt-scale mapX), so this template never branches on direction. -->\r\n<div\r\n class=\"fly-gantt__scroll\"\r\n role=\"grid\"\r\n tabindex=\"0\"\r\n [attr.aria-label]=\"'gantt.aria.grid' | translate\"\r\n [attr.aria-rowcount]=\"visibleRows().length\"\r\n (keydown)=\"onGridKeydown($event)\"\r\n>\r\n <div\r\n class=\"fly-gantt__canvas\"\r\n [style.grid-template-columns]=\"effectiveLabelWidth() + 'px ' + innerWidth() + 'px'\"\r\n [style.grid-template-rows]=\"HEADER_H + 'px ' + bodyHeight() + 'px'\"\r\n >\r\n <!-- \u2500\u2500 Corner (pinned both axes) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"fly-gantt__corner\" [style.height.px]=\"HEADER_H\">\r\n @if (resizableLabels()) {\r\n <!-- The divider lives in the corner because the corner is the one cell pinned on BOTH\r\n axes: the grip stays reachable however far the user has scrolled. The full-height\r\n strip down the label pane below is the same gesture, presentational only. -->\r\n <div\r\n class=\"fly-gantt__splitter\"\r\n role=\"separator\"\r\n tabindex=\"0\"\r\n aria-orientation=\"vertical\"\r\n [attr.aria-label]=\"'gantt.aria.label_resize' | translate\"\r\n [attr.aria-valuenow]=\"effectiveLabelWidth()\"\r\n [attr.aria-valuemin]=\"MIN_LABEL_W\"\r\n [attr.aria-valuemax]=\"MAX_LABEL_W\"\r\n (pointerdown)=\"onLabelResizePointerDown($event)\"\r\n (keydown)=\"onLabelResizeKeydown($event)\"\r\n (dblclick)=\"resetLabelWidth()\"\r\n ></div>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 Time header (pinned top) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <svg\r\n class=\"fly-gantt__time-header\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"HEADER_H\"\r\n [attr.viewBox]=\"'0 0 ' + innerWidth() + ' ' + HEADER_H\"\r\n aria-hidden=\"true\"\r\n >\r\n @for (b of weekendBands(); track b.key) {\r\n <rect class=\"fly-gantt__weekend\" [attr.x]=\"b.x\" [attr.y]=\"HEADER_UPPER_H\" [attr.width]=\"b.width\" [attr.height]=\"HEADER_LOWER_H\" />\r\n }\r\n @for (t of upperTicks(); track t.key) {\r\n <line class=\"fly-gantt__tick-line\" [attr.x1]=\"t.x\" [attr.y1]=\"0\" [attr.x2]=\"t.x\" [attr.y2]=\"HEADER_H\" />\r\n <text class=\"fly-gantt__tick-label fly-gantt__tick-label--upper\" [attr.x]=\"t.x + t.width / 2\" [attr.y]=\"HEADER_UPPER_H / 2 + 4\">{{ t.label }}</text>\r\n }\r\n @for (t of lowerTicks(); track t.key) {\r\n <line class=\"fly-gantt__tick-line\" [attr.x1]=\"t.x\" [attr.y1]=\"HEADER_UPPER_H\" [attr.x2]=\"t.x\" [attr.y2]=\"HEADER_H\" />\r\n <text class=\"fly-gantt__tick-label\" [attr.x]=\"t.x + t.width / 2\" [attr.y]=\"HEADER_UPPER_H + HEADER_LOWER_H / 2 + 4\">{{ t.label }}</text>\r\n }\r\n @if (todayX() !== null) {\r\n <line class=\"fly-gantt__today\" [attr.x1]=\"todayX()\" [attr.y1]=\"HEADER_UPPER_H\" [attr.x2]=\"todayX()\" [attr.y2]=\"HEADER_H\" />\r\n }\r\n </svg>\r\n\r\n <!-- \u2500\u2500 Label tree (pinned inline-start) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"fly-gantt__labels\" role=\"rowgroup\">\r\n @for (vm of rowVms(); track vm.flat.row.id) {\r\n <div\r\n class=\"fly-gantt__label-row\"\r\n role=\"row\"\r\n tabindex=\"-1\"\r\n [class.fly-gantt__label-row--selected]=\"selectedId() === vm.flat.row.id\"\r\n [class.fly-gantt__label-row--tinted]=\"vm.tint !== null\"\r\n [style.height.px]=\"rowHeight()\"\r\n [style.--fly-gantt-row-tint]=\"vm.tint\"\r\n [attr.aria-selected]=\"selectedId() === vm.flat.row.id\"\r\n [attr.aria-label]=\"vm.ariaLabel\"\r\n (click)=\"onRowClick(vm.flat.row.id)\"\r\n (dblclick)=\"onRowDblClick(vm.flat.row.id)\"\r\n (keydown.enter)=\"onLabelRowKeydown($event, vm.flat.row.id)\"\r\n >\r\n <span class=\"fly-gantt__label-inner\" [style.padding-inline-start.px]=\"indentFor(vm.flat.depth)\">\r\n @if (vm.flat.hasChildren) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-gantt__chevron\"\r\n [class.fly-gantt__chevron--collapsed]=\"isCollapsed(vm.flat.row.id)\"\r\n [attr.aria-label]=\"(isCollapsed(vm.flat.row.id) ? 'gantt.expand' : 'gantt.collapse') | translate\"\r\n [attr.aria-expanded]=\"!isCollapsed(vm.flat.row.id)\"\r\n (click)=\"toggleCollapse(vm.flat.row.id, $event)\"\r\n >\u25B8</button>\r\n } @else {\r\n <span class=\"fly-gantt__chevron-spacer\"></span>\r\n }\r\n @if (vm.color) {\r\n <!-- Colour chip: the row's own colour at full strength, so a milestone stays\r\n identifiable in the label pane where the band tint is deliberately faint. -->\r\n <span class=\"fly-gantt__label-swatch\" [style.background]=\"vm.color\" aria-hidden=\"true\"></span>\r\n }\r\n <span\r\n class=\"fly-gantt__label-text\"\r\n [class.fly-gantt__label-text--group]=\"vm.shape === 'group'\"\r\n [title]=\"vm.flat.row.label\"\r\n >{{ vm.flat.row.label }}</span>\r\n </span>\r\n </div>\r\n }\r\n @if (resizableLabels()) {\r\n <!-- aria-hidden so this presentational twin of the corner separator is not a second\r\n (and structurally invalid) child of the rowgroup in the accessibility tree. -->\r\n <div\r\n class=\"fly-gantt__splitter fly-gantt__splitter--rail\"\r\n aria-hidden=\"true\"\r\n (pointerdown)=\"onLabelResizePointerDown($event)\"\r\n (dblclick)=\"resetLabelWidth()\"\r\n ></div>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 Time grid body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <svg\r\n #bodySvg\r\n class=\"fly-gantt__body\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"bodyHeight()\"\r\n [attr.viewBox]=\"'0 0 ' + innerWidth() + ' ' + bodyHeight()\"\r\n >\r\n <defs>\r\n <marker\r\n [attr.id]=\"markerId\"\r\n markerWidth=\"8\"\r\n markerHeight=\"8\"\r\n refX=\"6\"\r\n refY=\"4\"\r\n orient=\"auto\"\r\n markerUnits=\"userSpaceOnUse\"\r\n >\r\n <path class=\"fly-gantt__arrowhead\" d=\"M0,0 L7,4 L0,8 Z\" />\r\n </marker>\r\n </defs>\r\n\r\n <!-- Row colour bands sit at the very bottom of the stack, so the weekend shading and the\r\n gridlines below still read through them. -->\r\n @for (vm of tintedRows(); track vm.flat.row.id) {\r\n <rect\r\n class=\"fly-gantt__row-band\"\r\n [attr.x]=\"0\"\r\n [attr.y]=\"vm.y\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"rowHeight()\"\r\n [style.fill]=\"vm.tint\"\r\n />\r\n }\r\n\r\n <!-- Weekend shading + vertical gridlines (behind the bars). -->\r\n @for (b of weekendBands(); track b.key) {\r\n <rect class=\"fly-gantt__weekend\" [attr.x]=\"b.x\" [attr.y]=\"0\" [attr.width]=\"b.width\" [attr.height]=\"bodyHeight()\" />\r\n }\r\n @for (t of lowerTicks(); track t.key) {\r\n <line class=\"fly-gantt__grid-line\" [attr.x1]=\"t.x\" [attr.y1]=\"0\" [attr.x2]=\"t.x\" [attr.y2]=\"bodyHeight()\" />\r\n }\r\n\r\n <!-- Rows: a full-width hit rect (click + link drop target) then the shape. -->\r\n @for (vm of rowVms(); track vm.flat.row.id) {\r\n <g class=\"fly-gantt__row\" [attr.data-row-id]=\"vm.flat.row.id\">\r\n <rect\r\n class=\"fly-gantt__row-hit\"\r\n [class.fly-gantt__row-hit--selected]=\"selectedId() === vm.flat.row.id\"\r\n [attr.x]=\"0\"\r\n [attr.y]=\"vm.y\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"rowHeight()\"\r\n (pointerdown)=\"onRowClick(vm.flat.row.id)\"\r\n (dblclick)=\"onRowDblClick(vm.flat.row.id)\"\r\n />\r\n\r\n @switch (vm.shape) {\r\n @case ('group') {\r\n <path class=\"fly-gantt__group\" [attr.d]=\"groupPath(vm)\" [style.fill]=\"vm.color\" [style.stroke]=\"vm.color\" />\r\n }\r\n @case ('milestone') {\r\n <polygon\r\n class=\"fly-gantt__milestone\"\r\n [class.fly-gantt__milestone--editable]=\"vm.editable\"\r\n [attr.points]=\"diamondPoints(vm)\"\r\n [style.fill]=\"vm.color\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'move')\"\r\n />\r\n @if (!readonly() && !vm.flat.row.readonly) {\r\n <!-- A diamond has no width, so one connector serves it; it reads as the finish\r\n end, which is what makes a milestone\u2192task drag the FS everyone expects. -->\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"milestoneConnectorX(vm)\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'finish')\"\r\n />\r\n }\r\n }\r\n @case ('bar') {\r\n <g class=\"fly-gantt__bar-group\">\r\n <rect\r\n class=\"fly-gantt__bar\"\r\n [class.fly-gantt__bar--editable]=\"vm.editable\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"vm.width\"\r\n [attr.height]=\"barHeight()\"\r\n rx=\"4\"\r\n [style.fill]=\"vm.color\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'move')\"\r\n />\r\n @if (vm.progressWidth > 0) {\r\n <rect\r\n class=\"fly-gantt__progress\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"vm.progressWidth\"\r\n [attr.height]=\"barHeight()\"\r\n rx=\"4\"\r\n />\r\n }\r\n @if (vm.editable) {\r\n <!-- Resize handles at both edges. -->\r\n <rect\r\n class=\"fly-gantt__handle\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"HANDLE_W\"\r\n [attr.height]=\"barHeight()\"\r\n [attr.aria-label]=\"'gantt.aria.resize_start' | translate\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'resize-start')\"\r\n />\r\n <rect\r\n class=\"fly-gantt__handle\"\r\n [attr.x]=\"vm.x + vm.width - HANDLE_W\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"HANDLE_W\"\r\n [attr.height]=\"barHeight()\"\r\n [attr.aria-label]=\"'gantt.aria.resize_end' | translate\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'resize-end')\"\r\n />\r\n }\r\n @if (!readonly() && !vm.flat.row.readonly) {\r\n <!-- One connector per END. Dragging from the start edge yields an SS/SF link\r\n and from the finish edge an FS/FF one \u2014 the drop edge picks which. -->\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"vm.startX\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle_start' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'start')\"\r\n />\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"vm.endX\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'finish')\"\r\n />\r\n }\r\n </g>\r\n }\r\n }\r\n </g>\r\n }\r\n\r\n <!-- Dependency arrows (skipped for missing / collapsed endpoints). Each carries a fat\r\n transparent twin so a 1.5px line is still clickable at pointer precision. -->\r\n @for (link of linkVms(); track link.key) {\r\n <g class=\"fly-gantt__link-group\" [class.fly-gantt__link-group--selected]=\"selectedLinkKey() === link.key\">\r\n <path\r\n class=\"fly-gantt__link-hit\"\r\n [attr.d]=\"link.path\"\r\n [attr.aria-label]=\"link.ariaLabel\"\r\n (click)=\"onLinkClick($event, link)\"\r\n />\r\n <path class=\"fly-gantt__link\" [attr.d]=\"link.path\" [attr.marker-end]=\"'url(#' + markerId + ')'\" />\r\n @if (selectedLinkKey() === link.key && !readonly()) {\r\n <g\r\n class=\"fly-gantt__link-delete\"\r\n [attr.transform]=\"'translate(' + link.badgeX + ',' + link.badgeY + ')'\"\r\n [attr.aria-label]=\"'gantt.aria.delete_link' | translate\"\r\n (click)=\"deleteLink($event, link)\"\r\n >\r\n <circle class=\"fly-gantt__link-delete-bg\" r=\"8\" />\r\n <path class=\"fly-gantt__link-delete-x\" d=\"M-3.5,-3.5 L3.5,3.5 M3.5,-3.5 L-3.5,3.5\" />\r\n </g>\r\n }\r\n </g>\r\n }\r\n\r\n <!-- In-flight link rubber band. -->\r\n @if (linkGesturePath(); as gp) {\r\n <path class=\"fly-gantt__link fly-gantt__link--ghost\" [attr.d]=\"gp\" [attr.marker-end]=\"'url(#' + markerId + ')'\" />\r\n }\r\n\r\n <!-- Today line (over the bars). -->\r\n @if (todayX() !== null) {\r\n <line class=\"fly-gantt__today\" [attr.x1]=\"todayX()\" [attr.y1]=\"0\" [attr.x2]=\"todayX()\" [attr.y2]=\"bodyHeight()\" />\r\n }\r\n </svg>\r\n </div>\r\n\r\n @if (visibleRows().length === 0) {\r\n <p class=\"fly-gantt__empty\">{{ 'gantt.no_data' | translate }}</p>\r\n }\r\n @if (overflowCount() > 0) {\r\n <p class=\"fly-gantt__overflow\">\r\n {{ 'gantt.overflow' | translate: { shown: maxRows(), total: maxRows() + overflowCount() } }}\r\n </p>\r\n }\r\n</div>\r\n\r\n<!-- Drag candidate tooltip (HTML overlay, follows the cursor). -->\r\n@if (dragTooltip(); as tip) {\r\n <div class=\"fly-gantt__tooltip\" [style.left.px]=\"tip.x\" [style.top.px]=\"tip.y\">{{ tip.text }}</div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--bg-2, var(--surface-card, #fff));--_surface-alt: var(--bg-3, var(--glass-bg-elevated, #f8fafc));--_surface-hover: var(--bg-hover, var(--surface-hover, #f1f5f9));--_border: var(--w08, var(--surface-border, #e2e8f0));--_border-strong: var(--w1, var(--surface-border, #cbd5e1));--_grid-line: var(--line-3, var(--surface-border, #eef2f7));--_text: var(--ink, var(--text-color, #0f172a));--_text-subtle: var(--ink-3, var(--text-color-secondary, #64748b));--_text-faint: var(--ink-4, var(--text-color-secondary, #94a3b8));--_accent: var(--accent);--_bar: var(--_accent);--_bar-progress: color-mix(in srgb, var(--_accent) 72%, #000);--_weekend: color-mix(in srgb, var(--_text-subtle) 9%, transparent);--_today: var(--danger, #ef4444);--_link: var(--_text-subtle);--_radius: var(--r-lg, 8px);--_transition: var(--t-state, .12s ease);display:block;inline-size:100%;block-size:100%;min-block-size:200px;color:var(--_text);font-size:13px}:host(.fly-gantt--resizing){cursor:col-resize;-webkit-user-select:none;user-select:none}.fly-gantt__scroll{position:relative;inline-size:100%;block-size:100%;overflow:auto;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);box-shadow:var(--shadow-card, none);outline:none}.fly-gantt__scroll:focus-visible{outline:2px solid var(--_accent);outline-offset:-2px}.fly-gantt__canvas{display:grid;position:relative}.fly-gantt__corner{position:sticky;inset-block-start:0;inset-inline-start:0;z-index:4;background:var(--_surface-alt);-webkit-backdrop-filter:blur(12px) saturate(140%);backdrop-filter:blur(12px) saturate(140%);border-inline-end:1px solid var(--_border);border-block-end:1px solid var(--_border-strong)}.fly-gantt__time-header{position:sticky;inset-block-start:0;z-index:3;display:block;background:var(--_surface-alt);-webkit-backdrop-filter:blur(12px) saturate(140%);backdrop-filter:blur(12px) saturate(140%);border-block-end:1px solid var(--_border-strong)}.fly-gantt__tick-line{stroke:var(--_grid-line);stroke-width:1}.fly-gantt__tick-label{fill:var(--_text-subtle);font-size:11px;text-anchor:middle;dominant-baseline:middle}.fly-gantt__tick-label--upper{fill:var(--_text);font-weight:600}.fly-gantt__splitter{position:absolute;inset-block:0;inset-inline-end:-3px;inline-size:7px;z-index:5;cursor:col-resize;touch-action:none}.fly-gantt__splitter:after{content:\"\";position:absolute;inset-block:0;inset-inline-start:3px;inline-size:1px;background:transparent;transition:background var(--_transition)}.fly-gantt__splitter:hover:after,.fly-gantt__splitter:focus-visible:after{background:var(--_accent)}.fly-gantt__splitter:focus-visible{outline:2px solid var(--_accent);outline-offset:-1px}:host(.fly-gantt--resizing) .fly-gantt__splitter:after{background:var(--_accent)}.fly-gantt__labels{position:sticky;inset-inline-start:0;z-index:2;background:var(--_surface);border-inline-end:1px solid var(--_border)}.fly-gantt__label-row{position:relative;display:flex;align-items:center;border-block-end:1px solid var(--_grid-line);cursor:pointer;transition:background var(--_transition)}.fly-gantt__label-row:hover{background:var(--_surface-hover)}.fly-gantt__label-row--selected{background:var(--_surface-hover);box-shadow:inset 3px 0 0 0 var(--_accent)}.fly-gantt__label-row--tinted:before{content:\"\";position:absolute;inset:0;background:var(--fly-gantt-row-tint);pointer-events:none}.fly-gantt__label-inner{position:relative;display:flex;align-items:center;gap:4px;inline-size:100%;min-inline-size:0;padding-inline-end:8px}.fly-gantt__label-swatch{flex:0 0 auto;inline-size:8px;block-size:8px;border-radius:2px}.fly-gantt__chevron{flex:0 0 auto;inline-size:18px;block-size:18px;padding:0;border:none;background:transparent;color:var(--_text-subtle);cursor:pointer;line-height:1;transform:rotate(90deg);transition:transform var(--_transition)}.fly-gantt__chevron--collapsed{transform:rotate(0)}:host(.fly-gantt--rtl) .fly-gantt__chevron--collapsed{transform:rotate(180deg)}.fly-gantt__chevron:focus-visible{outline:2px solid var(--_accent);outline-offset:1px;border-radius:4px}.fly-gantt__chevron-spacer{flex:0 0 auto;inline-size:18px}.fly-gantt__label-text{min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-gantt__label-text--group{font-weight:600}.fly-gantt__body{display:block;touch-action:pan-x pan-y}.fly-gantt__row-band{pointer-events:none}.fly-gantt__weekend{fill:var(--_weekend)}.fly-gantt__grid-line{stroke:var(--_grid-line);stroke-width:1}.fly-gantt__row-hit{fill:transparent}.fly-gantt__row-hit--selected{fill:var(--_surface-hover)}.fly-gantt__bar{fill:var(--_bar);stroke:none}.fly-gantt__bar--editable{cursor:grab}.fly-gantt__progress{fill:var(--_bar-progress);pointer-events:none}.fly-gantt__handle{fill:transparent;cursor:ew-resize}.fly-gantt__connector{fill:var(--_surface);stroke:var(--_accent);stroke-width:1.5;cursor:crosshair;opacity:0;transition:opacity var(--_transition)}.fly-gantt__row:hover .fly-gantt__connector{opacity:1}.fly-gantt__milestone{fill:var(--_accent);stroke:var(--_surface);stroke-width:1}.fly-gantt__milestone--editable{cursor:grab}.fly-gantt__group{fill:var(--_text-subtle);stroke:var(--_text-subtle)}.fly-gantt__link{fill:none;stroke:var(--_link);stroke-width:1.5;pointer-events:none}.fly-gantt__link-hit{fill:none;stroke:transparent;stroke-width:11;pointer-events:stroke;cursor:pointer}.fly-gantt__link-group:hover .fly-gantt__link{stroke:var(--_text)}.fly-gantt__link-group--selected .fly-gantt__link{stroke:var(--_accent);stroke-width:2.5}.fly-gantt__link-delete-bg{fill:var(--_accent)}.fly-gantt__link-delete{cursor:pointer}.fly-gantt__link-delete-x{stroke:var(--_surface);stroke-width:1.75;stroke-linecap:round;fill:none;pointer-events:none}.fly-gantt__link--ghost{stroke-dasharray:4 3;opacity:.8}.fly-gantt__arrowhead{fill:var(--_link)}.fly-gantt__today{stroke:var(--_today);stroke-width:1.5;stroke-dasharray:3 3;pointer-events:none}.fly-gantt__empty,.fly-gantt__overflow{margin:0;padding:12px;color:var(--_text-faint);font-size:12px;text-align:center}.fly-gantt__tooltip{position:fixed;z-index:20;transform:translate(12px,16px);padding:4px 8px;border-radius:6px;background:var(--_text);color:var(--_surface);font-size:12px;white-space:nowrap;pointer-events:none;direction:ltr;unicode-bidi:isolate}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13888
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyGanttComponent, isStandalone: true, selector: "fly-gantt", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, dependencies: { classPropertyName: "dependencies", publicName: "dependencies", isSignal: true, isRequired: false, transformFunction: null }, zoom: { classPropertyName: "zoom", publicName: "zoom", isSignal: true, isRequired: false, transformFunction: null }, showToday: { classPropertyName: "showToday", publicName: "showToday", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, labelWidth: { classPropertyName: "labelWidth", publicName: "labelWidth", isSignal: true, isRequired: false, transformFunction: null }, resizableLabels: { classPropertyName: "resizableLabels", publicName: "resizableLabels", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowDatesChange: "rowDatesChange", dependencyCreate: "dependencyCreate", dependencyDelete: "dependencyDelete", rowClick: "rowClick", rowDblClick: "rowDblClick", labelWidthChange: "labelWidthChange" }, host: { properties: { "class.fly-gantt--rtl": "rtl()", "class.fly-gantt--readonly": "readonly()", "class.fly-gantt--resizing": "resizingLabels()", "attr.dir": "i18n.direction()" }, classAttribute: "fly-gantt" }, viewQueries: [{ propertyName: "bodyRef", first: true, predicate: ["bodySvg"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Cross-scrolling canvas: a CSS grid whose header row and label column are sticky, so the\r\n time grid scrolls under a pinned header + label tree. All SVG geometry is pre-mirrored for\r\n RTL in the component (see gantt-scale mapX), so this template never branches on direction. -->\r\n<div\r\n class=\"fly-gantt__scroll\"\r\n role=\"grid\"\r\n tabindex=\"0\"\r\n [attr.aria-label]=\"'gantt.aria.grid' | translate\"\r\n [attr.aria-rowcount]=\"visibleRows().length\"\r\n (keydown)=\"onGridKeydown($event)\"\r\n>\r\n <div\r\n class=\"fly-gantt__canvas\"\r\n [style.grid-template-columns]=\"effectiveLabelWidth() + 'px ' + innerWidth() + 'px'\"\r\n [style.grid-template-rows]=\"HEADER_H + 'px ' + bodyHeight() + 'px'\"\r\n >\r\n <!-- \u2500\u2500 Corner (pinned both axes) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"fly-gantt__corner\" [style.height.px]=\"HEADER_H\">\r\n @if (resizableLabels()) {\r\n <!-- The divider lives in the corner because the corner is the one cell pinned on BOTH\r\n axes: the grip stays reachable however far the user has scrolled. The full-height\r\n strip down the label pane below is the same gesture, presentational only. -->\r\n <div\r\n class=\"fly-gantt__splitter\"\r\n role=\"separator\"\r\n tabindex=\"0\"\r\n aria-orientation=\"vertical\"\r\n [attr.aria-label]=\"'gantt.aria.label_resize' | translate\"\r\n [attr.aria-valuenow]=\"effectiveLabelWidth()\"\r\n [attr.aria-valuemin]=\"MIN_LABEL_W\"\r\n [attr.aria-valuemax]=\"MAX_LABEL_W\"\r\n (pointerdown)=\"onLabelResizePointerDown($event)\"\r\n (keydown)=\"onLabelResizeKeydown($event)\"\r\n (dblclick)=\"resetLabelWidth()\"\r\n ></div>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 Time header (pinned top) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <svg\r\n class=\"fly-gantt__time-header\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"HEADER_H\"\r\n [attr.viewBox]=\"'0 0 ' + innerWidth() + ' ' + HEADER_H\"\r\n aria-hidden=\"true\"\r\n >\r\n @for (b of weekendBands(); track b.key) {\r\n <rect class=\"fly-gantt__weekend\" [attr.x]=\"b.x\" [attr.y]=\"HEADER_UPPER_H\" [attr.width]=\"b.width\" [attr.height]=\"HEADER_LOWER_H\" />\r\n }\r\n @for (t of upperTicks(); track t.key) {\r\n <line class=\"fly-gantt__tick-line\" [attr.x1]=\"t.x\" [attr.y1]=\"0\" [attr.x2]=\"t.x\" [attr.y2]=\"HEADER_H\" />\r\n <text class=\"fly-gantt__tick-label fly-gantt__tick-label--upper\" [attr.x]=\"t.x + t.width / 2\" [attr.y]=\"HEADER_UPPER_H / 2 + 4\">{{ t.label }}</text>\r\n }\r\n @for (t of lowerTicks(); track t.key) {\r\n <line class=\"fly-gantt__tick-line\" [attr.x1]=\"t.x\" [attr.y1]=\"HEADER_UPPER_H\" [attr.x2]=\"t.x\" [attr.y2]=\"HEADER_H\" />\r\n <text class=\"fly-gantt__tick-label\" [attr.x]=\"t.x + t.width / 2\" [attr.y]=\"HEADER_UPPER_H + HEADER_LOWER_H / 2 + 4\">{{ t.label }}</text>\r\n }\r\n @if (todayX() !== null) {\r\n <line class=\"fly-gantt__today\" [attr.x1]=\"todayX()\" [attr.y1]=\"HEADER_UPPER_H\" [attr.x2]=\"todayX()\" [attr.y2]=\"HEADER_H\" />\r\n }\r\n </svg>\r\n\r\n <!-- \u2500\u2500 Label tree (pinned inline-start) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"fly-gantt__labels\" role=\"rowgroup\">\r\n @for (vm of rowVms(); track vm.flat.row.id) {\r\n <div\r\n class=\"fly-gantt__label-row\"\r\n role=\"row\"\r\n tabindex=\"-1\"\r\n [class.fly-gantt__label-row--selected]=\"selectedId() === vm.flat.row.id\"\r\n [class.fly-gantt__label-row--tinted]=\"vm.tint !== null\"\r\n [style.height.px]=\"rowHeight()\"\r\n [style.--fly-gantt-row-tint]=\"vm.tint\"\r\n [attr.aria-selected]=\"selectedId() === vm.flat.row.id\"\r\n [attr.aria-label]=\"vm.ariaLabel\"\r\n (click)=\"onRowClick(vm.flat.row.id)\"\r\n (dblclick)=\"onRowDblClick(vm.flat.row.id)\"\r\n (keydown.enter)=\"onLabelRowKeydown($event, vm.flat.row.id)\"\r\n >\r\n <span class=\"fly-gantt__label-inner\" [style.padding-inline-start.px]=\"indentFor(vm.flat.depth)\">\r\n @if (vm.flat.hasChildren) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-gantt__chevron\"\r\n [class.fly-gantt__chevron--collapsed]=\"isCollapsed(vm.flat.row.id)\"\r\n [attr.aria-label]=\"(isCollapsed(vm.flat.row.id) ? 'gantt.expand' : 'gantt.collapse') | translate\"\r\n [attr.aria-expanded]=\"!isCollapsed(vm.flat.row.id)\"\r\n (click)=\"toggleCollapse(vm.flat.row.id, $event)\"\r\n >\u25B8</button>\r\n } @else {\r\n <span class=\"fly-gantt__chevron-spacer\"></span>\r\n }\r\n @if (vm.color) {\r\n <!-- Colour chip: the row's own colour at full strength, so a milestone stays\r\n identifiable in the label pane where the band tint is deliberately faint. -->\r\n <span class=\"fly-gantt__label-swatch\" [style.background]=\"vm.color\" aria-hidden=\"true\"></span>\r\n }\r\n <span\r\n class=\"fly-gantt__label-text\"\r\n [class.fly-gantt__label-text--group]=\"vm.shape === 'group'\"\r\n [title]=\"vm.flat.row.label\"\r\n >{{ vm.flat.row.label }}</span>\r\n </span>\r\n </div>\r\n }\r\n @if (resizableLabels()) {\r\n <!-- aria-hidden so this presentational twin of the corner separator is not a second\r\n (and structurally invalid) child of the rowgroup in the accessibility tree. -->\r\n <div\r\n class=\"fly-gantt__splitter fly-gantt__splitter--rail\"\r\n aria-hidden=\"true\"\r\n (pointerdown)=\"onLabelResizePointerDown($event)\"\r\n (dblclick)=\"resetLabelWidth()\"\r\n ></div>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 Time grid body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <svg\r\n #bodySvg\r\n class=\"fly-gantt__body\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"bodyHeight()\"\r\n [attr.viewBox]=\"'0 0 ' + innerWidth() + ' ' + bodyHeight()\"\r\n >\r\n <defs>\r\n <marker\r\n [attr.id]=\"markerId\"\r\n markerWidth=\"8\"\r\n markerHeight=\"8\"\r\n refX=\"6\"\r\n refY=\"4\"\r\n orient=\"auto\"\r\n markerUnits=\"userSpaceOnUse\"\r\n >\r\n <path class=\"fly-gantt__arrowhead\" d=\"M0,0 L7,4 L0,8 Z\" />\r\n </marker>\r\n </defs>\r\n\r\n <!-- Row colour bands sit at the very bottom of the stack, so the weekend shading and the\r\n gridlines below still read through them. -->\r\n @for (vm of tintedRows(); track vm.flat.row.id) {\r\n <rect\r\n class=\"fly-gantt__row-band\"\r\n [attr.x]=\"0\"\r\n [attr.y]=\"vm.y\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"rowHeight()\"\r\n [style.fill]=\"vm.tint\"\r\n />\r\n }\r\n\r\n <!-- Weekend shading + vertical gridlines (behind the bars). -->\r\n @for (b of weekendBands(); track b.key) {\r\n <rect class=\"fly-gantt__weekend\" [attr.x]=\"b.x\" [attr.y]=\"0\" [attr.width]=\"b.width\" [attr.height]=\"bodyHeight()\" />\r\n }\r\n @for (t of lowerTicks(); track t.key) {\r\n <line class=\"fly-gantt__grid-line\" [attr.x1]=\"t.x\" [attr.y1]=\"0\" [attr.x2]=\"t.x\" [attr.y2]=\"bodyHeight()\" />\r\n }\r\n\r\n <!-- Rows: a full-width hit rect (click + link drop target) then the shape. -->\r\n @for (vm of rowVms(); track vm.flat.row.id) {\r\n <g class=\"fly-gantt__row\" [attr.data-row-id]=\"vm.flat.row.id\">\r\n <rect\r\n class=\"fly-gantt__row-hit\"\r\n [class.fly-gantt__row-hit--selected]=\"selectedId() === vm.flat.row.id\"\r\n [attr.x]=\"0\"\r\n [attr.y]=\"vm.y\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"rowHeight()\"\r\n (pointerdown)=\"onRowClick(vm.flat.row.id)\"\r\n (dblclick)=\"onRowDblClick(vm.flat.row.id)\"\r\n />\r\n\r\n @switch (vm.shape) {\r\n @case ('group') {\r\n <path class=\"fly-gantt__group\" [attr.d]=\"groupPath(vm)\" [style.fill]=\"vm.color\" [style.stroke]=\"vm.color\" />\r\n }\r\n @case ('milestone') {\r\n <polygon\r\n class=\"fly-gantt__milestone\"\r\n [class.fly-gantt__milestone--editable]=\"vm.editable\"\r\n [attr.points]=\"diamondPoints(vm)\"\r\n [style.fill]=\"vm.color\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'move')\"\r\n />\r\n @if (!readonly() && !vm.flat.row.readonly) {\r\n <!-- A diamond has no width, so one connector serves it; it reads as the finish\r\n end, which is what makes a milestone\u2192task drag the FS everyone expects. -->\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"milestoneConnectorX(vm)\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'finish')\"\r\n />\r\n }\r\n }\r\n @case ('bar') {\r\n <g class=\"fly-gantt__bar-group\">\r\n <rect\r\n class=\"fly-gantt__bar\"\r\n [class.fly-gantt__bar--editable]=\"vm.editable\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"vm.width\"\r\n [attr.height]=\"barHeight()\"\r\n rx=\"4\"\r\n [style.fill]=\"vm.color\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'move')\"\r\n />\r\n @if (vm.progressWidth > 0) {\r\n <rect\r\n class=\"fly-gantt__progress\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"vm.progressWidth\"\r\n [attr.height]=\"barHeight()\"\r\n rx=\"4\"\r\n />\r\n }\r\n @if (vm.editable) {\r\n <!-- Resize handles at both edges. -->\r\n <rect\r\n class=\"fly-gantt__handle\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"HANDLE_W\"\r\n [attr.height]=\"barHeight()\"\r\n [attr.aria-label]=\"'gantt.aria.resize_start' | translate\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'resize-start')\"\r\n />\r\n <rect\r\n class=\"fly-gantt__handle\"\r\n [attr.x]=\"vm.x + vm.width - HANDLE_W\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"HANDLE_W\"\r\n [attr.height]=\"barHeight()\"\r\n [attr.aria-label]=\"'gantt.aria.resize_end' | translate\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'resize-end')\"\r\n />\r\n }\r\n @if (!readonly() && !vm.flat.row.readonly) {\r\n <!-- One connector per END. Dragging from the start edge yields an SS/SF link\r\n and from the finish edge an FS/FF one \u2014 the drop edge picks which. -->\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"vm.startX\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle_start' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'start')\"\r\n />\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"vm.endX\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'finish')\"\r\n />\r\n }\r\n </g>\r\n }\r\n }\r\n </g>\r\n }\r\n\r\n <!-- Dependency arrows (skipped for missing / collapsed endpoints). Each carries a fat\r\n transparent twin so a 1.5px line is still clickable at pointer precision. -->\r\n @for (link of linkVms(); track link.key) {\r\n <g class=\"fly-gantt__link-group\" [class.fly-gantt__link-group--selected]=\"selectedLinkKey() === link.key\">\r\n <path\r\n class=\"fly-gantt__link-hit\"\r\n [attr.d]=\"link.path\"\r\n [attr.aria-label]=\"link.ariaLabel\"\r\n (click)=\"onLinkClick($event, link)\"\r\n />\r\n <path class=\"fly-gantt__link\" [attr.d]=\"link.path\" [attr.marker-end]=\"'url(#' + markerId + ')'\" />\r\n @if (selectedLinkKey() === link.key && !readonly()) {\r\n <g\r\n class=\"fly-gantt__link-delete\"\r\n [attr.transform]=\"'translate(' + link.badgeX + ',' + link.badgeY + ')'\"\r\n [attr.aria-label]=\"'gantt.aria.delete_link' | translate\"\r\n (click)=\"deleteLink($event, link)\"\r\n >\r\n <circle class=\"fly-gantt__link-delete-bg\" r=\"8\" />\r\n <path class=\"fly-gantt__link-delete-x\" d=\"M-3.5,-3.5 L3.5,3.5 M3.5,-3.5 L-3.5,3.5\" />\r\n </g>\r\n }\r\n </g>\r\n }\r\n\r\n <!-- In-flight link rubber band. -->\r\n @if (linkGesturePath(); as gp) {\r\n <path class=\"fly-gantt__link fly-gantt__link--ghost\" [attr.d]=\"gp\" [attr.marker-end]=\"'url(#' + markerId + ')'\" />\r\n }\r\n\r\n <!-- Today line (over the bars). -->\r\n @if (todayX() !== null) {\r\n <line class=\"fly-gantt__today\" [attr.x1]=\"todayX()\" [attr.y1]=\"0\" [attr.x2]=\"todayX()\" [attr.y2]=\"bodyHeight()\" />\r\n }\r\n </svg>\r\n </div>\r\n\r\n @if (visibleRows().length === 0) {\r\n <p class=\"fly-gantt__empty\">{{ 'gantt.no_data' | translate }}</p>\r\n }\r\n @if (overflowCount() > 0) {\r\n <p class=\"fly-gantt__overflow\">\r\n {{ 'gantt.overflow' | translate: { shown: maxRows(), total: maxRows() + overflowCount() } }}\r\n </p>\r\n }\r\n</div>\r\n\r\n<!-- Drag candidate tooltip (HTML overlay, follows the cursor). -->\r\n@if (dragTooltip(); as tip) {\r\n <div class=\"fly-gantt__tooltip\" [style.left.px]=\"tip.x\" [style.top.px]=\"tip.y\">{{ tip.text }}</div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--bg-2, var(--surface-card, #fff));--_surface-alt: var(--bg-3, var(--glass-bg-elevated, #f8fafc));--_surface-hover: var(--bg-hover, var(--surface-hover, #f1f5f9));--_border: var(--w08, var(--surface-border, #e2e8f0));--_border-strong: var(--w1, var(--surface-border, #cbd5e1));--_grid-line: var(--line-3, var(--surface-border, #eef2f7));--_text: var(--ink, var(--text-color, #0f172a));--_text-subtle: var(--ink-3, var(--text-color-secondary, #64748b));--_text-faint: var(--ink-4, var(--text-color-secondary, #94a3b8));--_accent: var(--accent);--_bar: var(--_accent);--_bar-progress: color-mix(in srgb, var(--_accent) 72%, #000);--_weekend: color-mix(in srgb, var(--_text-subtle) 9%, transparent);--_today: var(--danger, #ef4444);--_link: var(--_text-subtle);--_radius: var(--r-lg, 8px);--_transition: var(--t-state, .12s ease);display:block;inline-size:100%;block-size:100%;min-block-size:200px;color:var(--_text);font-size:13px}:host(.fly-gantt--resizing){cursor:col-resize;-webkit-user-select:none;user-select:none}.fly-gantt__scroll{position:relative;inline-size:100%;block-size:100%;overflow:auto;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);box-shadow:var(--shadow-card, none);outline:none}.fly-gantt__scroll:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:-2px}.fly-gantt__canvas{display:grid;position:relative}.fly-gantt__corner{position:sticky;inset-block-start:0;inset-inline-start:0;z-index:4;background:var(--_surface-alt);-webkit-backdrop-filter:blur(12px) saturate(140%);backdrop-filter:blur(12px) saturate(140%);border-inline-end:1px solid var(--_border);border-block-end:1px solid var(--_border-strong)}.fly-gantt__time-header{position:sticky;inset-block-start:0;z-index:3;display:block;background:var(--_surface-alt);-webkit-backdrop-filter:blur(12px) saturate(140%);backdrop-filter:blur(12px) saturate(140%);border-block-end:1px solid var(--_border-strong)}.fly-gantt__tick-line{stroke:var(--_grid-line);stroke-width:1}.fly-gantt__tick-label{fill:var(--_text-subtle);font-size:11px;text-anchor:middle;dominant-baseline:middle}.fly-gantt__tick-label--upper{fill:var(--_text);font-weight:600}.fly-gantt__splitter{position:absolute;inset-block:0;inset-inline-end:-3px;inline-size:7px;z-index:5;cursor:col-resize;touch-action:none}.fly-gantt__splitter:after{content:\"\";position:absolute;inset-block:0;inset-inline-start:3px;inline-size:1px;background:transparent;transition:background var(--_transition)}.fly-gantt__splitter:hover:after,.fly-gantt__splitter:focus-visible:after{background:var(--_accent)}.fly-gantt__splitter:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:-1px}:host(.fly-gantt--resizing) .fly-gantt__splitter:after{background:var(--_accent)}.fly-gantt__labels{position:sticky;inset-inline-start:0;z-index:2;background:var(--_surface);border-inline-end:1px solid var(--_border)}.fly-gantt__label-row{position:relative;display:flex;align-items:center;border-block-end:1px solid var(--_grid-line);cursor:pointer;transition:background var(--_transition)}.fly-gantt__label-row:hover{background:var(--_surface-hover)}.fly-gantt__label-row--selected{background:var(--_surface-hover);box-shadow:inset 3px 0 0 0 var(--_accent)}.fly-gantt__label-row--tinted:before{content:\"\";position:absolute;inset:0;background:var(--fly-gantt-row-tint);pointer-events:none}.fly-gantt__label-inner{position:relative;display:flex;align-items:center;gap:4px;inline-size:100%;min-inline-size:0;padding-inline-end:8px}.fly-gantt__label-swatch{flex:0 0 auto;inline-size:8px;block-size:8px;border-radius:2px}.fly-gantt__chevron{flex:0 0 auto;inline-size:18px;block-size:18px;padding:0;border:none;background:transparent;color:var(--_text-subtle);cursor:pointer;line-height:1;transform:rotate(90deg);transition:transform var(--_transition)}.fly-gantt__chevron--collapsed{transform:rotate(0)}:host(.fly-gantt--rtl) .fly-gantt__chevron--collapsed{transform:rotate(180deg)}.fly-gantt__chevron:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:1px;border-radius:4px}.fly-gantt__chevron-spacer{flex:0 0 auto;inline-size:18px}.fly-gantt__label-text{min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-gantt__label-text--group{font-weight:600}.fly-gantt__body{display:block;touch-action:pan-x pan-y}.fly-gantt__row-band{pointer-events:none}.fly-gantt__weekend{fill:var(--_weekend)}.fly-gantt__grid-line{stroke:var(--_grid-line);stroke-width:1}.fly-gantt__row-hit{fill:transparent}.fly-gantt__row-hit--selected{fill:var(--_surface-hover)}.fly-gantt__bar{fill:var(--_bar);stroke:none}.fly-gantt__bar--editable{cursor:grab}.fly-gantt__progress{fill:var(--_bar-progress);pointer-events:none}.fly-gantt__handle{fill:transparent;cursor:ew-resize}.fly-gantt__connector{fill:var(--_surface);stroke:var(--_accent);stroke-width:1.5;cursor:crosshair;opacity:0;transition:opacity var(--_transition)}.fly-gantt__row:hover .fly-gantt__connector{opacity:1}.fly-gantt__milestone{fill:var(--_accent);stroke:var(--_surface);stroke-width:1}.fly-gantt__milestone--editable{cursor:grab}.fly-gantt__group{fill:var(--_text-subtle);stroke:var(--_text-subtle)}.fly-gantt__link{fill:none;stroke:var(--_link);stroke-width:1.5;pointer-events:none}.fly-gantt__link-hit{fill:none;stroke:transparent;stroke-width:11;pointer-events:stroke;cursor:pointer}.fly-gantt__link-group:hover .fly-gantt__link{stroke:var(--_text)}.fly-gantt__link-group--selected .fly-gantt__link{stroke:var(--_accent);stroke-width:2.5}.fly-gantt__link-delete-bg{fill:var(--_accent)}.fly-gantt__link-delete{cursor:pointer}.fly-gantt__link-delete-x{stroke:var(--_surface);stroke-width:1.75;stroke-linecap:round;fill:none;pointer-events:none}.fly-gantt__link--ghost{stroke-dasharray:4 3;opacity:.8}.fly-gantt__arrowhead{fill:var(--_link)}.fly-gantt__today{stroke:var(--_today);stroke-width:1.5;stroke-dasharray:3 3;pointer-events:none}.fly-gantt__empty,.fly-gantt__overflow{margin:0;padding:12px;color:var(--_text-faint);font-size:12px;text-align:center}.fly-gantt__tooltip{position:fixed;z-index:20;transform:translate(12px,16px);padding:4px 8px;border-radius:6px;background:var(--_text);color:var(--_surface);font-size:12px;white-space:nowrap;pointer-events:none;direction:ltr;unicode-bidi:isolate}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13889
13889
  }
13890
13890
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyGanttComponent, decorators: [{
13891
13891
  type: Component,
@@ -13895,7 +13895,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
13895
13895
  '[class.fly-gantt--readonly]': 'readonly()',
13896
13896
  '[class.fly-gantt--resizing]': 'resizingLabels()',
13897
13897
  '[attr.dir]': 'i18n.direction()',
13898
- }, template: "<!-- Cross-scrolling canvas: a CSS grid whose header row and label column are sticky, so the\r\n time grid scrolls under a pinned header + label tree. All SVG geometry is pre-mirrored for\r\n RTL in the component (see gantt-scale mapX), so this template never branches on direction. -->\r\n<div\r\n class=\"fly-gantt__scroll\"\r\n role=\"grid\"\r\n tabindex=\"0\"\r\n [attr.aria-label]=\"'gantt.aria.grid' | translate\"\r\n [attr.aria-rowcount]=\"visibleRows().length\"\r\n (keydown)=\"onGridKeydown($event)\"\r\n>\r\n <div\r\n class=\"fly-gantt__canvas\"\r\n [style.grid-template-columns]=\"effectiveLabelWidth() + 'px ' + innerWidth() + 'px'\"\r\n [style.grid-template-rows]=\"HEADER_H + 'px ' + bodyHeight() + 'px'\"\r\n >\r\n <!-- \u2500\u2500 Corner (pinned both axes) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"fly-gantt__corner\" [style.height.px]=\"HEADER_H\">\r\n @if (resizableLabels()) {\r\n <!-- The divider lives in the corner because the corner is the one cell pinned on BOTH\r\n axes: the grip stays reachable however far the user has scrolled. The full-height\r\n strip down the label pane below is the same gesture, presentational only. -->\r\n <div\r\n class=\"fly-gantt__splitter\"\r\n role=\"separator\"\r\n tabindex=\"0\"\r\n aria-orientation=\"vertical\"\r\n [attr.aria-label]=\"'gantt.aria.label_resize' | translate\"\r\n [attr.aria-valuenow]=\"effectiveLabelWidth()\"\r\n [attr.aria-valuemin]=\"MIN_LABEL_W\"\r\n [attr.aria-valuemax]=\"MAX_LABEL_W\"\r\n (pointerdown)=\"onLabelResizePointerDown($event)\"\r\n (keydown)=\"onLabelResizeKeydown($event)\"\r\n (dblclick)=\"resetLabelWidth()\"\r\n ></div>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 Time header (pinned top) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <svg\r\n class=\"fly-gantt__time-header\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"HEADER_H\"\r\n [attr.viewBox]=\"'0 0 ' + innerWidth() + ' ' + HEADER_H\"\r\n aria-hidden=\"true\"\r\n >\r\n @for (b of weekendBands(); track b.key) {\r\n <rect class=\"fly-gantt__weekend\" [attr.x]=\"b.x\" [attr.y]=\"HEADER_UPPER_H\" [attr.width]=\"b.width\" [attr.height]=\"HEADER_LOWER_H\" />\r\n }\r\n @for (t of upperTicks(); track t.key) {\r\n <line class=\"fly-gantt__tick-line\" [attr.x1]=\"t.x\" [attr.y1]=\"0\" [attr.x2]=\"t.x\" [attr.y2]=\"HEADER_H\" />\r\n <text class=\"fly-gantt__tick-label fly-gantt__tick-label--upper\" [attr.x]=\"t.x + t.width / 2\" [attr.y]=\"HEADER_UPPER_H / 2 + 4\">{{ t.label }}</text>\r\n }\r\n @for (t of lowerTicks(); track t.key) {\r\n <line class=\"fly-gantt__tick-line\" [attr.x1]=\"t.x\" [attr.y1]=\"HEADER_UPPER_H\" [attr.x2]=\"t.x\" [attr.y2]=\"HEADER_H\" />\r\n <text class=\"fly-gantt__tick-label\" [attr.x]=\"t.x + t.width / 2\" [attr.y]=\"HEADER_UPPER_H + HEADER_LOWER_H / 2 + 4\">{{ t.label }}</text>\r\n }\r\n @if (todayX() !== null) {\r\n <line class=\"fly-gantt__today\" [attr.x1]=\"todayX()\" [attr.y1]=\"HEADER_UPPER_H\" [attr.x2]=\"todayX()\" [attr.y2]=\"HEADER_H\" />\r\n }\r\n </svg>\r\n\r\n <!-- \u2500\u2500 Label tree (pinned inline-start) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"fly-gantt__labels\" role=\"rowgroup\">\r\n @for (vm of rowVms(); track vm.flat.row.id) {\r\n <div\r\n class=\"fly-gantt__label-row\"\r\n role=\"row\"\r\n tabindex=\"-1\"\r\n [class.fly-gantt__label-row--selected]=\"selectedId() === vm.flat.row.id\"\r\n [class.fly-gantt__label-row--tinted]=\"vm.tint !== null\"\r\n [style.height.px]=\"rowHeight()\"\r\n [style.--fly-gantt-row-tint]=\"vm.tint\"\r\n [attr.aria-selected]=\"selectedId() === vm.flat.row.id\"\r\n [attr.aria-label]=\"vm.ariaLabel\"\r\n (click)=\"onRowClick(vm.flat.row.id)\"\r\n (dblclick)=\"onRowDblClick(vm.flat.row.id)\"\r\n (keydown.enter)=\"onLabelRowKeydown($event, vm.flat.row.id)\"\r\n >\r\n <span class=\"fly-gantt__label-inner\" [style.padding-inline-start.px]=\"indentFor(vm.flat.depth)\">\r\n @if (vm.flat.hasChildren) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-gantt__chevron\"\r\n [class.fly-gantt__chevron--collapsed]=\"isCollapsed(vm.flat.row.id)\"\r\n [attr.aria-label]=\"(isCollapsed(vm.flat.row.id) ? 'gantt.expand' : 'gantt.collapse') | translate\"\r\n [attr.aria-expanded]=\"!isCollapsed(vm.flat.row.id)\"\r\n (click)=\"toggleCollapse(vm.flat.row.id, $event)\"\r\n >\u25B8</button>\r\n } @else {\r\n <span class=\"fly-gantt__chevron-spacer\"></span>\r\n }\r\n @if (vm.color) {\r\n <!-- Colour chip: the row's own colour at full strength, so a milestone stays\r\n identifiable in the label pane where the band tint is deliberately faint. -->\r\n <span class=\"fly-gantt__label-swatch\" [style.background]=\"vm.color\" aria-hidden=\"true\"></span>\r\n }\r\n <span\r\n class=\"fly-gantt__label-text\"\r\n [class.fly-gantt__label-text--group]=\"vm.shape === 'group'\"\r\n [title]=\"vm.flat.row.label\"\r\n >{{ vm.flat.row.label }}</span>\r\n </span>\r\n </div>\r\n }\r\n @if (resizableLabels()) {\r\n <!-- aria-hidden so this presentational twin of the corner separator is not a second\r\n (and structurally invalid) child of the rowgroup in the accessibility tree. -->\r\n <div\r\n class=\"fly-gantt__splitter fly-gantt__splitter--rail\"\r\n aria-hidden=\"true\"\r\n (pointerdown)=\"onLabelResizePointerDown($event)\"\r\n (dblclick)=\"resetLabelWidth()\"\r\n ></div>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 Time grid body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <svg\r\n #bodySvg\r\n class=\"fly-gantt__body\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"bodyHeight()\"\r\n [attr.viewBox]=\"'0 0 ' + innerWidth() + ' ' + bodyHeight()\"\r\n >\r\n <defs>\r\n <marker\r\n [attr.id]=\"markerId\"\r\n markerWidth=\"8\"\r\n markerHeight=\"8\"\r\n refX=\"6\"\r\n refY=\"4\"\r\n orient=\"auto\"\r\n markerUnits=\"userSpaceOnUse\"\r\n >\r\n <path class=\"fly-gantt__arrowhead\" d=\"M0,0 L7,4 L0,8 Z\" />\r\n </marker>\r\n </defs>\r\n\r\n <!-- Row colour bands sit at the very bottom of the stack, so the weekend shading and the\r\n gridlines below still read through them. -->\r\n @for (vm of tintedRows(); track vm.flat.row.id) {\r\n <rect\r\n class=\"fly-gantt__row-band\"\r\n [attr.x]=\"0\"\r\n [attr.y]=\"vm.y\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"rowHeight()\"\r\n [style.fill]=\"vm.tint\"\r\n />\r\n }\r\n\r\n <!-- Weekend shading + vertical gridlines (behind the bars). -->\r\n @for (b of weekendBands(); track b.key) {\r\n <rect class=\"fly-gantt__weekend\" [attr.x]=\"b.x\" [attr.y]=\"0\" [attr.width]=\"b.width\" [attr.height]=\"bodyHeight()\" />\r\n }\r\n @for (t of lowerTicks(); track t.key) {\r\n <line class=\"fly-gantt__grid-line\" [attr.x1]=\"t.x\" [attr.y1]=\"0\" [attr.x2]=\"t.x\" [attr.y2]=\"bodyHeight()\" />\r\n }\r\n\r\n <!-- Rows: a full-width hit rect (click + link drop target) then the shape. -->\r\n @for (vm of rowVms(); track vm.flat.row.id) {\r\n <g class=\"fly-gantt__row\" [attr.data-row-id]=\"vm.flat.row.id\">\r\n <rect\r\n class=\"fly-gantt__row-hit\"\r\n [class.fly-gantt__row-hit--selected]=\"selectedId() === vm.flat.row.id\"\r\n [attr.x]=\"0\"\r\n [attr.y]=\"vm.y\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"rowHeight()\"\r\n (pointerdown)=\"onRowClick(vm.flat.row.id)\"\r\n (dblclick)=\"onRowDblClick(vm.flat.row.id)\"\r\n />\r\n\r\n @switch (vm.shape) {\r\n @case ('group') {\r\n <path class=\"fly-gantt__group\" [attr.d]=\"groupPath(vm)\" [style.fill]=\"vm.color\" [style.stroke]=\"vm.color\" />\r\n }\r\n @case ('milestone') {\r\n <polygon\r\n class=\"fly-gantt__milestone\"\r\n [class.fly-gantt__milestone--editable]=\"vm.editable\"\r\n [attr.points]=\"diamondPoints(vm)\"\r\n [style.fill]=\"vm.color\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'move')\"\r\n />\r\n @if (!readonly() && !vm.flat.row.readonly) {\r\n <!-- A diamond has no width, so one connector serves it; it reads as the finish\r\n end, which is what makes a milestone\u2192task drag the FS everyone expects. -->\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"milestoneConnectorX(vm)\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'finish')\"\r\n />\r\n }\r\n }\r\n @case ('bar') {\r\n <g class=\"fly-gantt__bar-group\">\r\n <rect\r\n class=\"fly-gantt__bar\"\r\n [class.fly-gantt__bar--editable]=\"vm.editable\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"vm.width\"\r\n [attr.height]=\"barHeight()\"\r\n rx=\"4\"\r\n [style.fill]=\"vm.color\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'move')\"\r\n />\r\n @if (vm.progressWidth > 0) {\r\n <rect\r\n class=\"fly-gantt__progress\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"vm.progressWidth\"\r\n [attr.height]=\"barHeight()\"\r\n rx=\"4\"\r\n />\r\n }\r\n @if (vm.editable) {\r\n <!-- Resize handles at both edges. -->\r\n <rect\r\n class=\"fly-gantt__handle\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"HANDLE_W\"\r\n [attr.height]=\"barHeight()\"\r\n [attr.aria-label]=\"'gantt.aria.resize_start' | translate\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'resize-start')\"\r\n />\r\n <rect\r\n class=\"fly-gantt__handle\"\r\n [attr.x]=\"vm.x + vm.width - HANDLE_W\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"HANDLE_W\"\r\n [attr.height]=\"barHeight()\"\r\n [attr.aria-label]=\"'gantt.aria.resize_end' | translate\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'resize-end')\"\r\n />\r\n }\r\n @if (!readonly() && !vm.flat.row.readonly) {\r\n <!-- One connector per END. Dragging from the start edge yields an SS/SF link\r\n and from the finish edge an FS/FF one \u2014 the drop edge picks which. -->\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"vm.startX\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle_start' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'start')\"\r\n />\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"vm.endX\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'finish')\"\r\n />\r\n }\r\n </g>\r\n }\r\n }\r\n </g>\r\n }\r\n\r\n <!-- Dependency arrows (skipped for missing / collapsed endpoints). Each carries a fat\r\n transparent twin so a 1.5px line is still clickable at pointer precision. -->\r\n @for (link of linkVms(); track link.key) {\r\n <g class=\"fly-gantt__link-group\" [class.fly-gantt__link-group--selected]=\"selectedLinkKey() === link.key\">\r\n <path\r\n class=\"fly-gantt__link-hit\"\r\n [attr.d]=\"link.path\"\r\n [attr.aria-label]=\"link.ariaLabel\"\r\n (click)=\"onLinkClick($event, link)\"\r\n />\r\n <path class=\"fly-gantt__link\" [attr.d]=\"link.path\" [attr.marker-end]=\"'url(#' + markerId + ')'\" />\r\n @if (selectedLinkKey() === link.key && !readonly()) {\r\n <g\r\n class=\"fly-gantt__link-delete\"\r\n [attr.transform]=\"'translate(' + link.badgeX + ',' + link.badgeY + ')'\"\r\n [attr.aria-label]=\"'gantt.aria.delete_link' | translate\"\r\n (click)=\"deleteLink($event, link)\"\r\n >\r\n <circle class=\"fly-gantt__link-delete-bg\" r=\"8\" />\r\n <path class=\"fly-gantt__link-delete-x\" d=\"M-3.5,-3.5 L3.5,3.5 M3.5,-3.5 L-3.5,3.5\" />\r\n </g>\r\n }\r\n </g>\r\n }\r\n\r\n <!-- In-flight link rubber band. -->\r\n @if (linkGesturePath(); as gp) {\r\n <path class=\"fly-gantt__link fly-gantt__link--ghost\" [attr.d]=\"gp\" [attr.marker-end]=\"'url(#' + markerId + ')'\" />\r\n }\r\n\r\n <!-- Today line (over the bars). -->\r\n @if (todayX() !== null) {\r\n <line class=\"fly-gantt__today\" [attr.x1]=\"todayX()\" [attr.y1]=\"0\" [attr.x2]=\"todayX()\" [attr.y2]=\"bodyHeight()\" />\r\n }\r\n </svg>\r\n </div>\r\n\r\n @if (visibleRows().length === 0) {\r\n <p class=\"fly-gantt__empty\">{{ 'gantt.no_data' | translate }}</p>\r\n }\r\n @if (overflowCount() > 0) {\r\n <p class=\"fly-gantt__overflow\">\r\n {{ 'gantt.overflow' | translate: { shown: maxRows(), total: maxRows() + overflowCount() } }}\r\n </p>\r\n }\r\n</div>\r\n\r\n<!-- Drag candidate tooltip (HTML overlay, follows the cursor). -->\r\n@if (dragTooltip(); as tip) {\r\n <div class=\"fly-gantt__tooltip\" [style.left.px]=\"tip.x\" [style.top.px]=\"tip.y\">{{ tip.text }}</div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--bg-2, var(--surface-card, #fff));--_surface-alt: var(--bg-3, var(--glass-bg-elevated, #f8fafc));--_surface-hover: var(--bg-hover, var(--surface-hover, #f1f5f9));--_border: var(--w08, var(--surface-border, #e2e8f0));--_border-strong: var(--w1, var(--surface-border, #cbd5e1));--_grid-line: var(--line-3, var(--surface-border, #eef2f7));--_text: var(--ink, var(--text-color, #0f172a));--_text-subtle: var(--ink-3, var(--text-color-secondary, #64748b));--_text-faint: var(--ink-4, var(--text-color-secondary, #94a3b8));--_accent: var(--accent);--_bar: var(--_accent);--_bar-progress: color-mix(in srgb, var(--_accent) 72%, #000);--_weekend: color-mix(in srgb, var(--_text-subtle) 9%, transparent);--_today: var(--danger, #ef4444);--_link: var(--_text-subtle);--_radius: var(--r-lg, 8px);--_transition: var(--t-state, .12s ease);display:block;inline-size:100%;block-size:100%;min-block-size:200px;color:var(--_text);font-size:13px}:host(.fly-gantt--resizing){cursor:col-resize;-webkit-user-select:none;user-select:none}.fly-gantt__scroll{position:relative;inline-size:100%;block-size:100%;overflow:auto;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);box-shadow:var(--shadow-card, none);outline:none}.fly-gantt__scroll:focus-visible{outline:2px solid var(--_accent);outline-offset:-2px}.fly-gantt__canvas{display:grid;position:relative}.fly-gantt__corner{position:sticky;inset-block-start:0;inset-inline-start:0;z-index:4;background:var(--_surface-alt);-webkit-backdrop-filter:blur(12px) saturate(140%);backdrop-filter:blur(12px) saturate(140%);border-inline-end:1px solid var(--_border);border-block-end:1px solid var(--_border-strong)}.fly-gantt__time-header{position:sticky;inset-block-start:0;z-index:3;display:block;background:var(--_surface-alt);-webkit-backdrop-filter:blur(12px) saturate(140%);backdrop-filter:blur(12px) saturate(140%);border-block-end:1px solid var(--_border-strong)}.fly-gantt__tick-line{stroke:var(--_grid-line);stroke-width:1}.fly-gantt__tick-label{fill:var(--_text-subtle);font-size:11px;text-anchor:middle;dominant-baseline:middle}.fly-gantt__tick-label--upper{fill:var(--_text);font-weight:600}.fly-gantt__splitter{position:absolute;inset-block:0;inset-inline-end:-3px;inline-size:7px;z-index:5;cursor:col-resize;touch-action:none}.fly-gantt__splitter:after{content:\"\";position:absolute;inset-block:0;inset-inline-start:3px;inline-size:1px;background:transparent;transition:background var(--_transition)}.fly-gantt__splitter:hover:after,.fly-gantt__splitter:focus-visible:after{background:var(--_accent)}.fly-gantt__splitter:focus-visible{outline:2px solid var(--_accent);outline-offset:-1px}:host(.fly-gantt--resizing) .fly-gantt__splitter:after{background:var(--_accent)}.fly-gantt__labels{position:sticky;inset-inline-start:0;z-index:2;background:var(--_surface);border-inline-end:1px solid var(--_border)}.fly-gantt__label-row{position:relative;display:flex;align-items:center;border-block-end:1px solid var(--_grid-line);cursor:pointer;transition:background var(--_transition)}.fly-gantt__label-row:hover{background:var(--_surface-hover)}.fly-gantt__label-row--selected{background:var(--_surface-hover);box-shadow:inset 3px 0 0 0 var(--_accent)}.fly-gantt__label-row--tinted:before{content:\"\";position:absolute;inset:0;background:var(--fly-gantt-row-tint);pointer-events:none}.fly-gantt__label-inner{position:relative;display:flex;align-items:center;gap:4px;inline-size:100%;min-inline-size:0;padding-inline-end:8px}.fly-gantt__label-swatch{flex:0 0 auto;inline-size:8px;block-size:8px;border-radius:2px}.fly-gantt__chevron{flex:0 0 auto;inline-size:18px;block-size:18px;padding:0;border:none;background:transparent;color:var(--_text-subtle);cursor:pointer;line-height:1;transform:rotate(90deg);transition:transform var(--_transition)}.fly-gantt__chevron--collapsed{transform:rotate(0)}:host(.fly-gantt--rtl) .fly-gantt__chevron--collapsed{transform:rotate(180deg)}.fly-gantt__chevron:focus-visible{outline:2px solid var(--_accent);outline-offset:1px;border-radius:4px}.fly-gantt__chevron-spacer{flex:0 0 auto;inline-size:18px}.fly-gantt__label-text{min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-gantt__label-text--group{font-weight:600}.fly-gantt__body{display:block;touch-action:pan-x pan-y}.fly-gantt__row-band{pointer-events:none}.fly-gantt__weekend{fill:var(--_weekend)}.fly-gantt__grid-line{stroke:var(--_grid-line);stroke-width:1}.fly-gantt__row-hit{fill:transparent}.fly-gantt__row-hit--selected{fill:var(--_surface-hover)}.fly-gantt__bar{fill:var(--_bar);stroke:none}.fly-gantt__bar--editable{cursor:grab}.fly-gantt__progress{fill:var(--_bar-progress);pointer-events:none}.fly-gantt__handle{fill:transparent;cursor:ew-resize}.fly-gantt__connector{fill:var(--_surface);stroke:var(--_accent);stroke-width:1.5;cursor:crosshair;opacity:0;transition:opacity var(--_transition)}.fly-gantt__row:hover .fly-gantt__connector{opacity:1}.fly-gantt__milestone{fill:var(--_accent);stroke:var(--_surface);stroke-width:1}.fly-gantt__milestone--editable{cursor:grab}.fly-gantt__group{fill:var(--_text-subtle);stroke:var(--_text-subtle)}.fly-gantt__link{fill:none;stroke:var(--_link);stroke-width:1.5;pointer-events:none}.fly-gantt__link-hit{fill:none;stroke:transparent;stroke-width:11;pointer-events:stroke;cursor:pointer}.fly-gantt__link-group:hover .fly-gantt__link{stroke:var(--_text)}.fly-gantt__link-group--selected .fly-gantt__link{stroke:var(--_accent);stroke-width:2.5}.fly-gantt__link-delete-bg{fill:var(--_accent)}.fly-gantt__link-delete{cursor:pointer}.fly-gantt__link-delete-x{stroke:var(--_surface);stroke-width:1.75;stroke-linecap:round;fill:none;pointer-events:none}.fly-gantt__link--ghost{stroke-dasharray:4 3;opacity:.8}.fly-gantt__arrowhead{fill:var(--_link)}.fly-gantt__today{stroke:var(--_today);stroke-width:1.5;stroke-dasharray:3 3;pointer-events:none}.fly-gantt__empty,.fly-gantt__overflow{margin:0;padding:12px;color:var(--_text-faint);font-size:12px;text-align:center}.fly-gantt__tooltip{position:fixed;z-index:20;transform:translate(12px,16px);padding:4px 8px;border-radius:6px;background:var(--_text);color:var(--_surface);font-size:12px;white-space:nowrap;pointer-events:none;direction:ltr;unicode-bidi:isolate}\n"] }]
13898
+ }, template: "<!-- Cross-scrolling canvas: a CSS grid whose header row and label column are sticky, so the\r\n time grid scrolls under a pinned header + label tree. All SVG geometry is pre-mirrored for\r\n RTL in the component (see gantt-scale mapX), so this template never branches on direction. -->\r\n<div\r\n class=\"fly-gantt__scroll\"\r\n role=\"grid\"\r\n tabindex=\"0\"\r\n [attr.aria-label]=\"'gantt.aria.grid' | translate\"\r\n [attr.aria-rowcount]=\"visibleRows().length\"\r\n (keydown)=\"onGridKeydown($event)\"\r\n>\r\n <div\r\n class=\"fly-gantt__canvas\"\r\n [style.grid-template-columns]=\"effectiveLabelWidth() + 'px ' + innerWidth() + 'px'\"\r\n [style.grid-template-rows]=\"HEADER_H + 'px ' + bodyHeight() + 'px'\"\r\n >\r\n <!-- \u2500\u2500 Corner (pinned both axes) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"fly-gantt__corner\" [style.height.px]=\"HEADER_H\">\r\n @if (resizableLabels()) {\r\n <!-- The divider lives in the corner because the corner is the one cell pinned on BOTH\r\n axes: the grip stays reachable however far the user has scrolled. The full-height\r\n strip down the label pane below is the same gesture, presentational only. -->\r\n <div\r\n class=\"fly-gantt__splitter\"\r\n role=\"separator\"\r\n tabindex=\"0\"\r\n aria-orientation=\"vertical\"\r\n [attr.aria-label]=\"'gantt.aria.label_resize' | translate\"\r\n [attr.aria-valuenow]=\"effectiveLabelWidth()\"\r\n [attr.aria-valuemin]=\"MIN_LABEL_W\"\r\n [attr.aria-valuemax]=\"MAX_LABEL_W\"\r\n (pointerdown)=\"onLabelResizePointerDown($event)\"\r\n (keydown)=\"onLabelResizeKeydown($event)\"\r\n (dblclick)=\"resetLabelWidth()\"\r\n ></div>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 Time header (pinned top) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <svg\r\n class=\"fly-gantt__time-header\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"HEADER_H\"\r\n [attr.viewBox]=\"'0 0 ' + innerWidth() + ' ' + HEADER_H\"\r\n aria-hidden=\"true\"\r\n >\r\n @for (b of weekendBands(); track b.key) {\r\n <rect class=\"fly-gantt__weekend\" [attr.x]=\"b.x\" [attr.y]=\"HEADER_UPPER_H\" [attr.width]=\"b.width\" [attr.height]=\"HEADER_LOWER_H\" />\r\n }\r\n @for (t of upperTicks(); track t.key) {\r\n <line class=\"fly-gantt__tick-line\" [attr.x1]=\"t.x\" [attr.y1]=\"0\" [attr.x2]=\"t.x\" [attr.y2]=\"HEADER_H\" />\r\n <text class=\"fly-gantt__tick-label fly-gantt__tick-label--upper\" [attr.x]=\"t.x + t.width / 2\" [attr.y]=\"HEADER_UPPER_H / 2 + 4\">{{ t.label }}</text>\r\n }\r\n @for (t of lowerTicks(); track t.key) {\r\n <line class=\"fly-gantt__tick-line\" [attr.x1]=\"t.x\" [attr.y1]=\"HEADER_UPPER_H\" [attr.x2]=\"t.x\" [attr.y2]=\"HEADER_H\" />\r\n <text class=\"fly-gantt__tick-label\" [attr.x]=\"t.x + t.width / 2\" [attr.y]=\"HEADER_UPPER_H + HEADER_LOWER_H / 2 + 4\">{{ t.label }}</text>\r\n }\r\n @if (todayX() !== null) {\r\n <line class=\"fly-gantt__today\" [attr.x1]=\"todayX()\" [attr.y1]=\"HEADER_UPPER_H\" [attr.x2]=\"todayX()\" [attr.y2]=\"HEADER_H\" />\r\n }\r\n </svg>\r\n\r\n <!-- \u2500\u2500 Label tree (pinned inline-start) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"fly-gantt__labels\" role=\"rowgroup\">\r\n @for (vm of rowVms(); track vm.flat.row.id) {\r\n <div\r\n class=\"fly-gantt__label-row\"\r\n role=\"row\"\r\n tabindex=\"-1\"\r\n [class.fly-gantt__label-row--selected]=\"selectedId() === vm.flat.row.id\"\r\n [class.fly-gantt__label-row--tinted]=\"vm.tint !== null\"\r\n [style.height.px]=\"rowHeight()\"\r\n [style.--fly-gantt-row-tint]=\"vm.tint\"\r\n [attr.aria-selected]=\"selectedId() === vm.flat.row.id\"\r\n [attr.aria-label]=\"vm.ariaLabel\"\r\n (click)=\"onRowClick(vm.flat.row.id)\"\r\n (dblclick)=\"onRowDblClick(vm.flat.row.id)\"\r\n (keydown.enter)=\"onLabelRowKeydown($event, vm.flat.row.id)\"\r\n >\r\n <span class=\"fly-gantt__label-inner\" [style.padding-inline-start.px]=\"indentFor(vm.flat.depth)\">\r\n @if (vm.flat.hasChildren) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-gantt__chevron\"\r\n [class.fly-gantt__chevron--collapsed]=\"isCollapsed(vm.flat.row.id)\"\r\n [attr.aria-label]=\"(isCollapsed(vm.flat.row.id) ? 'gantt.expand' : 'gantt.collapse') | translate\"\r\n [attr.aria-expanded]=\"!isCollapsed(vm.flat.row.id)\"\r\n (click)=\"toggleCollapse(vm.flat.row.id, $event)\"\r\n >\u25B8</button>\r\n } @else {\r\n <span class=\"fly-gantt__chevron-spacer\"></span>\r\n }\r\n @if (vm.color) {\r\n <!-- Colour chip: the row's own colour at full strength, so a milestone stays\r\n identifiable in the label pane where the band tint is deliberately faint. -->\r\n <span class=\"fly-gantt__label-swatch\" [style.background]=\"vm.color\" aria-hidden=\"true\"></span>\r\n }\r\n <span\r\n class=\"fly-gantt__label-text\"\r\n [class.fly-gantt__label-text--group]=\"vm.shape === 'group'\"\r\n [title]=\"vm.flat.row.label\"\r\n >{{ vm.flat.row.label }}</span>\r\n </span>\r\n </div>\r\n }\r\n @if (resizableLabels()) {\r\n <!-- aria-hidden so this presentational twin of the corner separator is not a second\r\n (and structurally invalid) child of the rowgroup in the accessibility tree. -->\r\n <div\r\n class=\"fly-gantt__splitter fly-gantt__splitter--rail\"\r\n aria-hidden=\"true\"\r\n (pointerdown)=\"onLabelResizePointerDown($event)\"\r\n (dblclick)=\"resetLabelWidth()\"\r\n ></div>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 Time grid body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <svg\r\n #bodySvg\r\n class=\"fly-gantt__body\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"bodyHeight()\"\r\n [attr.viewBox]=\"'0 0 ' + innerWidth() + ' ' + bodyHeight()\"\r\n >\r\n <defs>\r\n <marker\r\n [attr.id]=\"markerId\"\r\n markerWidth=\"8\"\r\n markerHeight=\"8\"\r\n refX=\"6\"\r\n refY=\"4\"\r\n orient=\"auto\"\r\n markerUnits=\"userSpaceOnUse\"\r\n >\r\n <path class=\"fly-gantt__arrowhead\" d=\"M0,0 L7,4 L0,8 Z\" />\r\n </marker>\r\n </defs>\r\n\r\n <!-- Row colour bands sit at the very bottom of the stack, so the weekend shading and the\r\n gridlines below still read through them. -->\r\n @for (vm of tintedRows(); track vm.flat.row.id) {\r\n <rect\r\n class=\"fly-gantt__row-band\"\r\n [attr.x]=\"0\"\r\n [attr.y]=\"vm.y\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"rowHeight()\"\r\n [style.fill]=\"vm.tint\"\r\n />\r\n }\r\n\r\n <!-- Weekend shading + vertical gridlines (behind the bars). -->\r\n @for (b of weekendBands(); track b.key) {\r\n <rect class=\"fly-gantt__weekend\" [attr.x]=\"b.x\" [attr.y]=\"0\" [attr.width]=\"b.width\" [attr.height]=\"bodyHeight()\" />\r\n }\r\n @for (t of lowerTicks(); track t.key) {\r\n <line class=\"fly-gantt__grid-line\" [attr.x1]=\"t.x\" [attr.y1]=\"0\" [attr.x2]=\"t.x\" [attr.y2]=\"bodyHeight()\" />\r\n }\r\n\r\n <!-- Rows: a full-width hit rect (click + link drop target) then the shape. -->\r\n @for (vm of rowVms(); track vm.flat.row.id) {\r\n <g class=\"fly-gantt__row\" [attr.data-row-id]=\"vm.flat.row.id\">\r\n <rect\r\n class=\"fly-gantt__row-hit\"\r\n [class.fly-gantt__row-hit--selected]=\"selectedId() === vm.flat.row.id\"\r\n [attr.x]=\"0\"\r\n [attr.y]=\"vm.y\"\r\n [attr.width]=\"innerWidth()\"\r\n [attr.height]=\"rowHeight()\"\r\n (pointerdown)=\"onRowClick(vm.flat.row.id)\"\r\n (dblclick)=\"onRowDblClick(vm.flat.row.id)\"\r\n />\r\n\r\n @switch (vm.shape) {\r\n @case ('group') {\r\n <path class=\"fly-gantt__group\" [attr.d]=\"groupPath(vm)\" [style.fill]=\"vm.color\" [style.stroke]=\"vm.color\" />\r\n }\r\n @case ('milestone') {\r\n <polygon\r\n class=\"fly-gantt__milestone\"\r\n [class.fly-gantt__milestone--editable]=\"vm.editable\"\r\n [attr.points]=\"diamondPoints(vm)\"\r\n [style.fill]=\"vm.color\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'move')\"\r\n />\r\n @if (!readonly() && !vm.flat.row.readonly) {\r\n <!-- A diamond has no width, so one connector serves it; it reads as the finish\r\n end, which is what makes a milestone\u2192task drag the FS everyone expects. -->\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"milestoneConnectorX(vm)\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'finish')\"\r\n />\r\n }\r\n }\r\n @case ('bar') {\r\n <g class=\"fly-gantt__bar-group\">\r\n <rect\r\n class=\"fly-gantt__bar\"\r\n [class.fly-gantt__bar--editable]=\"vm.editable\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"vm.width\"\r\n [attr.height]=\"barHeight()\"\r\n rx=\"4\"\r\n [style.fill]=\"vm.color\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'move')\"\r\n />\r\n @if (vm.progressWidth > 0) {\r\n <rect\r\n class=\"fly-gantt__progress\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"vm.progressWidth\"\r\n [attr.height]=\"barHeight()\"\r\n rx=\"4\"\r\n />\r\n }\r\n @if (vm.editable) {\r\n <!-- Resize handles at both edges. -->\r\n <rect\r\n class=\"fly-gantt__handle\"\r\n [attr.x]=\"vm.x\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"HANDLE_W\"\r\n [attr.height]=\"barHeight()\"\r\n [attr.aria-label]=\"'gantt.aria.resize_start' | translate\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'resize-start')\"\r\n />\r\n <rect\r\n class=\"fly-gantt__handle\"\r\n [attr.x]=\"vm.x + vm.width - HANDLE_W\"\r\n [attr.y]=\"barTop(vm)\"\r\n [attr.width]=\"HANDLE_W\"\r\n [attr.height]=\"barHeight()\"\r\n [attr.aria-label]=\"'gantt.aria.resize_end' | translate\"\r\n (pointerdown)=\"onBarPointerDown($event, vm, 'resize-end')\"\r\n />\r\n }\r\n @if (!readonly() && !vm.flat.row.readonly) {\r\n <!-- One connector per END. Dragging from the start edge yields an SS/SF link\r\n and from the finish edge an FS/FF one \u2014 the drop edge picks which. -->\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"vm.startX\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle_start' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'start')\"\r\n />\r\n <circle\r\n class=\"fly-gantt__connector\"\r\n [attr.cx]=\"vm.endX\"\r\n [attr.cy]=\"vm.midY\"\r\n r=\"4\"\r\n [attr.aria-label]=\"'gantt.aria.link_handle' | translate: { label: vm.flat.row.label }\"\r\n (pointerdown)=\"onLinkPointerDown($event, vm, 'finish')\"\r\n />\r\n }\r\n </g>\r\n }\r\n }\r\n </g>\r\n }\r\n\r\n <!-- Dependency arrows (skipped for missing / collapsed endpoints). Each carries a fat\r\n transparent twin so a 1.5px line is still clickable at pointer precision. -->\r\n @for (link of linkVms(); track link.key) {\r\n <g class=\"fly-gantt__link-group\" [class.fly-gantt__link-group--selected]=\"selectedLinkKey() === link.key\">\r\n <path\r\n class=\"fly-gantt__link-hit\"\r\n [attr.d]=\"link.path\"\r\n [attr.aria-label]=\"link.ariaLabel\"\r\n (click)=\"onLinkClick($event, link)\"\r\n />\r\n <path class=\"fly-gantt__link\" [attr.d]=\"link.path\" [attr.marker-end]=\"'url(#' + markerId + ')'\" />\r\n @if (selectedLinkKey() === link.key && !readonly()) {\r\n <g\r\n class=\"fly-gantt__link-delete\"\r\n [attr.transform]=\"'translate(' + link.badgeX + ',' + link.badgeY + ')'\"\r\n [attr.aria-label]=\"'gantt.aria.delete_link' | translate\"\r\n (click)=\"deleteLink($event, link)\"\r\n >\r\n <circle class=\"fly-gantt__link-delete-bg\" r=\"8\" />\r\n <path class=\"fly-gantt__link-delete-x\" d=\"M-3.5,-3.5 L3.5,3.5 M3.5,-3.5 L-3.5,3.5\" />\r\n </g>\r\n }\r\n </g>\r\n }\r\n\r\n <!-- In-flight link rubber band. -->\r\n @if (linkGesturePath(); as gp) {\r\n <path class=\"fly-gantt__link fly-gantt__link--ghost\" [attr.d]=\"gp\" [attr.marker-end]=\"'url(#' + markerId + ')'\" />\r\n }\r\n\r\n <!-- Today line (over the bars). -->\r\n @if (todayX() !== null) {\r\n <line class=\"fly-gantt__today\" [attr.x1]=\"todayX()\" [attr.y1]=\"0\" [attr.x2]=\"todayX()\" [attr.y2]=\"bodyHeight()\" />\r\n }\r\n </svg>\r\n </div>\r\n\r\n @if (visibleRows().length === 0) {\r\n <p class=\"fly-gantt__empty\">{{ 'gantt.no_data' | translate }}</p>\r\n }\r\n @if (overflowCount() > 0) {\r\n <p class=\"fly-gantt__overflow\">\r\n {{ 'gantt.overflow' | translate: { shown: maxRows(), total: maxRows() + overflowCount() } }}\r\n </p>\r\n }\r\n</div>\r\n\r\n<!-- Drag candidate tooltip (HTML overlay, follows the cursor). -->\r\n@if (dragTooltip(); as tip) {\r\n <div class=\"fly-gantt__tooltip\" [style.left.px]=\"tip.x\" [style.top.px]=\"tip.y\">{{ tip.text }}</div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--bg-2, var(--surface-card, #fff));--_surface-alt: var(--bg-3, var(--glass-bg-elevated, #f8fafc));--_surface-hover: var(--bg-hover, var(--surface-hover, #f1f5f9));--_border: var(--w08, var(--surface-border, #e2e8f0));--_border-strong: var(--w1, var(--surface-border, #cbd5e1));--_grid-line: var(--line-3, var(--surface-border, #eef2f7));--_text: var(--ink, var(--text-color, #0f172a));--_text-subtle: var(--ink-3, var(--text-color-secondary, #64748b));--_text-faint: var(--ink-4, var(--text-color-secondary, #94a3b8));--_accent: var(--accent);--_bar: var(--_accent);--_bar-progress: color-mix(in srgb, var(--_accent) 72%, #000);--_weekend: color-mix(in srgb, var(--_text-subtle) 9%, transparent);--_today: var(--danger, #ef4444);--_link: var(--_text-subtle);--_radius: var(--r-lg, 8px);--_transition: var(--t-state, .12s ease);display:block;inline-size:100%;block-size:100%;min-block-size:200px;color:var(--_text);font-size:13px}:host(.fly-gantt--resizing){cursor:col-resize;-webkit-user-select:none;user-select:none}.fly-gantt__scroll{position:relative;inline-size:100%;block-size:100%;overflow:auto;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);box-shadow:var(--shadow-card, none);outline:none}.fly-gantt__scroll:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:-2px}.fly-gantt__canvas{display:grid;position:relative}.fly-gantt__corner{position:sticky;inset-block-start:0;inset-inline-start:0;z-index:4;background:var(--_surface-alt);-webkit-backdrop-filter:blur(12px) saturate(140%);backdrop-filter:blur(12px) saturate(140%);border-inline-end:1px solid var(--_border);border-block-end:1px solid var(--_border-strong)}.fly-gantt__time-header{position:sticky;inset-block-start:0;z-index:3;display:block;background:var(--_surface-alt);-webkit-backdrop-filter:blur(12px) saturate(140%);backdrop-filter:blur(12px) saturate(140%);border-block-end:1px solid var(--_border-strong)}.fly-gantt__tick-line{stroke:var(--_grid-line);stroke-width:1}.fly-gantt__tick-label{fill:var(--_text-subtle);font-size:11px;text-anchor:middle;dominant-baseline:middle}.fly-gantt__tick-label--upper{fill:var(--_text);font-weight:600}.fly-gantt__splitter{position:absolute;inset-block:0;inset-inline-end:-3px;inline-size:7px;z-index:5;cursor:col-resize;touch-action:none}.fly-gantt__splitter:after{content:\"\";position:absolute;inset-block:0;inset-inline-start:3px;inline-size:1px;background:transparent;transition:background var(--_transition)}.fly-gantt__splitter:hover:after,.fly-gantt__splitter:focus-visible:after{background:var(--_accent)}.fly-gantt__splitter:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:-1px}:host(.fly-gantt--resizing) .fly-gantt__splitter:after{background:var(--_accent)}.fly-gantt__labels{position:sticky;inset-inline-start:0;z-index:2;background:var(--_surface);border-inline-end:1px solid var(--_border)}.fly-gantt__label-row{position:relative;display:flex;align-items:center;border-block-end:1px solid var(--_grid-line);cursor:pointer;transition:background var(--_transition)}.fly-gantt__label-row:hover{background:var(--_surface-hover)}.fly-gantt__label-row--selected{background:var(--_surface-hover);box-shadow:inset 3px 0 0 0 var(--_accent)}.fly-gantt__label-row--tinted:before{content:\"\";position:absolute;inset:0;background:var(--fly-gantt-row-tint);pointer-events:none}.fly-gantt__label-inner{position:relative;display:flex;align-items:center;gap:4px;inline-size:100%;min-inline-size:0;padding-inline-end:8px}.fly-gantt__label-swatch{flex:0 0 auto;inline-size:8px;block-size:8px;border-radius:2px}.fly-gantt__chevron{flex:0 0 auto;inline-size:18px;block-size:18px;padding:0;border:none;background:transparent;color:var(--_text-subtle);cursor:pointer;line-height:1;transform:rotate(90deg);transition:transform var(--_transition)}.fly-gantt__chevron--collapsed{transform:rotate(0)}:host(.fly-gantt--rtl) .fly-gantt__chevron--collapsed{transform:rotate(180deg)}.fly-gantt__chevron:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:1px;border-radius:4px}.fly-gantt__chevron-spacer{flex:0 0 auto;inline-size:18px}.fly-gantt__label-text{min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-gantt__label-text--group{font-weight:600}.fly-gantt__body{display:block;touch-action:pan-x pan-y}.fly-gantt__row-band{pointer-events:none}.fly-gantt__weekend{fill:var(--_weekend)}.fly-gantt__grid-line{stroke:var(--_grid-line);stroke-width:1}.fly-gantt__row-hit{fill:transparent}.fly-gantt__row-hit--selected{fill:var(--_surface-hover)}.fly-gantt__bar{fill:var(--_bar);stroke:none}.fly-gantt__bar--editable{cursor:grab}.fly-gantt__progress{fill:var(--_bar-progress);pointer-events:none}.fly-gantt__handle{fill:transparent;cursor:ew-resize}.fly-gantt__connector{fill:var(--_surface);stroke:var(--_accent);stroke-width:1.5;cursor:crosshair;opacity:0;transition:opacity var(--_transition)}.fly-gantt__row:hover .fly-gantt__connector{opacity:1}.fly-gantt__milestone{fill:var(--_accent);stroke:var(--_surface);stroke-width:1}.fly-gantt__milestone--editable{cursor:grab}.fly-gantt__group{fill:var(--_text-subtle);stroke:var(--_text-subtle)}.fly-gantt__link{fill:none;stroke:var(--_link);stroke-width:1.5;pointer-events:none}.fly-gantt__link-hit{fill:none;stroke:transparent;stroke-width:11;pointer-events:stroke;cursor:pointer}.fly-gantt__link-group:hover .fly-gantt__link{stroke:var(--_text)}.fly-gantt__link-group--selected .fly-gantt__link{stroke:var(--_accent);stroke-width:2.5}.fly-gantt__link-delete-bg{fill:var(--_accent)}.fly-gantt__link-delete{cursor:pointer}.fly-gantt__link-delete-x{stroke:var(--_surface);stroke-width:1.75;stroke-linecap:round;fill:none;pointer-events:none}.fly-gantt__link--ghost{stroke-dasharray:4 3;opacity:.8}.fly-gantt__arrowhead{fill:var(--_link)}.fly-gantt__today{stroke:var(--_today);stroke-width:1.5;stroke-dasharray:3 3;pointer-events:none}.fly-gantt__empty,.fly-gantt__overflow{margin:0;padding:12px;color:var(--_text-faint);font-size:12px;text-align:center}.fly-gantt__tooltip{position:fixed;z-index:20;transform:translate(12px,16px);padding:4px 8px;border-radius:6px;background:var(--_text);color:var(--_surface);font-size:12px;white-space:nowrap;pointer-events:none;direction:ltr;unicode-bidi:isolate}\n"] }]
13899
13899
  }], propDecorators: { rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], dependencies: [{ type: i0.Input, args: [{ isSignal: true, alias: "dependencies", required: false }] }], zoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoom", required: false }] }], showToday: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToday", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], labelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelWidth", required: false }] }], resizableLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizableLabels", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }], rowDatesChange: [{ type: i0.Output, args: ["rowDatesChange"] }], dependencyCreate: [{ type: i0.Output, args: ["dependencyCreate"] }], dependencyDelete: [{ type: i0.Output, args: ["dependencyDelete"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowDblClick: [{ type: i0.Output, args: ["rowDblClick"] }], labelWidthChange: [{ type: i0.Output, args: ["labelWidthChange"] }], bodyRef: [{ type: i0.ViewChild, args: ['bodySvg', { isSignal: true }] }] } });
13900
13900
 
13901
13901
  // ── Bundled ISO 3166-1 country list ──────────────────────────────────────────
@@ -14662,7 +14662,7 @@ class FlyDynamicFormComponent {
14662
14662
  return this._i18n.t(key, params);
14663
14663
  }
14664
14664
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyDynamicFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
14665
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyDynamicFormComponent, isStandalone: true, selector: "fly-dynamic-form, fly-survey-form", inputs: { definition: { classPropertyName: "definition", publicName: "definition", isSignal: true, isRequired: true, transformFunction: null }, isReadonly: { classPropertyName: "isReadonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, hideSubmit: { classPropertyName: "hideSubmit", publicName: "hideSubmit", isSignal: true, isRequired: false, transformFunction: null }, answers: { classPropertyName: "answers", publicName: "answers", isSignal: true, isRequired: false, transformFunction: null }, showScore: { classPropertyName: "showScore", publicName: "showScore", isSignal: true, isRequired: false, transformFunction: null }, scoreDisplay: { classPropertyName: "scoreDisplay", publicName: "scoreDisplay", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { answersChange: "answersChange", validityChange: "validityChange", submit: "submit", fileSelected: "fileSelected" }, host: { properties: { "class.fly-dynamic-form--readonly": "isReadonly()", "class.fly-survey-form--readonly": "isReadonly()" }, classAttribute: "fly-dynamic-form fly-survey-form" }, ngImport: i0, template: "<div class=\"fly-dynamic-form__body\">\r\n <header class=\"fly-dynamic-form__header\">\r\n <h2 class=\"fly-dynamic-form__title\">{{ definition().title }}</h2>\r\n @if (definition().description) {\r\n <p class=\"fly-dynamic-form__description\">{{ definition().description }}</p>\r\n }\r\n </header>\r\n\r\n <div class=\"fly-dynamic-form__fields\">\r\n @for (grp of groupedQuestions(); track $index) {\r\n @if (grp.group) {\r\n <fieldset class=\"fly-dynamic-form__section\">\r\n <legend class=\"fly-dynamic-form__section-title\">{{ grp.group }}</legend>\r\n @for (item of grp.items; track item.q.id) {\r\n <ng-container *ngTemplateOutlet=\"fieldTpl; context: { q: item.q, i: item.index }\" />\r\n }\r\n </fieldset>\r\n } @else {\r\n @for (item of grp.items; track item.q.id) {\r\n <ng-container *ngTemplateOutlet=\"fieldTpl; context: { q: item.q, i: item.index }\" />\r\n }\r\n }\r\n }\r\n </div>\r\n\r\n <ng-template #fieldTpl let-q=\"q\" let-i=\"i\">\r\n <div class=\"fly-dynamic-form__field\" [class.fly-dynamic-form__field--invalid]=\"showError(q)\">\r\n\r\n <!-- \u2500\u2500 Native input group (RadioButton / MultipleSelect) \u2500\u2500 -->\r\n @if (isFieldset(q.type)) {\r\n <fieldset\r\n class=\"fly-dynamic-form__group\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\">\r\n <legend class=\"fly-dynamic-form__label\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </legend>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n\r\n @switch (q.type) {\r\n @case ('RadioButton') {\r\n <div class=\"fly-dynamic-form__options\">\r\n @for (opt of q.options; track opt.id) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"fieldId(i)\"\r\n [value]=\"opt.id\"\r\n [checked]=\"isSelected(q, opt.id)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onRadio(q, opt.id)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ opt.label }}</span>\r\n @if (optionScore(opt) !== null) {\r\n <span class=\"fly-dynamic-form__option-score\" [class.fly-dynamic-form__option-score--inline]=\"scoreDisplay() === 'inline'\">{{ optionScore(opt) }}</span>\r\n }\r\n </label>\r\n }\r\n </div>\r\n }\r\n @case ('MultipleSelect') {\r\n <div class=\"fly-dynamic-form__options\">\r\n @for (opt of q.options; track opt.id) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"checkbox\"\r\n [value]=\"opt.id\"\r\n [checked]=\"isSelected(q, opt.id)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onMultiToggle(q, opt.id, $any($event.target).checked)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ opt.label }}</span>\r\n @if (optionScore(opt) !== null) {\r\n <span class=\"fly-dynamic-form__option-score\" [class.fly-dynamic-form__option-score--inline]=\"scoreDisplay() === 'inline'\">{{ optionScore(opt) }}</span>\r\n }\r\n </label>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n </fieldset>\r\n }\r\n\r\n <!-- \u2500\u2500 Boolean \u2192 segmented Yes / No radiogroup (not a toggle) \u2500\u2500 -->\r\n @else if (q.type === 'Boolean') {\r\n <span class=\"fly-dynamic-form__label\" [id]=\"fieldId(i) + '-lbl'\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </span>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n <div\r\n class=\"fly-dynamic-form__segmented\"\r\n role=\"radiogroup\"\r\n [attr.aria-labelledby]=\"fieldId(i) + '-lbl'\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__seg\"\r\n role=\"radio\"\r\n [class.fly-dynamic-form__seg--on]=\"boolValue(q) === true\"\r\n [attr.aria-checked]=\"boolValue(q) === true\"\r\n [disabled]=\"isReadonly()\"\r\n (click)=\"onBoolean(q, true)\">\r\n {{ 'form.yes' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__seg\"\r\n role=\"radio\"\r\n [class.fly-dynamic-form__seg--on]=\"boolValue(q) === false\"\r\n [attr.aria-checked]=\"boolValue(q) === false\"\r\n [disabled]=\"isReadonly()\"\r\n (click)=\"onBoolean(q, false)\">\r\n {{ 'form.no' | translate }}\r\n </button>\r\n </div>\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n }\r\n\r\n <!-- \u2500\u2500 Searchable DS single-select (SingleSelect+hasSearch / Country) \u2500\u2500 -->\r\n @else if (usesDsSelect(q)) {\r\n <span class=\"fly-dynamic-form__label\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </span>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n <fly-select\r\n [options]=\"isCountry(q.type) ? countryOptions(q) : selectOptions(q)\"\r\n [multiple]=\"false\"\r\n [searchable]=\"selectSearchable(q)\"\r\n [clearable]=\"!q.required\"\r\n [disabled]=\"isReadonly()\"\r\n [ariaLabel]=\"q.text\"\r\n [placeholder]=\"'form.select_placeholder' | translate\"\r\n [searchPlaceholder]=\"(isCountry(q.type) ? 'form.country_search' : 'form.search_placeholder') | translate\"\r\n [noResultsLabel]=\"'form.no_results' | translate\"\r\n [ngModel]=\"singleValue(q)\"\r\n (selectionChange)=\"onSingleSelect(q, $event)\" />\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n }\r\n\r\n <!-- \u2500\u2500 Single labelled native control \u2500\u2500 -->\r\n @else {\r\n <label class=\"fly-dynamic-form__label\" [for]=\"fieldId(i)\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </label>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n\r\n @switch (q.type) {\r\n @case ('Text') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"text\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [attr.minlength]=\"q.fieldOptions?.minLength ?? null\"\r\n [attr.maxlength]=\"q.fieldOptions?.maxLength ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\" />\r\n }\r\n @case ('MultilineText') {\r\n <textarea\r\n class=\"fly-dynamic-form__input fly-dynamic-form__textarea\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [rows]=\"q.fieldOptions?.rows ?? 4\"\r\n [attr.minlength]=\"q.fieldOptions?.minLength ?? null\"\r\n [attr.maxlength]=\"q.fieldOptions?.maxLength ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\"></textarea>\r\n }\r\n @case ('Number') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"number\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"numberValue(q)\"\r\n [attr.min]=\"q.fieldOptions?.numericMin ?? null\"\r\n [attr.max]=\"q.fieldOptions?.numericMax ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onNumber(q, $any($event.target).value)\" />\r\n }\r\n @case ('Email') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"email\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\" />\r\n }\r\n @case ('Date') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"date\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"dateValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onDate(q, $any($event.target).value)\" />\r\n }\r\n @case ('DateTime') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"datetime-local\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"dateValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onDate(q, $any($event.target).value)\" />\r\n }\r\n @case ('File') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #fileRef\r\n type=\"file\"\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, fileRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n @case ('Image') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #imgRef\r\n type=\"file\"\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, imgRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n @case ('MultiFile') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #multiRef\r\n type=\"file\"\r\n multiple\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, multiRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n @if (fileError(q)) {\r\n <p class=\"fly-dynamic-form__error\" role=\"alert\">{{ fileError(q) }}</p>\r\n }\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (definition().declaration; as decl) {\r\n <div class=\"fly-dynamic-form__declaration\">\r\n <p class=\"fly-dynamic-form__declaration-text\">{{ decl }}</p>\r\n @if (!isReadonly()) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"declarationAccepted()\"\r\n (change)=\"onDeclarationToggle($any($event.target).checked)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ 'form.declaration_accept' | translate }}</span>\r\n </label>\r\n }\r\n </div>\r\n }\r\n\r\n @if (!isReadonly() && !hideSubmit()) {\r\n <div class=\"fly-dynamic-form__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__submit\"\r\n [disabled]=\"!canSubmit()\"\r\n (click)=\"onSubmit()\">\r\n {{ 'form.submit' | translate }}\r\n </button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-dynamic-form__body{display:flex;flex-direction:column;gap:20px}.fly-dynamic-form__header{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__title{margin:0;font-size:18px;font-weight:700;color:var(--_text)}.fly-dynamic-form__description{margin:0;color:var(--_text-subtle);line-height:1.5}.fly-dynamic-form__fields{display:flex;flex-direction:column;gap:18px}.fly-dynamic-form__section{display:flex;flex-direction:column;gap:18px;margin:0;padding:16px;border:1px solid var(--_border);border-radius:var(--_radius);min-inline-size:0;background:var(--_surface)}.fly-dynamic-form__section-title{padding:0 6px;font-size:13px;font-weight:700;color:var(--_text)}.fly-dynamic-form__field{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__group{display:flex;flex-direction:column;gap:6px;margin:0;padding:0;border:none;min-inline-size:0}.fly-dynamic-form__label{font-weight:600;color:var(--_text)}.fly-dynamic-form__req{color:var(--_danger);margin-inline-start:2px}.fly-dynamic-form__desc{margin:0;font-size:12px;color:var(--_text-subtle);line-height:1.45}.fly-dynamic-form__error{margin:0;font-size:12px;color:var(--_danger)}.fly-dynamic-form__input{inline-size:100%;min-block-size:2.25rem;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-dynamic-form__textarea{min-block-size:5rem;resize:vertical;line-height:1.5}.fly-dynamic-form__input:focus-visible{outline:2px solid var(--_accent);outline-offset:1px}.fly-dynamic-form__input:disabled{opacity:.6;cursor:not-allowed}.fly-dynamic-form__field--invalid .fly-dynamic-form__input{border-color:var(--_danger)}.fly-dynamic-form__options{display:flex;flex-direction:column;gap:8px}.fly-dynamic-form__option{display:flex;align-items:center;gap:8px;cursor:pointer;color:var(--_text)}.fly-dynamic-form__option input{inline-size:1rem;block-size:1rem;accent-color:var(--_accent);cursor:pointer}.fly-dynamic-form__option input:disabled{cursor:not-allowed}.fly-dynamic-form__option-label{line-height:1.3}.fly-dynamic-form__option-score{margin-inline-start:auto;padding:1px 8px;border-radius:999px;background:var(--_fill);color:var(--_text-subtle);font-size:11px;font-weight:700;font-variant-numeric:tabular-nums}.fly-dynamic-form__option-score--inline{margin-inline-start:6px;padding:0;border-radius:0;background:transparent}.fly-dynamic-form__segmented{display:inline-flex;align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);overflow:hidden;background:var(--_surface)}.fly-dynamic-form__seg{min-inline-size:4.5rem;padding:7px 16px;border:none;border-inline-end:1px solid var(--_border);background:transparent;color:var(--_text-subtle);font:inherit;font-weight:600;cursor:pointer;transition:background .12s ease,color .12s ease}.fly-dynamic-form__seg:last-child{border-inline-end:none}.fly-dynamic-form__seg:hover:not(:disabled){background:var(--_surface-hover)}.fly-dynamic-form__seg--on{background:var(--_accent);color:#fff}.fly-dynamic-form__seg:focus-visible{outline:2px solid var(--_accent);outline-offset:-2px}.fly-dynamic-form__seg:disabled{opacity:.6;cursor:not-allowed}.fly-dynamic-form__file{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__file-input{font:inherit;color:var(--_text-subtle)}.fly-dynamic-form__file-list{margin:0;padding-inline-start:18px;color:var(--_text-subtle);font-size:12px}.fly-dynamic-form__declaration{display:flex;flex-direction:column;gap:10px;padding:14px 16px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_fill)}.fly-dynamic-form__declaration-text{margin:0;color:var(--_text-subtle);line-height:1.5}.fly-dynamic-form__actions{display:flex;justify-content:flex-end}.fly-dynamic-form__submit{padding:9px 22px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer;transition:opacity .12s ease}.fly-dynamic-form__submit:hover:not(:disabled){opacity:.9}.fly-dynamic-form__submit:focus-visible{outline:2px solid var(--_accent);outline-offset:2px}.fly-dynamic-form__submit:disabled{opacity:.5;cursor:not-allowed}\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.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: "component", type: FlySelectComponent, selector: "fly-select", inputs: ["options", "multiple", "searchable", "clearable", "showSelectAll", "disabled", "placeholder", "searchPlaceholder", "noResultsLabel", "selectAllLabel", "deselectAllLabel", "clearLabel", "summaryFormatter", "ariaLabel"], outputs: ["selectionChange", "openedChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
14665
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyDynamicFormComponent, isStandalone: true, selector: "fly-dynamic-form, fly-survey-form", inputs: { definition: { classPropertyName: "definition", publicName: "definition", isSignal: true, isRequired: true, transformFunction: null }, isReadonly: { classPropertyName: "isReadonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, hideSubmit: { classPropertyName: "hideSubmit", publicName: "hideSubmit", isSignal: true, isRequired: false, transformFunction: null }, answers: { classPropertyName: "answers", publicName: "answers", isSignal: true, isRequired: false, transformFunction: null }, showScore: { classPropertyName: "showScore", publicName: "showScore", isSignal: true, isRequired: false, transformFunction: null }, scoreDisplay: { classPropertyName: "scoreDisplay", publicName: "scoreDisplay", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { answersChange: "answersChange", validityChange: "validityChange", submit: "submit", fileSelected: "fileSelected" }, host: { properties: { "class.fly-dynamic-form--readonly": "isReadonly()", "class.fly-survey-form--readonly": "isReadonly()" }, classAttribute: "fly-dynamic-form fly-survey-form" }, ngImport: i0, template: "<div class=\"fly-dynamic-form__body\">\r\n <header class=\"fly-dynamic-form__header\">\r\n <h2 class=\"fly-dynamic-form__title\">{{ definition().title }}</h2>\r\n @if (definition().description) {\r\n <p class=\"fly-dynamic-form__description\">{{ definition().description }}</p>\r\n }\r\n </header>\r\n\r\n <div class=\"fly-dynamic-form__fields\">\r\n @for (grp of groupedQuestions(); track $index) {\r\n @if (grp.group) {\r\n <fieldset class=\"fly-dynamic-form__section\">\r\n <legend class=\"fly-dynamic-form__section-title\">{{ grp.group }}</legend>\r\n @for (item of grp.items; track item.q.id) {\r\n <ng-container *ngTemplateOutlet=\"fieldTpl; context: { q: item.q, i: item.index }\" />\r\n }\r\n </fieldset>\r\n } @else {\r\n @for (item of grp.items; track item.q.id) {\r\n <ng-container *ngTemplateOutlet=\"fieldTpl; context: { q: item.q, i: item.index }\" />\r\n }\r\n }\r\n }\r\n </div>\r\n\r\n <ng-template #fieldTpl let-q=\"q\" let-i=\"i\">\r\n <div class=\"fly-dynamic-form__field\" [class.fly-dynamic-form__field--invalid]=\"showError(q)\">\r\n\r\n <!-- \u2500\u2500 Native input group (RadioButton / MultipleSelect) \u2500\u2500 -->\r\n @if (isFieldset(q.type)) {\r\n <fieldset\r\n class=\"fly-dynamic-form__group\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\">\r\n <legend class=\"fly-dynamic-form__label\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </legend>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n\r\n @switch (q.type) {\r\n @case ('RadioButton') {\r\n <div class=\"fly-dynamic-form__options\">\r\n @for (opt of q.options; track opt.id) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"fieldId(i)\"\r\n [value]=\"opt.id\"\r\n [checked]=\"isSelected(q, opt.id)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onRadio(q, opt.id)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ opt.label }}</span>\r\n @if (optionScore(opt) !== null) {\r\n <span class=\"fly-dynamic-form__option-score\" [class.fly-dynamic-form__option-score--inline]=\"scoreDisplay() === 'inline'\">{{ optionScore(opt) }}</span>\r\n }\r\n </label>\r\n }\r\n </div>\r\n }\r\n @case ('MultipleSelect') {\r\n <div class=\"fly-dynamic-form__options\">\r\n @for (opt of q.options; track opt.id) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"checkbox\"\r\n [value]=\"opt.id\"\r\n [checked]=\"isSelected(q, opt.id)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onMultiToggle(q, opt.id, $any($event.target).checked)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ opt.label }}</span>\r\n @if (optionScore(opt) !== null) {\r\n <span class=\"fly-dynamic-form__option-score\" [class.fly-dynamic-form__option-score--inline]=\"scoreDisplay() === 'inline'\">{{ optionScore(opt) }}</span>\r\n }\r\n </label>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n </fieldset>\r\n }\r\n\r\n <!-- \u2500\u2500 Boolean \u2192 segmented Yes / No radiogroup (not a toggle) \u2500\u2500 -->\r\n @else if (q.type === 'Boolean') {\r\n <span class=\"fly-dynamic-form__label\" [id]=\"fieldId(i) + '-lbl'\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </span>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n <div\r\n class=\"fly-dynamic-form__segmented\"\r\n role=\"radiogroup\"\r\n [attr.aria-labelledby]=\"fieldId(i) + '-lbl'\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__seg\"\r\n role=\"radio\"\r\n [class.fly-dynamic-form__seg--on]=\"boolValue(q) === true\"\r\n [attr.aria-checked]=\"boolValue(q) === true\"\r\n [disabled]=\"isReadonly()\"\r\n (click)=\"onBoolean(q, true)\">\r\n {{ 'form.yes' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__seg\"\r\n role=\"radio\"\r\n [class.fly-dynamic-form__seg--on]=\"boolValue(q) === false\"\r\n [attr.aria-checked]=\"boolValue(q) === false\"\r\n [disabled]=\"isReadonly()\"\r\n (click)=\"onBoolean(q, false)\">\r\n {{ 'form.no' | translate }}\r\n </button>\r\n </div>\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n }\r\n\r\n <!-- \u2500\u2500 Searchable DS single-select (SingleSelect+hasSearch / Country) \u2500\u2500 -->\r\n @else if (usesDsSelect(q)) {\r\n <span class=\"fly-dynamic-form__label\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </span>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n <fly-select\r\n [options]=\"isCountry(q.type) ? countryOptions(q) : selectOptions(q)\"\r\n [multiple]=\"false\"\r\n [searchable]=\"selectSearchable(q)\"\r\n [clearable]=\"!q.required\"\r\n [disabled]=\"isReadonly()\"\r\n [ariaLabel]=\"q.text\"\r\n [placeholder]=\"'form.select_placeholder' | translate\"\r\n [searchPlaceholder]=\"(isCountry(q.type) ? 'form.country_search' : 'form.search_placeholder') | translate\"\r\n [noResultsLabel]=\"'form.no_results' | translate\"\r\n [ngModel]=\"singleValue(q)\"\r\n (selectionChange)=\"onSingleSelect(q, $event)\" />\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n }\r\n\r\n <!-- \u2500\u2500 Single labelled native control \u2500\u2500 -->\r\n @else {\r\n <label class=\"fly-dynamic-form__label\" [for]=\"fieldId(i)\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </label>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n\r\n @switch (q.type) {\r\n @case ('Text') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"text\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [attr.minlength]=\"q.fieldOptions?.minLength ?? null\"\r\n [attr.maxlength]=\"q.fieldOptions?.maxLength ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\" />\r\n }\r\n @case ('MultilineText') {\r\n <textarea\r\n class=\"fly-dynamic-form__input fly-dynamic-form__textarea\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [rows]=\"q.fieldOptions?.rows ?? 4\"\r\n [attr.minlength]=\"q.fieldOptions?.minLength ?? null\"\r\n [attr.maxlength]=\"q.fieldOptions?.maxLength ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\"></textarea>\r\n }\r\n @case ('Number') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"number\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"numberValue(q)\"\r\n [attr.min]=\"q.fieldOptions?.numericMin ?? null\"\r\n [attr.max]=\"q.fieldOptions?.numericMax ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onNumber(q, $any($event.target).value)\" />\r\n }\r\n @case ('Email') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"email\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\" />\r\n }\r\n @case ('Date') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"date\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"dateValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onDate(q, $any($event.target).value)\" />\r\n }\r\n @case ('DateTime') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"datetime-local\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"dateValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onDate(q, $any($event.target).value)\" />\r\n }\r\n @case ('File') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #fileRef\r\n type=\"file\"\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, fileRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n @case ('Image') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #imgRef\r\n type=\"file\"\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, imgRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n @case ('MultiFile') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #multiRef\r\n type=\"file\"\r\n multiple\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, multiRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n @if (fileError(q)) {\r\n <p class=\"fly-dynamic-form__error\" role=\"alert\">{{ fileError(q) }}</p>\r\n }\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (definition().declaration; as decl) {\r\n <div class=\"fly-dynamic-form__declaration\">\r\n <p class=\"fly-dynamic-form__declaration-text\">{{ decl }}</p>\r\n @if (!isReadonly()) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"declarationAccepted()\"\r\n (change)=\"onDeclarationToggle($any($event.target).checked)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ 'form.declaration_accept' | translate }}</span>\r\n </label>\r\n }\r\n </div>\r\n }\r\n\r\n @if (!isReadonly() && !hideSubmit()) {\r\n <div class=\"fly-dynamic-form__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__submit\"\r\n [disabled]=\"!canSubmit()\"\r\n (click)=\"onSubmit()\">\r\n {{ 'form.submit' | translate }}\r\n </button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-dynamic-form__body{display:flex;flex-direction:column;gap:20px}.fly-dynamic-form__header{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__title{margin:0;font-size:18px;font-weight:700;color:var(--_text)}.fly-dynamic-form__description{margin:0;color:var(--_text-subtle);line-height:1.5}.fly-dynamic-form__fields{display:flex;flex-direction:column;gap:18px}.fly-dynamic-form__section{display:flex;flex-direction:column;gap:18px;margin:0;padding:16px;border:1px solid var(--_border);border-radius:var(--_radius);min-inline-size:0;background:var(--_surface)}.fly-dynamic-form__section-title{padding:0 6px;font-size:13px;font-weight:700;color:var(--_text)}.fly-dynamic-form__field{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__group{display:flex;flex-direction:column;gap:6px;margin:0;padding:0;border:none;min-inline-size:0}.fly-dynamic-form__label{font-weight:600;color:var(--_text)}.fly-dynamic-form__req{color:var(--_danger);margin-inline-start:2px}.fly-dynamic-form__desc{margin:0;font-size:12px;color:var(--_text-subtle);line-height:1.45}.fly-dynamic-form__error{margin:0;font-size:12px;color:var(--_danger)}.fly-dynamic-form__input{inline-size:100%;min-block-size:2.25rem;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-dynamic-form__textarea{min-block-size:5rem;resize:vertical;line-height:1.5}.fly-dynamic-form__input:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:1px}.fly-dynamic-form__input:disabled{opacity:.6;cursor:not-allowed}.fly-dynamic-form__field--invalid .fly-dynamic-form__input{border-color:var(--_danger)}.fly-dynamic-form__options{display:flex;flex-direction:column;gap:8px}.fly-dynamic-form__option{display:flex;align-items:center;gap:8px;cursor:pointer;color:var(--_text)}.fly-dynamic-form__option input{inline-size:1rem;block-size:1rem;accent-color:var(--_accent);cursor:pointer}.fly-dynamic-form__option input:disabled{cursor:not-allowed}.fly-dynamic-form__option-label{line-height:1.3}.fly-dynamic-form__option-score{margin-inline-start:auto;padding:1px 8px;border-radius:999px;background:var(--_fill);color:var(--_text-subtle);font-size:11px;font-weight:700;font-variant-numeric:tabular-nums}.fly-dynamic-form__option-score--inline{margin-inline-start:6px;padding:0;border-radius:0;background:transparent}.fly-dynamic-form__segmented{display:inline-flex;align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);overflow:hidden;background:var(--_surface)}.fly-dynamic-form__seg{min-inline-size:4.5rem;padding:7px 16px;border:none;border-inline-end:1px solid var(--_border);background:transparent;color:var(--_text-subtle);font:inherit;font-weight:600;cursor:pointer;transition:background .12s ease,color .12s ease}.fly-dynamic-form__seg:last-child{border-inline-end:none}.fly-dynamic-form__seg:hover:not(:disabled){background:var(--_surface-hover)}.fly-dynamic-form__seg--on{background:var(--_accent);color:#fff}.fly-dynamic-form__seg:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:-2px}.fly-dynamic-form__seg:disabled{opacity:.6;cursor:not-allowed}.fly-dynamic-form__file{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__file-input{font:inherit;color:var(--_text-subtle)}.fly-dynamic-form__file-list{margin:0;padding-inline-start:18px;color:var(--_text-subtle);font-size:12px}.fly-dynamic-form__declaration{display:flex;flex-direction:column;gap:10px;padding:14px 16px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_fill)}.fly-dynamic-form__declaration-text{margin:0;color:var(--_text-subtle);line-height:1.5}.fly-dynamic-form__actions{display:flex;justify-content:flex-end}.fly-dynamic-form__submit{padding:9px 22px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer;transition:opacity .12s ease}.fly-dynamic-form__submit:hover:not(:disabled){opacity:.9}.fly-dynamic-form__submit:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:2px}.fly-dynamic-form__submit:disabled{opacity:.5;cursor:not-allowed}\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.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: "component", type: FlySelectComponent, selector: "fly-select", inputs: ["options", "multiple", "searchable", "clearable", "showSelectAll", "disabled", "placeholder", "searchPlaceholder", "noResultsLabel", "selectAllLabel", "deselectAllLabel", "clearLabel", "summaryFormatter", "ariaLabel"], outputs: ["selectionChange", "openedChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
14666
14666
  }
14667
14667
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyDynamicFormComponent, decorators: [{
14668
14668
  type: Component,
@@ -14670,7 +14670,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
14670
14670
  class: 'fly-dynamic-form fly-survey-form',
14671
14671
  '[class.fly-dynamic-form--readonly]': 'isReadonly()',
14672
14672
  '[class.fly-survey-form--readonly]': 'isReadonly()',
14673
- }, template: "<div class=\"fly-dynamic-form__body\">\r\n <header class=\"fly-dynamic-form__header\">\r\n <h2 class=\"fly-dynamic-form__title\">{{ definition().title }}</h2>\r\n @if (definition().description) {\r\n <p class=\"fly-dynamic-form__description\">{{ definition().description }}</p>\r\n }\r\n </header>\r\n\r\n <div class=\"fly-dynamic-form__fields\">\r\n @for (grp of groupedQuestions(); track $index) {\r\n @if (grp.group) {\r\n <fieldset class=\"fly-dynamic-form__section\">\r\n <legend class=\"fly-dynamic-form__section-title\">{{ grp.group }}</legend>\r\n @for (item of grp.items; track item.q.id) {\r\n <ng-container *ngTemplateOutlet=\"fieldTpl; context: { q: item.q, i: item.index }\" />\r\n }\r\n </fieldset>\r\n } @else {\r\n @for (item of grp.items; track item.q.id) {\r\n <ng-container *ngTemplateOutlet=\"fieldTpl; context: { q: item.q, i: item.index }\" />\r\n }\r\n }\r\n }\r\n </div>\r\n\r\n <ng-template #fieldTpl let-q=\"q\" let-i=\"i\">\r\n <div class=\"fly-dynamic-form__field\" [class.fly-dynamic-form__field--invalid]=\"showError(q)\">\r\n\r\n <!-- \u2500\u2500 Native input group (RadioButton / MultipleSelect) \u2500\u2500 -->\r\n @if (isFieldset(q.type)) {\r\n <fieldset\r\n class=\"fly-dynamic-form__group\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\">\r\n <legend class=\"fly-dynamic-form__label\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </legend>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n\r\n @switch (q.type) {\r\n @case ('RadioButton') {\r\n <div class=\"fly-dynamic-form__options\">\r\n @for (opt of q.options; track opt.id) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"fieldId(i)\"\r\n [value]=\"opt.id\"\r\n [checked]=\"isSelected(q, opt.id)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onRadio(q, opt.id)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ opt.label }}</span>\r\n @if (optionScore(opt) !== null) {\r\n <span class=\"fly-dynamic-form__option-score\" [class.fly-dynamic-form__option-score--inline]=\"scoreDisplay() === 'inline'\">{{ optionScore(opt) }}</span>\r\n }\r\n </label>\r\n }\r\n </div>\r\n }\r\n @case ('MultipleSelect') {\r\n <div class=\"fly-dynamic-form__options\">\r\n @for (opt of q.options; track opt.id) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"checkbox\"\r\n [value]=\"opt.id\"\r\n [checked]=\"isSelected(q, opt.id)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onMultiToggle(q, opt.id, $any($event.target).checked)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ opt.label }}</span>\r\n @if (optionScore(opt) !== null) {\r\n <span class=\"fly-dynamic-form__option-score\" [class.fly-dynamic-form__option-score--inline]=\"scoreDisplay() === 'inline'\">{{ optionScore(opt) }}</span>\r\n }\r\n </label>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n </fieldset>\r\n }\r\n\r\n <!-- \u2500\u2500 Boolean \u2192 segmented Yes / No radiogroup (not a toggle) \u2500\u2500 -->\r\n @else if (q.type === 'Boolean') {\r\n <span class=\"fly-dynamic-form__label\" [id]=\"fieldId(i) + '-lbl'\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </span>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n <div\r\n class=\"fly-dynamic-form__segmented\"\r\n role=\"radiogroup\"\r\n [attr.aria-labelledby]=\"fieldId(i) + '-lbl'\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__seg\"\r\n role=\"radio\"\r\n [class.fly-dynamic-form__seg--on]=\"boolValue(q) === true\"\r\n [attr.aria-checked]=\"boolValue(q) === true\"\r\n [disabled]=\"isReadonly()\"\r\n (click)=\"onBoolean(q, true)\">\r\n {{ 'form.yes' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__seg\"\r\n role=\"radio\"\r\n [class.fly-dynamic-form__seg--on]=\"boolValue(q) === false\"\r\n [attr.aria-checked]=\"boolValue(q) === false\"\r\n [disabled]=\"isReadonly()\"\r\n (click)=\"onBoolean(q, false)\">\r\n {{ 'form.no' | translate }}\r\n </button>\r\n </div>\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n }\r\n\r\n <!-- \u2500\u2500 Searchable DS single-select (SingleSelect+hasSearch / Country) \u2500\u2500 -->\r\n @else if (usesDsSelect(q)) {\r\n <span class=\"fly-dynamic-form__label\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </span>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n <fly-select\r\n [options]=\"isCountry(q.type) ? countryOptions(q) : selectOptions(q)\"\r\n [multiple]=\"false\"\r\n [searchable]=\"selectSearchable(q)\"\r\n [clearable]=\"!q.required\"\r\n [disabled]=\"isReadonly()\"\r\n [ariaLabel]=\"q.text\"\r\n [placeholder]=\"'form.select_placeholder' | translate\"\r\n [searchPlaceholder]=\"(isCountry(q.type) ? 'form.country_search' : 'form.search_placeholder') | translate\"\r\n [noResultsLabel]=\"'form.no_results' | translate\"\r\n [ngModel]=\"singleValue(q)\"\r\n (selectionChange)=\"onSingleSelect(q, $event)\" />\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n }\r\n\r\n <!-- \u2500\u2500 Single labelled native control \u2500\u2500 -->\r\n @else {\r\n <label class=\"fly-dynamic-form__label\" [for]=\"fieldId(i)\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </label>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n\r\n @switch (q.type) {\r\n @case ('Text') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"text\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [attr.minlength]=\"q.fieldOptions?.minLength ?? null\"\r\n [attr.maxlength]=\"q.fieldOptions?.maxLength ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\" />\r\n }\r\n @case ('MultilineText') {\r\n <textarea\r\n class=\"fly-dynamic-form__input fly-dynamic-form__textarea\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [rows]=\"q.fieldOptions?.rows ?? 4\"\r\n [attr.minlength]=\"q.fieldOptions?.minLength ?? null\"\r\n [attr.maxlength]=\"q.fieldOptions?.maxLength ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\"></textarea>\r\n }\r\n @case ('Number') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"number\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"numberValue(q)\"\r\n [attr.min]=\"q.fieldOptions?.numericMin ?? null\"\r\n [attr.max]=\"q.fieldOptions?.numericMax ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onNumber(q, $any($event.target).value)\" />\r\n }\r\n @case ('Email') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"email\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\" />\r\n }\r\n @case ('Date') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"date\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"dateValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onDate(q, $any($event.target).value)\" />\r\n }\r\n @case ('DateTime') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"datetime-local\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"dateValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onDate(q, $any($event.target).value)\" />\r\n }\r\n @case ('File') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #fileRef\r\n type=\"file\"\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, fileRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n @case ('Image') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #imgRef\r\n type=\"file\"\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, imgRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n @case ('MultiFile') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #multiRef\r\n type=\"file\"\r\n multiple\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, multiRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n @if (fileError(q)) {\r\n <p class=\"fly-dynamic-form__error\" role=\"alert\">{{ fileError(q) }}</p>\r\n }\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (definition().declaration; as decl) {\r\n <div class=\"fly-dynamic-form__declaration\">\r\n <p class=\"fly-dynamic-form__declaration-text\">{{ decl }}</p>\r\n @if (!isReadonly()) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"declarationAccepted()\"\r\n (change)=\"onDeclarationToggle($any($event.target).checked)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ 'form.declaration_accept' | translate }}</span>\r\n </label>\r\n }\r\n </div>\r\n }\r\n\r\n @if (!isReadonly() && !hideSubmit()) {\r\n <div class=\"fly-dynamic-form__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__submit\"\r\n [disabled]=\"!canSubmit()\"\r\n (click)=\"onSubmit()\">\r\n {{ 'form.submit' | translate }}\r\n </button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-dynamic-form__body{display:flex;flex-direction:column;gap:20px}.fly-dynamic-form__header{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__title{margin:0;font-size:18px;font-weight:700;color:var(--_text)}.fly-dynamic-form__description{margin:0;color:var(--_text-subtle);line-height:1.5}.fly-dynamic-form__fields{display:flex;flex-direction:column;gap:18px}.fly-dynamic-form__section{display:flex;flex-direction:column;gap:18px;margin:0;padding:16px;border:1px solid var(--_border);border-radius:var(--_radius);min-inline-size:0;background:var(--_surface)}.fly-dynamic-form__section-title{padding:0 6px;font-size:13px;font-weight:700;color:var(--_text)}.fly-dynamic-form__field{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__group{display:flex;flex-direction:column;gap:6px;margin:0;padding:0;border:none;min-inline-size:0}.fly-dynamic-form__label{font-weight:600;color:var(--_text)}.fly-dynamic-form__req{color:var(--_danger);margin-inline-start:2px}.fly-dynamic-form__desc{margin:0;font-size:12px;color:var(--_text-subtle);line-height:1.45}.fly-dynamic-form__error{margin:0;font-size:12px;color:var(--_danger)}.fly-dynamic-form__input{inline-size:100%;min-block-size:2.25rem;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-dynamic-form__textarea{min-block-size:5rem;resize:vertical;line-height:1.5}.fly-dynamic-form__input:focus-visible{outline:2px solid var(--_accent);outline-offset:1px}.fly-dynamic-form__input:disabled{opacity:.6;cursor:not-allowed}.fly-dynamic-form__field--invalid .fly-dynamic-form__input{border-color:var(--_danger)}.fly-dynamic-form__options{display:flex;flex-direction:column;gap:8px}.fly-dynamic-form__option{display:flex;align-items:center;gap:8px;cursor:pointer;color:var(--_text)}.fly-dynamic-form__option input{inline-size:1rem;block-size:1rem;accent-color:var(--_accent);cursor:pointer}.fly-dynamic-form__option input:disabled{cursor:not-allowed}.fly-dynamic-form__option-label{line-height:1.3}.fly-dynamic-form__option-score{margin-inline-start:auto;padding:1px 8px;border-radius:999px;background:var(--_fill);color:var(--_text-subtle);font-size:11px;font-weight:700;font-variant-numeric:tabular-nums}.fly-dynamic-form__option-score--inline{margin-inline-start:6px;padding:0;border-radius:0;background:transparent}.fly-dynamic-form__segmented{display:inline-flex;align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);overflow:hidden;background:var(--_surface)}.fly-dynamic-form__seg{min-inline-size:4.5rem;padding:7px 16px;border:none;border-inline-end:1px solid var(--_border);background:transparent;color:var(--_text-subtle);font:inherit;font-weight:600;cursor:pointer;transition:background .12s ease,color .12s ease}.fly-dynamic-form__seg:last-child{border-inline-end:none}.fly-dynamic-form__seg:hover:not(:disabled){background:var(--_surface-hover)}.fly-dynamic-form__seg--on{background:var(--_accent);color:#fff}.fly-dynamic-form__seg:focus-visible{outline:2px solid var(--_accent);outline-offset:-2px}.fly-dynamic-form__seg:disabled{opacity:.6;cursor:not-allowed}.fly-dynamic-form__file{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__file-input{font:inherit;color:var(--_text-subtle)}.fly-dynamic-form__file-list{margin:0;padding-inline-start:18px;color:var(--_text-subtle);font-size:12px}.fly-dynamic-form__declaration{display:flex;flex-direction:column;gap:10px;padding:14px 16px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_fill)}.fly-dynamic-form__declaration-text{margin:0;color:var(--_text-subtle);line-height:1.5}.fly-dynamic-form__actions{display:flex;justify-content:flex-end}.fly-dynamic-form__submit{padding:9px 22px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer;transition:opacity .12s ease}.fly-dynamic-form__submit:hover:not(:disabled){opacity:.9}.fly-dynamic-form__submit:focus-visible{outline:2px solid var(--_accent);outline-offset:2px}.fly-dynamic-form__submit:disabled{opacity:.5;cursor:not-allowed}\n"] }]
14673
+ }, template: "<div class=\"fly-dynamic-form__body\">\r\n <header class=\"fly-dynamic-form__header\">\r\n <h2 class=\"fly-dynamic-form__title\">{{ definition().title }}</h2>\r\n @if (definition().description) {\r\n <p class=\"fly-dynamic-form__description\">{{ definition().description }}</p>\r\n }\r\n </header>\r\n\r\n <div class=\"fly-dynamic-form__fields\">\r\n @for (grp of groupedQuestions(); track $index) {\r\n @if (grp.group) {\r\n <fieldset class=\"fly-dynamic-form__section\">\r\n <legend class=\"fly-dynamic-form__section-title\">{{ grp.group }}</legend>\r\n @for (item of grp.items; track item.q.id) {\r\n <ng-container *ngTemplateOutlet=\"fieldTpl; context: { q: item.q, i: item.index }\" />\r\n }\r\n </fieldset>\r\n } @else {\r\n @for (item of grp.items; track item.q.id) {\r\n <ng-container *ngTemplateOutlet=\"fieldTpl; context: { q: item.q, i: item.index }\" />\r\n }\r\n }\r\n }\r\n </div>\r\n\r\n <ng-template #fieldTpl let-q=\"q\" let-i=\"i\">\r\n <div class=\"fly-dynamic-form__field\" [class.fly-dynamic-form__field--invalid]=\"showError(q)\">\r\n\r\n <!-- \u2500\u2500 Native input group (RadioButton / MultipleSelect) \u2500\u2500 -->\r\n @if (isFieldset(q.type)) {\r\n <fieldset\r\n class=\"fly-dynamic-form__group\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\">\r\n <legend class=\"fly-dynamic-form__label\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </legend>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n\r\n @switch (q.type) {\r\n @case ('RadioButton') {\r\n <div class=\"fly-dynamic-form__options\">\r\n @for (opt of q.options; track opt.id) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"fieldId(i)\"\r\n [value]=\"opt.id\"\r\n [checked]=\"isSelected(q, opt.id)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onRadio(q, opt.id)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ opt.label }}</span>\r\n @if (optionScore(opt) !== null) {\r\n <span class=\"fly-dynamic-form__option-score\" [class.fly-dynamic-form__option-score--inline]=\"scoreDisplay() === 'inline'\">{{ optionScore(opt) }}</span>\r\n }\r\n </label>\r\n }\r\n </div>\r\n }\r\n @case ('MultipleSelect') {\r\n <div class=\"fly-dynamic-form__options\">\r\n @for (opt of q.options; track opt.id) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"checkbox\"\r\n [value]=\"opt.id\"\r\n [checked]=\"isSelected(q, opt.id)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onMultiToggle(q, opt.id, $any($event.target).checked)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ opt.label }}</span>\r\n @if (optionScore(opt) !== null) {\r\n <span class=\"fly-dynamic-form__option-score\" [class.fly-dynamic-form__option-score--inline]=\"scoreDisplay() === 'inline'\">{{ optionScore(opt) }}</span>\r\n }\r\n </label>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n </fieldset>\r\n }\r\n\r\n <!-- \u2500\u2500 Boolean \u2192 segmented Yes / No radiogroup (not a toggle) \u2500\u2500 -->\r\n @else if (q.type === 'Boolean') {\r\n <span class=\"fly-dynamic-form__label\" [id]=\"fieldId(i) + '-lbl'\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </span>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n <div\r\n class=\"fly-dynamic-form__segmented\"\r\n role=\"radiogroup\"\r\n [attr.aria-labelledby]=\"fieldId(i) + '-lbl'\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__seg\"\r\n role=\"radio\"\r\n [class.fly-dynamic-form__seg--on]=\"boolValue(q) === true\"\r\n [attr.aria-checked]=\"boolValue(q) === true\"\r\n [disabled]=\"isReadonly()\"\r\n (click)=\"onBoolean(q, true)\">\r\n {{ 'form.yes' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__seg\"\r\n role=\"radio\"\r\n [class.fly-dynamic-form__seg--on]=\"boolValue(q) === false\"\r\n [attr.aria-checked]=\"boolValue(q) === false\"\r\n [disabled]=\"isReadonly()\"\r\n (click)=\"onBoolean(q, false)\">\r\n {{ 'form.no' | translate }}\r\n </button>\r\n </div>\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n }\r\n\r\n <!-- \u2500\u2500 Searchable DS single-select (SingleSelect+hasSearch / Country) \u2500\u2500 -->\r\n @else if (usesDsSelect(q)) {\r\n <span class=\"fly-dynamic-form__label\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </span>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n <fly-select\r\n [options]=\"isCountry(q.type) ? countryOptions(q) : selectOptions(q)\"\r\n [multiple]=\"false\"\r\n [searchable]=\"selectSearchable(q)\"\r\n [clearable]=\"!q.required\"\r\n [disabled]=\"isReadonly()\"\r\n [ariaLabel]=\"q.text\"\r\n [placeholder]=\"'form.select_placeholder' | translate\"\r\n [searchPlaceholder]=\"(isCountry(q.type) ? 'form.country_search' : 'form.search_placeholder') | translate\"\r\n [noResultsLabel]=\"'form.no_results' | translate\"\r\n [ngModel]=\"singleValue(q)\"\r\n (selectionChange)=\"onSingleSelect(q, $event)\" />\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n }\r\n\r\n <!-- \u2500\u2500 Single labelled native control \u2500\u2500 -->\r\n @else {\r\n <label class=\"fly-dynamic-form__label\" [for]=\"fieldId(i)\">\r\n {{ q.text }}\r\n @if (q.required) { <span class=\"fly-dynamic-form__req\" aria-hidden=\"true\">*</span> }\r\n </label>\r\n @if (q.description) {\r\n <p class=\"fly-dynamic-form__desc\" [id]=\"descId(i)\">{{ q.description }}</p>\r\n }\r\n\r\n @switch (q.type) {\r\n @case ('Text') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"text\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [attr.minlength]=\"q.fieldOptions?.minLength ?? null\"\r\n [attr.maxlength]=\"q.fieldOptions?.maxLength ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\" />\r\n }\r\n @case ('MultilineText') {\r\n <textarea\r\n class=\"fly-dynamic-form__input fly-dynamic-form__textarea\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [rows]=\"q.fieldOptions?.rows ?? 4\"\r\n [attr.minlength]=\"q.fieldOptions?.minLength ?? null\"\r\n [attr.maxlength]=\"q.fieldOptions?.maxLength ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\"></textarea>\r\n }\r\n @case ('Number') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"number\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"numberValue(q)\"\r\n [attr.min]=\"q.fieldOptions?.numericMin ?? null\"\r\n [attr.max]=\"q.fieldOptions?.numericMax ?? null\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onNumber(q, $any($event.target).value)\" />\r\n }\r\n @case ('Email') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"email\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"textValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onText(q, $any($event.target).value)\" />\r\n }\r\n @case ('Date') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"date\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"dateValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onDate(q, $any($event.target).value)\" />\r\n }\r\n @case ('DateTime') {\r\n <input\r\n class=\"fly-dynamic-form__input\"\r\n type=\"datetime-local\"\r\n [id]=\"fieldId(i)\"\r\n [value]=\"dateValue(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (input)=\"onDate(q, $any($event.target).value)\" />\r\n }\r\n @case ('File') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #fileRef\r\n type=\"file\"\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, fileRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n @case ('Image') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #imgRef\r\n type=\"file\"\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, imgRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n @case ('MultiFile') {\r\n <div class=\"fly-dynamic-form__file\">\r\n <input\r\n #multiRef\r\n type=\"file\"\r\n multiple\r\n class=\"fly-dynamic-form__file-input\"\r\n [id]=\"fieldId(i)\"\r\n [accept]=\"acceptFor(q)\"\r\n [attr.aria-required]=\"q.required || null\"\r\n [attr.aria-invalid]=\"showError(q) || null\"\r\n [attr.aria-describedby]=\"describedBy(q, i)\"\r\n [disabled]=\"isReadonly()\"\r\n (change)=\"onFiles(q, multiRef)\" />\r\n @if (fileNames(q).length) {\r\n <ul class=\"fly-dynamic-form__file-list\">\r\n @for (name of fileNames(q); track name) { <li>{{ name }}</li> }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n }\r\n\r\n @if (showError(q)) {\r\n <p class=\"fly-dynamic-form__error\" [id]=\"errId(i)\" role=\"alert\">\r\n {{ 'form.required_error' | translate }}\r\n </p>\r\n }\r\n @if (fileError(q)) {\r\n <p class=\"fly-dynamic-form__error\" role=\"alert\">{{ fileError(q) }}</p>\r\n }\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n @if (definition().declaration; as decl) {\r\n <div class=\"fly-dynamic-form__declaration\">\r\n <p class=\"fly-dynamic-form__declaration-text\">{{ decl }}</p>\r\n @if (!isReadonly()) {\r\n <label class=\"fly-dynamic-form__option\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"declarationAccepted()\"\r\n (change)=\"onDeclarationToggle($any($event.target).checked)\" />\r\n <span class=\"fly-dynamic-form__option-label\">{{ 'form.declaration_accept' | translate }}</span>\r\n </label>\r\n }\r\n </div>\r\n }\r\n\r\n @if (!isReadonly() && !hideSubmit()) {\r\n <div class=\"fly-dynamic-form__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-dynamic-form__submit\"\r\n [disabled]=\"!canSubmit()\"\r\n (click)=\"onSubmit()\">\r\n {{ 'form.submit' | translate }}\r\n </button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-dynamic-form__body{display:flex;flex-direction:column;gap:20px}.fly-dynamic-form__header{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__title{margin:0;font-size:18px;font-weight:700;color:var(--_text)}.fly-dynamic-form__description{margin:0;color:var(--_text-subtle);line-height:1.5}.fly-dynamic-form__fields{display:flex;flex-direction:column;gap:18px}.fly-dynamic-form__section{display:flex;flex-direction:column;gap:18px;margin:0;padding:16px;border:1px solid var(--_border);border-radius:var(--_radius);min-inline-size:0;background:var(--_surface)}.fly-dynamic-form__section-title{padding:0 6px;font-size:13px;font-weight:700;color:var(--_text)}.fly-dynamic-form__field{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__group{display:flex;flex-direction:column;gap:6px;margin:0;padding:0;border:none;min-inline-size:0}.fly-dynamic-form__label{font-weight:600;color:var(--_text)}.fly-dynamic-form__req{color:var(--_danger);margin-inline-start:2px}.fly-dynamic-form__desc{margin:0;font-size:12px;color:var(--_text-subtle);line-height:1.45}.fly-dynamic-form__error{margin:0;font-size:12px;color:var(--_danger)}.fly-dynamic-form__input{inline-size:100%;min-block-size:2.25rem;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-dynamic-form__textarea{min-block-size:5rem;resize:vertical;line-height:1.5}.fly-dynamic-form__input:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:1px}.fly-dynamic-form__input:disabled{opacity:.6;cursor:not-allowed}.fly-dynamic-form__field--invalid .fly-dynamic-form__input{border-color:var(--_danger)}.fly-dynamic-form__options{display:flex;flex-direction:column;gap:8px}.fly-dynamic-form__option{display:flex;align-items:center;gap:8px;cursor:pointer;color:var(--_text)}.fly-dynamic-form__option input{inline-size:1rem;block-size:1rem;accent-color:var(--_accent);cursor:pointer}.fly-dynamic-form__option input:disabled{cursor:not-allowed}.fly-dynamic-form__option-label{line-height:1.3}.fly-dynamic-form__option-score{margin-inline-start:auto;padding:1px 8px;border-radius:999px;background:var(--_fill);color:var(--_text-subtle);font-size:11px;font-weight:700;font-variant-numeric:tabular-nums}.fly-dynamic-form__option-score--inline{margin-inline-start:6px;padding:0;border-radius:0;background:transparent}.fly-dynamic-form__segmented{display:inline-flex;align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);overflow:hidden;background:var(--_surface)}.fly-dynamic-form__seg{min-inline-size:4.5rem;padding:7px 16px;border:none;border-inline-end:1px solid var(--_border);background:transparent;color:var(--_text-subtle);font:inherit;font-weight:600;cursor:pointer;transition:background .12s ease,color .12s ease}.fly-dynamic-form__seg:last-child{border-inline-end:none}.fly-dynamic-form__seg:hover:not(:disabled){background:var(--_surface-hover)}.fly-dynamic-form__seg--on{background:var(--_accent);color:#fff}.fly-dynamic-form__seg:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:-2px}.fly-dynamic-form__seg:disabled{opacity:.6;cursor:not-allowed}.fly-dynamic-form__file{display:flex;flex-direction:column;gap:6px}.fly-dynamic-form__file-input{font:inherit;color:var(--_text-subtle)}.fly-dynamic-form__file-list{margin:0;padding-inline-start:18px;color:var(--_text-subtle);font-size:12px}.fly-dynamic-form__declaration{display:flex;flex-direction:column;gap:10px;padding:14px 16px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_fill)}.fly-dynamic-form__declaration-text{margin:0;color:var(--_text-subtle);line-height:1.5}.fly-dynamic-form__actions{display:flex;justify-content:flex-end}.fly-dynamic-form__submit{padding:9px 22px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer;transition:opacity .12s ease}.fly-dynamic-form__submit:hover:not(:disabled){opacity:.9}.fly-dynamic-form__submit:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:2px}.fly-dynamic-form__submit:disabled{opacity:.5;cursor:not-allowed}\n"] }]
14674
14674
  }], ctorParameters: () => [], propDecorators: { definition: [{ type: i0.Input, args: [{ isSignal: true, alias: "definition", required: true }] }], isReadonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], hideSubmit: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideSubmit", required: false }] }], answers: [{ type: i0.Input, args: [{ isSignal: true, alias: "answers", required: false }] }], showScore: [{ type: i0.Input, args: [{ isSignal: true, alias: "showScore", required: false }] }], scoreDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "scoreDisplay", required: false }] }], answersChange: [{ type: i0.Output, args: ["answersChange"] }], validityChange: [{ type: i0.Output, args: ["validityChange"] }], submit: [{ type: i0.Output, args: ["submit"] }], fileSelected: [{ type: i0.Output, args: ["fileSelected"] }] } });
14675
14675
 
14676
14676
  // ── fly-survey-form — backward-compatible re-export ──────────────────────────
@@ -15034,7 +15034,7 @@ class FlyCommentThreadComponent {
15034
15034
  this._drafts.set(map);
15035
15035
  }
15036
15036
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyCommentThreadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
15037
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyCommentThreadComponent, isStandalone: true, selector: "fly-comment-thread", inputs: { rootPage: { classPropertyName: "rootPage", publicName: "rootPage", isSignal: true, isRequired: true, transformFunction: null }, repliesByParent: { classPropertyName: "repliesByParent", publicName: "repliesByParent", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, isLocked: { classPropertyName: "isLocked", publicName: "isLocked", isSignal: true, isRequired: false, transformFunction: null }, currentUserId: { classPropertyName: "currentUserId", publicName: "currentUserId", isSignal: true, isRequired: false, transformFunction: null }, isReadonly: { classPropertyName: "isReadonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, canModerateThread: { classPropertyName: "canModerateThread", publicName: "canModerateThread", isSignal: true, isRequired: false, transformFunction: null }, resolveDisplayName: { classPropertyName: "resolveDisplayName", publicName: "resolveDisplayName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loadReplies: "loadReplies", loadMore: "loadMore", submit: "submit", edit: "edit", delete: "delete", report: "report", lockToggle: "lockToggle", sortChange: "sortChange" }, host: { properties: { "class.fly-comment-thread--locked": "isLocked()", "class.fly-comment-thread--readonly": "isReadonly()" }, classAttribute: "fly-comment-thread" }, ngImport: i0, template: "<div class=\"fly-comment-thread__body\">\r\n <!-- \u2500\u2500 Header: count + one combined sort/lock icon-button toolbar \u2500\u2500 -->\r\n <header class=\"fly-comment-thread__header\">\r\n <span class=\"fly-comment-thread__count\">\r\n {{ 'comment.count' | translate: { n: rootPage().total } }}\r\n </span>\r\n\r\n <div class=\"fly-comment-thread__toolbar\" role=\"group\" [attr.aria-label]=\"'comment.sort_label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"sort() === 'newest'\"\r\n [attr.aria-pressed]=\"sort() === 'newest'\"\r\n [flyTooltip]=\"'comment.sort_newest' | translate\"\r\n [attr.aria-label]=\"'comment.sort_newest' | translate\"\r\n (click)=\"onSortPick('newest')\">\r\n <i class=\"pi pi-sort-amount-down\" aria-hidden=\"true\"></i>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"sort() === 'oldest'\"\r\n [attr.aria-pressed]=\"sort() === 'oldest'\"\r\n [flyTooltip]=\"'comment.sort_oldest' | translate\"\r\n [attr.aria-label]=\"'comment.sort_oldest' | translate\"\r\n (click)=\"onSortPick('oldest')\">\r\n <i class=\"pi pi-sort-amount-up\" aria-hidden=\"true\"></i>\r\n </button>\r\n\r\n @if (canModerateThread() && !isReadonly()) {\r\n <span class=\"fly-comment-thread__toolbar-sep\" aria-hidden=\"true\"></span>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"isLocked()\"\r\n [attr.aria-pressed]=\"isLocked()\"\r\n [flyTooltip]=\"(isLocked() ? 'comment.unlock' : 'comment.lock') | translate\"\r\n [attr.aria-label]=\"(isLocked() ? 'comment.unlock' : 'comment.lock') | translate\"\r\n (click)=\"toggleLock()\">\r\n <i class=\"pi\" [class.pi-lock]=\"!isLocked()\" [class.pi-lock-open]=\"isLocked()\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n </div>\r\n </header>\r\n\r\n @if (isLocked()) {\r\n <p class=\"fly-comment-thread__locked-notice\">{{ 'comment.locked_notice' | translate }}</p>\r\n }\r\n\r\n <!-- \u2500\u2500 Root composer \u2500\u2500 -->\r\n @if (canReply()) {\r\n <div class=\"fly-comment-thread__composer\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [id]=\"fieldId('root-composer')\"\r\n [attr.aria-label]=\"'comment.composer_placeholder' | translate\"\r\n [placeholder]=\"'comment.composer_placeholder' | translate\"\r\n [ngModel]=\"rootDraft()\"\r\n (ngModelChange)=\"onRootDraftChange($event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__submit-btn\"\r\n [disabled]=\"!rootDraft().trim()\"\r\n (click)=\"submitRoot()\">\r\n {{ 'comment.post' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- \u2500\u2500 Root comments \u2500\u2500 -->\r\n @if (rootPage().items.length === 0) {\r\n <p class=\"fly-comment-thread__empty\">{{ 'comment.empty' | translate }}</p>\r\n } @else {\r\n <ul class=\"fly-comment-thread__list\" role=\"list\">\r\n @for (c of rootPage().items; track c.id) {\r\n <ng-container [ngTemplateOutlet]=\"commentNode\" [ngTemplateOutletContext]=\"{ $implicit: c }\"></ng-container>\r\n }\r\n </ul>\r\n\r\n @if (rootPage().hasMore) {\r\n <button type=\"button\" class=\"fly-comment-thread__load-more\" (click)=\"loadMoreRoot()\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 Recursive comment node template \u2500\u2500 -->\r\n<ng-template #commentNode let-comment>\r\n <li class=\"fly-comment-thread__item\" [attr.data-depth]=\"comment.depth\">\r\n <div class=\"fly-comment-thread__row\">\r\n <div class=\"fly-comment-thread__avatar\" aria-hidden=\"true\">\r\n @if (comment.authorAvatarUrl) {\r\n <img [src]=\"comment.authorAvatarUrl\" alt=\"\" />\r\n } @else {\r\n <span class=\"fly-comment-thread__avatar-fallback\">{{ authorInitial(comment) }}</span>\r\n }\r\n </div>\r\n\r\n <div class=\"fly-comment-thread__content\">\r\n <div class=\"fly-comment-thread__meta\">\r\n <span class=\"fly-comment-thread__author\">{{ authorLabel(comment) }}</span>\r\n <span class=\"fly-comment-thread__timestamp\">{{ formatDate(comment.createdAt) }}</span>\r\n @if (comment.isEdited && !comment.isDeleted) {\r\n <span class=\"fly-comment-thread__edited\">{{ 'comment.edited' | translate }}</span>\r\n }\r\n </div>\r\n\r\n @if (comment.isDeleted) {\r\n <p class=\"fly-comment-thread__tombstone\">{{ 'comment.deleted' | translate }}</p>\r\n } @else if (editingId() === comment.id) {\r\n <div class=\"fly-comment-thread__edit-box\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [ngModel]=\"comment.body\"\r\n (ngModelChange)=\"onEditDraftChange($event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"cancelEdit()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__submit-btn\" (click)=\"saveEdit(comment)\">\r\n {{ 'comment.save' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"fly-comment-thread__text-row\">\r\n <p class=\"fly-comment-thread__text\">{{ comment.body }}</p>\r\n @if (!isReadonly()) {\r\n <div class=\"fly-comment-thread__actions\">\r\n @if (canReply()) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.reply' | translate\"\r\n [attr.aria-label]=\"'comment.reply' | translate\"\r\n (click)=\"openReplyBox(comment.id)\">\r\n <i class=\"pi pi-reply\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canEditComment(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.edit' | translate\"\r\n [attr.aria-label]=\"'comment.edit' | translate\"\r\n (click)=\"startEdit(comment)\">\r\n <i class=\"pi pi-pencil\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canDeleteComment(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn fly-comment-thread__icon-btn--danger\"\r\n [flyTooltip]=\"'comment.delete' | translate\"\r\n [attr.aria-label]=\"'comment.delete' | translate\"\r\n (click)=\"requestDelete(comment)\">\r\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canReport(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.report' | translate\"\r\n [attr.aria-label]=\"'comment.report' | translate\"\r\n (click)=\"openReport(comment)\">\r\n <i class=\"pi pi-flag\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (confirmingDeleteId() === comment.id) {\r\n <div class=\"fly-comment-thread__confirm\">\r\n <span>{{ 'comment.delete_confirm' | translate }}</span>\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"cancelDelete()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__danger-btn\" (click)=\"confirmDelete(comment)\">\r\n {{ 'comment.delete' | translate }}\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (isReplyBoxOpen(comment.id)) {\r\n <div class=\"fly-comment-thread__composer fly-comment-thread__composer--reply\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"2\"\r\n [attr.aria-label]=\"'comment.reply_placeholder' | translate\"\r\n [placeholder]=\"'comment.reply_placeholder' | translate\"\r\n [ngModel]=\"replyDraft(comment.id)\"\r\n (ngModelChange)=\"onReplyDraftChange(comment.id, $event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"closeReplyBox(comment.id)\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__submit-btn\"\r\n [disabled]=\"!replyDraft(comment.id).trim()\"\r\n (click)=\"submitReply(comment.id)\">\r\n {{ 'comment.post' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (comment.replyCount > 0) {\r\n <button type=\"button\" class=\"fly-comment-thread__toggle-replies\" (click)=\"toggleReplies(comment)\">\r\n {{ (isExpanded(comment.id) ? 'comment.hide_replies' : 'comment.show_replies') | translate: { n: comment.replyCount } }}\r\n </button>\r\n }\r\n\r\n @if (isExpanded(comment.id)) {\r\n <ul class=\"fly-comment-thread__list fly-comment-thread__list--nested\" role=\"list\">\r\n @for (child of repliesFor(comment.id)?.items ?? []; track child.id) {\r\n <ng-container [ngTemplateOutlet]=\"commentNode\" [ngTemplateOutletContext]=\"{ $implicit: child }\"></ng-container>\r\n }\r\n </ul>\r\n @if (repliesFor(comment.id)?.hasMore) {\r\n <button type=\"button\" class=\"fly-comment-thread__load-more fly-comment-thread__load-more--nested\" (click)=\"loadMoreReplies(comment.id)\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </li>\r\n</ng-template>\r\n\r\n<!-- \u2500\u2500 Report dialog \u2500\u2500 -->\r\n@if (reportingId()) {\r\n <div class=\"fly-comment-thread__overlay\">\r\n <div class=\"fly-comment-thread__overlay-backdrop\" role=\"button\" tabindex=\"0\"\r\n [attr.aria-label]=\"'common.action.cancel' | translate\"\r\n (click)=\"closeReport()\"\r\n (keydown.enter)=\"closeReport()\"\r\n (keydown.space)=\"onOverlayBackdropSpace($event)\"></div>\r\n <div class=\"fly-comment-thread__dialog\" role=\"dialog\" [attr.aria-label]=\"'comment.report_title' | translate\">\r\n <h3 class=\"fly-comment-thread__dialog-title\">{{ 'comment.report_title' | translate }}</h3>\r\n\r\n <fieldset class=\"fly-comment-thread__reason-group\">\r\n <legend>{{ 'comment.report_reason_label' | translate }}</legend>\r\n @for (reason of reportReasons; track reason) {\r\n <label class=\"fly-comment-thread__reason-option\">\r\n <input\r\n type=\"radio\"\r\n name=\"fly-comment-report-reason\"\r\n [value]=\"reason\"\r\n [checked]=\"reportReason() === reason\"\r\n (change)=\"onReportReasonChange(reason)\" />\r\n <span>{{ 'comment.reason.' + reason | translate }}</span>\r\n </label>\r\n }\r\n </fieldset>\r\n\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [attr.aria-label]=\"'comment.report_detail_label' | translate\"\r\n [placeholder]=\"'comment.report_detail_label' | translate\"\r\n [ngModel]=\"reportDetail()\"\r\n (ngModelChange)=\"onReportDetailChange($event)\"></textarea>\r\n\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"closeReport()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__submit-btn\" [disabled]=\"!reportReason()\" (click)=\"submitReport()\">\r\n {{ 'comment.report_submit' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_text-tertiary: var(--label-tertiary, #94a3b8);--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-comment-thread__body{display:flex;flex-direction:column;gap:16px}.fly-comment-thread__header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.fly-comment-thread__count{font-weight:700;font-size:14px}.fly-comment-thread__toolbar{display:inline-flex;align-items:center;gap:2px;padding:2px;border:1px solid var(--_border);border-radius:calc(var(--_radius) + 2px);background:var(--_surface)}.fly-comment-thread__toolbar-sep{inline-size:1px;block-size:18px;margin-inline:2px;background:var(--_border)}.fly-comment-thread__icon-btn{display:inline-flex;align-items:center;justify-content:center;inline-size:26px;block-size:26px;flex:none;padding:0;border:none;border-radius:50%;background:transparent;color:var(--_text-subtle);cursor:pointer;transition:background var(--t-state, .15s),color var(--t-state, .15s)}.fly-comment-thread__icon-btn .pi{font-size:13px}.fly-comment-thread__icon-btn:hover{background:var(--_surface-hover);color:var(--_text)}.fly-comment-thread__icon-btn:focus-visible{outline:2px solid var(--_accent);outline-offset:1px}.fly-comment-thread__icon-btn--active{background:var(--_accent);color:#fff}.fly-comment-thread__icon-btn--active:hover{background:var(--_accent);opacity:.9}.fly-comment-thread__icon-btn--danger:hover{background:var(--_danger);color:#fff}.fly-comment-thread__locked-notice{margin:0;padding:8px 12px;border-radius:var(--_radius);background:var(--_fill);color:var(--_text-subtle);font-size:12px}.fly-comment-thread__empty{margin:0;color:var(--_text-subtle);text-align:center;padding:16px 0}.fly-comment-thread__composer{display:flex;flex-direction:column;gap:8px}.fly-comment-thread__composer--reply{margin-block-start:8px}.fly-comment-thread__textarea{inline-size:100%;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;line-height:1.5;resize:vertical}.fly-comment-thread__textarea:focus-visible{outline:2px solid var(--_accent);outline-offset:1px}.fly-comment-thread__composer-actions{display:flex;justify-content:flex-end;gap:8px}.fly-comment-thread__submit-btn{padding:6px 16px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__submit-btn:hover:not(:disabled){opacity:.9}.fly-comment-thread__submit-btn:disabled{opacity:.5;cursor:not-allowed}.fly-comment-thread__cancel-btn{padding:6px 14px;border:1px solid var(--_border);border-radius:var(--_radius);background:transparent;color:var(--_text-subtle);font:inherit;cursor:pointer}.fly-comment-thread__cancel-btn:hover{background:var(--_surface-hover)}.fly-comment-thread__danger-btn{padding:6px 14px;border:none;border-radius:var(--_radius);background:var(--_danger);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__danger-btn:hover{opacity:.9}.fly-comment-thread__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:14px}.fly-comment-thread__list--nested{margin-block-start:10px;margin-inline-start:20px;padding-inline-start:12px;border-inline-start:2px solid var(--_border);gap:12px}.fly-comment-thread__item{display:block}.fly-comment-thread__row{display:flex;gap:10px;align-items:flex-start}.fly-comment-thread__avatar{inline-size:32px;block-size:32px;border-radius:50%;overflow:hidden;flex:none;background:var(--_fill);display:flex;align-items:center;justify-content:center}.fly-comment-thread__avatar img{inline-size:100%;block-size:100%;object-fit:cover}.fly-comment-thread__avatar-fallback{font-weight:700;color:var(--_text-subtle);text-transform:uppercase}.fly-comment-thread__content{flex:1 1 auto;min-inline-size:0;display:flex;flex-direction:column;gap:4px}.fly-comment-thread__meta{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}.fly-comment-thread__author{font-weight:700;color:var(--_text)}.fly-comment-thread__timestamp{font-size:11px;color:var(--_text-tertiary)}.fly-comment-thread__edited{font-size:11px;color:var(--_text-tertiary);font-style:italic}.fly-comment-thread__text-row{display:flex;align-items:flex-start;gap:4px}.fly-comment-thread__text{flex:1 1 auto;min-inline-size:0;margin:0;color:var(--_text);line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}.fly-comment-thread__tombstone{margin:0;color:var(--_text-tertiary);font-style:italic}.fly-comment-thread__edit-box{display:flex;flex-direction:column;gap:6px}.fly-comment-thread__actions{display:flex;align-items:center;gap:2px;flex:none;margin-inline-start:auto}.fly-comment-thread__confirm{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:var(--_radius);background:var(--_fill);font-size:12px;color:var(--_text-subtle)}.fly-comment-thread__toggle-replies{align-self:flex-start;border:none;background:transparent;padding:0;margin-block-start:4px;color:var(--_accent);font:inherit;font-size:12px;font-weight:700;cursor:pointer}.fly-comment-thread__toggle-replies:hover{text-decoration:underline}.fly-comment-thread__load-more{align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:6px 14px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__load-more:hover{background:var(--_surface-hover)}.fly-comment-thread__load-more--nested{margin-inline-start:20px}.fly-comment-thread__overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:1000}.fly-comment-thread__overlay-backdrop{position:absolute;inset:0;background:#00000073;border:none;padding:0;margin:0;cursor:pointer}.fly-comment-thread__dialog{position:relative;z-index:1;inline-size:min(420px,90vw);max-block-size:85vh;overflow-y:auto;background:var(--_surface);border-radius:12px;padding:20px;display:flex;flex-direction:column;gap:14px;box-shadow:0 12px 32px #00000040}.fly-comment-thread__dialog-title{margin:0;font-size:16px;font-weight:700}.fly-comment-thread__reason-group{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;border:none}.fly-comment-thread__reason-group legend{font-weight:600;padding:0;margin-block-end:4px}.fly-comment-thread__reason-option{display:flex;align-items:center;gap:8px;cursor:pointer}.fly-comment-thread__reason-option input{accent-color:var(--_accent);cursor:pointer}:host(.fly-comment-thread--readonly) .fly-comment-thread__composer,:host(.fly-comment-thread--readonly) .fly-comment-thread__actions{display:none}\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.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: "directive", type: FlyTooltipDirective, selector: "[flyTooltip], [data-tooltip]", inputs: ["flyTooltip", "flyTooltipPlacement", "flyTooltipDisabled", "flyTooltipDelay"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
15037
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyCommentThreadComponent, isStandalone: true, selector: "fly-comment-thread", inputs: { rootPage: { classPropertyName: "rootPage", publicName: "rootPage", isSignal: true, isRequired: true, transformFunction: null }, repliesByParent: { classPropertyName: "repliesByParent", publicName: "repliesByParent", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, isLocked: { classPropertyName: "isLocked", publicName: "isLocked", isSignal: true, isRequired: false, transformFunction: null }, currentUserId: { classPropertyName: "currentUserId", publicName: "currentUserId", isSignal: true, isRequired: false, transformFunction: null }, isReadonly: { classPropertyName: "isReadonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, canModerateThread: { classPropertyName: "canModerateThread", publicName: "canModerateThread", isSignal: true, isRequired: false, transformFunction: null }, resolveDisplayName: { classPropertyName: "resolveDisplayName", publicName: "resolveDisplayName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loadReplies: "loadReplies", loadMore: "loadMore", submit: "submit", edit: "edit", delete: "delete", report: "report", lockToggle: "lockToggle", sortChange: "sortChange" }, host: { properties: { "class.fly-comment-thread--locked": "isLocked()", "class.fly-comment-thread--readonly": "isReadonly()" }, classAttribute: "fly-comment-thread" }, ngImport: i0, template: "<div class=\"fly-comment-thread__body\">\r\n <!-- \u2500\u2500 Header: count + one combined sort/lock icon-button toolbar \u2500\u2500 -->\r\n <header class=\"fly-comment-thread__header\">\r\n <span class=\"fly-comment-thread__count\">\r\n {{ 'comment.count' | translate: { n: rootPage().total } }}\r\n </span>\r\n\r\n <div class=\"fly-comment-thread__toolbar\" role=\"group\" [attr.aria-label]=\"'comment.sort_label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"sort() === 'newest'\"\r\n [attr.aria-pressed]=\"sort() === 'newest'\"\r\n [flyTooltip]=\"'comment.sort_newest' | translate\"\r\n [attr.aria-label]=\"'comment.sort_newest' | translate\"\r\n (click)=\"onSortPick('newest')\">\r\n <i class=\"pi pi-sort-amount-down\" aria-hidden=\"true\"></i>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"sort() === 'oldest'\"\r\n [attr.aria-pressed]=\"sort() === 'oldest'\"\r\n [flyTooltip]=\"'comment.sort_oldest' | translate\"\r\n [attr.aria-label]=\"'comment.sort_oldest' | translate\"\r\n (click)=\"onSortPick('oldest')\">\r\n <i class=\"pi pi-sort-amount-up\" aria-hidden=\"true\"></i>\r\n </button>\r\n\r\n @if (canModerateThread() && !isReadonly()) {\r\n <span class=\"fly-comment-thread__toolbar-sep\" aria-hidden=\"true\"></span>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"isLocked()\"\r\n [attr.aria-pressed]=\"isLocked()\"\r\n [flyTooltip]=\"(isLocked() ? 'comment.unlock' : 'comment.lock') | translate\"\r\n [attr.aria-label]=\"(isLocked() ? 'comment.unlock' : 'comment.lock') | translate\"\r\n (click)=\"toggleLock()\">\r\n <i class=\"pi\" [class.pi-lock]=\"!isLocked()\" [class.pi-lock-open]=\"isLocked()\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n </div>\r\n </header>\r\n\r\n @if (isLocked()) {\r\n <p class=\"fly-comment-thread__locked-notice\">{{ 'comment.locked_notice' | translate }}</p>\r\n }\r\n\r\n <!-- \u2500\u2500 Root composer \u2500\u2500 -->\r\n @if (canReply()) {\r\n <div class=\"fly-comment-thread__composer\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [id]=\"fieldId('root-composer')\"\r\n [attr.aria-label]=\"'comment.composer_placeholder' | translate\"\r\n [placeholder]=\"'comment.composer_placeholder' | translate\"\r\n [ngModel]=\"rootDraft()\"\r\n (ngModelChange)=\"onRootDraftChange($event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__submit-btn\"\r\n [disabled]=\"!rootDraft().trim()\"\r\n (click)=\"submitRoot()\">\r\n {{ 'comment.post' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- \u2500\u2500 Root comments \u2500\u2500 -->\r\n @if (rootPage().items.length === 0) {\r\n <p class=\"fly-comment-thread__empty\">{{ 'comment.empty' | translate }}</p>\r\n } @else {\r\n <ul class=\"fly-comment-thread__list\" role=\"list\">\r\n @for (c of rootPage().items; track c.id) {\r\n <ng-container [ngTemplateOutlet]=\"commentNode\" [ngTemplateOutletContext]=\"{ $implicit: c }\"></ng-container>\r\n }\r\n </ul>\r\n\r\n @if (rootPage().hasMore) {\r\n <button type=\"button\" class=\"fly-comment-thread__load-more\" (click)=\"loadMoreRoot()\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 Recursive comment node template \u2500\u2500 -->\r\n<ng-template #commentNode let-comment>\r\n <li class=\"fly-comment-thread__item\" [attr.data-depth]=\"comment.depth\">\r\n <div class=\"fly-comment-thread__row\">\r\n <div class=\"fly-comment-thread__avatar\" aria-hidden=\"true\">\r\n @if (comment.authorAvatarUrl) {\r\n <img [src]=\"comment.authorAvatarUrl\" alt=\"\" />\r\n } @else {\r\n <span class=\"fly-comment-thread__avatar-fallback\">{{ authorInitial(comment) }}</span>\r\n }\r\n </div>\r\n\r\n <div class=\"fly-comment-thread__content\">\r\n <div class=\"fly-comment-thread__meta\">\r\n <span class=\"fly-comment-thread__author\">{{ authorLabel(comment) }}</span>\r\n <span class=\"fly-comment-thread__timestamp\">{{ formatDate(comment.createdAt) }}</span>\r\n @if (comment.isEdited && !comment.isDeleted) {\r\n <span class=\"fly-comment-thread__edited\">{{ 'comment.edited' | translate }}</span>\r\n }\r\n </div>\r\n\r\n @if (comment.isDeleted) {\r\n <p class=\"fly-comment-thread__tombstone\">{{ 'comment.deleted' | translate }}</p>\r\n } @else if (editingId() === comment.id) {\r\n <div class=\"fly-comment-thread__edit-box\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [ngModel]=\"comment.body\"\r\n (ngModelChange)=\"onEditDraftChange($event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"cancelEdit()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__submit-btn\" (click)=\"saveEdit(comment)\">\r\n {{ 'comment.save' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"fly-comment-thread__text-row\">\r\n <p class=\"fly-comment-thread__text\">{{ comment.body }}</p>\r\n @if (!isReadonly()) {\r\n <div class=\"fly-comment-thread__actions\">\r\n @if (canReply()) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.reply' | translate\"\r\n [attr.aria-label]=\"'comment.reply' | translate\"\r\n (click)=\"openReplyBox(comment.id)\">\r\n <i class=\"pi pi-reply\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canEditComment(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.edit' | translate\"\r\n [attr.aria-label]=\"'comment.edit' | translate\"\r\n (click)=\"startEdit(comment)\">\r\n <i class=\"pi pi-pencil\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canDeleteComment(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn fly-comment-thread__icon-btn--danger\"\r\n [flyTooltip]=\"'comment.delete' | translate\"\r\n [attr.aria-label]=\"'comment.delete' | translate\"\r\n (click)=\"requestDelete(comment)\">\r\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canReport(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.report' | translate\"\r\n [attr.aria-label]=\"'comment.report' | translate\"\r\n (click)=\"openReport(comment)\">\r\n <i class=\"pi pi-flag\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (confirmingDeleteId() === comment.id) {\r\n <div class=\"fly-comment-thread__confirm\">\r\n <span>{{ 'comment.delete_confirm' | translate }}</span>\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"cancelDelete()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__danger-btn\" (click)=\"confirmDelete(comment)\">\r\n {{ 'comment.delete' | translate }}\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (isReplyBoxOpen(comment.id)) {\r\n <div class=\"fly-comment-thread__composer fly-comment-thread__composer--reply\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"2\"\r\n [attr.aria-label]=\"'comment.reply_placeholder' | translate\"\r\n [placeholder]=\"'comment.reply_placeholder' | translate\"\r\n [ngModel]=\"replyDraft(comment.id)\"\r\n (ngModelChange)=\"onReplyDraftChange(comment.id, $event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"closeReplyBox(comment.id)\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__submit-btn\"\r\n [disabled]=\"!replyDraft(comment.id).trim()\"\r\n (click)=\"submitReply(comment.id)\">\r\n {{ 'comment.post' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (comment.replyCount > 0) {\r\n <button type=\"button\" class=\"fly-comment-thread__toggle-replies\" (click)=\"toggleReplies(comment)\">\r\n {{ (isExpanded(comment.id) ? 'comment.hide_replies' : 'comment.show_replies') | translate: { n: comment.replyCount } }}\r\n </button>\r\n }\r\n\r\n @if (isExpanded(comment.id)) {\r\n <ul class=\"fly-comment-thread__list fly-comment-thread__list--nested\" role=\"list\">\r\n @for (child of repliesFor(comment.id)?.items ?? []; track child.id) {\r\n <ng-container [ngTemplateOutlet]=\"commentNode\" [ngTemplateOutletContext]=\"{ $implicit: child }\"></ng-container>\r\n }\r\n </ul>\r\n @if (repliesFor(comment.id)?.hasMore) {\r\n <button type=\"button\" class=\"fly-comment-thread__load-more fly-comment-thread__load-more--nested\" (click)=\"loadMoreReplies(comment.id)\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </li>\r\n</ng-template>\r\n\r\n<!-- \u2500\u2500 Report dialog \u2500\u2500 -->\r\n@if (reportingId()) {\r\n <div class=\"fly-comment-thread__overlay\">\r\n <div class=\"fly-comment-thread__overlay-backdrop\" role=\"button\" tabindex=\"0\"\r\n [attr.aria-label]=\"'common.action.cancel' | translate\"\r\n (click)=\"closeReport()\"\r\n (keydown.enter)=\"closeReport()\"\r\n (keydown.space)=\"onOverlayBackdropSpace($event)\"></div>\r\n <div class=\"fly-comment-thread__dialog\" role=\"dialog\" [attr.aria-label]=\"'comment.report_title' | translate\">\r\n <h3 class=\"fly-comment-thread__dialog-title\">{{ 'comment.report_title' | translate }}</h3>\r\n\r\n <fieldset class=\"fly-comment-thread__reason-group\">\r\n <legend>{{ 'comment.report_reason_label' | translate }}</legend>\r\n @for (reason of reportReasons; track reason) {\r\n <label class=\"fly-comment-thread__reason-option\">\r\n <input\r\n type=\"radio\"\r\n name=\"fly-comment-report-reason\"\r\n [value]=\"reason\"\r\n [checked]=\"reportReason() === reason\"\r\n (change)=\"onReportReasonChange(reason)\" />\r\n <span>{{ 'comment.reason.' + reason | translate }}</span>\r\n </label>\r\n }\r\n </fieldset>\r\n\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [attr.aria-label]=\"'comment.report_detail_label' | translate\"\r\n [placeholder]=\"'comment.report_detail_label' | translate\"\r\n [ngModel]=\"reportDetail()\"\r\n (ngModelChange)=\"onReportDetailChange($event)\"></textarea>\r\n\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"closeReport()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__submit-btn\" [disabled]=\"!reportReason()\" (click)=\"submitReport()\">\r\n {{ 'comment.report_submit' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_text-tertiary: var(--label-tertiary, #94a3b8);--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-comment-thread__body{display:flex;flex-direction:column;gap:16px}.fly-comment-thread__header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.fly-comment-thread__count{font-weight:700;font-size:14px}.fly-comment-thread__toolbar{display:inline-flex;align-items:center;gap:2px;padding:2px;border:1px solid var(--_border);border-radius:calc(var(--_radius) + 2px);background:var(--_surface)}.fly-comment-thread__toolbar-sep{inline-size:1px;block-size:18px;margin-inline:2px;background:var(--_border)}.fly-comment-thread__icon-btn{display:inline-flex;align-items:center;justify-content:center;inline-size:26px;block-size:26px;flex:none;padding:0;border:none;border-radius:50%;background:transparent;color:var(--_text-subtle);cursor:pointer;transition:background var(--t-state, .15s),color var(--t-state, .15s)}.fly-comment-thread__icon-btn .pi{font-size:13px}.fly-comment-thread__icon-btn:hover{background:var(--_surface-hover);color:var(--_text)}.fly-comment-thread__icon-btn:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:1px}.fly-comment-thread__icon-btn--active{background:var(--_accent);color:#fff}.fly-comment-thread__icon-btn--active:hover{background:var(--_accent);opacity:.9}.fly-comment-thread__icon-btn--danger:hover{background:var(--_danger);color:#fff}.fly-comment-thread__locked-notice{margin:0;padding:8px 12px;border-radius:var(--_radius);background:var(--_fill);color:var(--_text-subtle);font-size:12px}.fly-comment-thread__empty{margin:0;color:var(--_text-subtle);text-align:center;padding:16px 0}.fly-comment-thread__composer{display:flex;flex-direction:column;gap:8px}.fly-comment-thread__composer--reply{margin-block-start:8px}.fly-comment-thread__textarea{inline-size:100%;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;line-height:1.5;resize:vertical}.fly-comment-thread__textarea:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:1px}.fly-comment-thread__composer-actions{display:flex;justify-content:flex-end;gap:8px}.fly-comment-thread__submit-btn{padding:6px 16px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__submit-btn:hover:not(:disabled){opacity:.9}.fly-comment-thread__submit-btn:disabled{opacity:.5;cursor:not-allowed}.fly-comment-thread__cancel-btn{padding:6px 14px;border:1px solid var(--_border);border-radius:var(--_radius);background:transparent;color:var(--_text-subtle);font:inherit;cursor:pointer}.fly-comment-thread__cancel-btn:hover{background:var(--_surface-hover)}.fly-comment-thread__danger-btn{padding:6px 14px;border:none;border-radius:var(--_radius);background:var(--_danger);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__danger-btn:hover{opacity:.9}.fly-comment-thread__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:14px}.fly-comment-thread__list--nested{margin-block-start:10px;margin-inline-start:20px;padding-inline-start:12px;border-inline-start:2px solid var(--_border);gap:12px}.fly-comment-thread__item{display:block}.fly-comment-thread__row{display:flex;gap:10px;align-items:flex-start}.fly-comment-thread__avatar{inline-size:32px;block-size:32px;border-radius:50%;overflow:hidden;flex:none;background:var(--_fill);display:flex;align-items:center;justify-content:center}.fly-comment-thread__avatar img{inline-size:100%;block-size:100%;object-fit:cover}.fly-comment-thread__avatar-fallback{font-weight:700;color:var(--_text-subtle);text-transform:uppercase}.fly-comment-thread__content{flex:1 1 auto;min-inline-size:0;display:flex;flex-direction:column;gap:4px}.fly-comment-thread__meta{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}.fly-comment-thread__author{font-weight:700;color:var(--_text)}.fly-comment-thread__timestamp{font-size:11px;color:var(--_text-tertiary)}.fly-comment-thread__edited{font-size:11px;color:var(--_text-tertiary);font-style:italic}.fly-comment-thread__text-row{display:flex;align-items:flex-start;gap:4px}.fly-comment-thread__text{flex:1 1 auto;min-inline-size:0;margin:0;color:var(--_text);line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}.fly-comment-thread__tombstone{margin:0;color:var(--_text-tertiary);font-style:italic}.fly-comment-thread__edit-box{display:flex;flex-direction:column;gap:6px}.fly-comment-thread__actions{display:flex;align-items:center;gap:2px;flex:none;margin-inline-start:auto}.fly-comment-thread__confirm{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:var(--_radius);background:var(--_fill);font-size:12px;color:var(--_text-subtle)}.fly-comment-thread__toggle-replies{align-self:flex-start;border:none;background:transparent;padding:0;margin-block-start:4px;color:var(--_accent);font:inherit;font-size:12px;font-weight:700;cursor:pointer}.fly-comment-thread__toggle-replies:hover{text-decoration:underline}.fly-comment-thread__load-more{align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:6px 14px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__load-more:hover{background:var(--_surface-hover)}.fly-comment-thread__load-more--nested{margin-inline-start:20px}.fly-comment-thread__overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:1000}.fly-comment-thread__overlay-backdrop{position:absolute;inset:0;background:#00000073;border:none;padding:0;margin:0;cursor:pointer}.fly-comment-thread__dialog{position:relative;z-index:1;inline-size:min(420px,90vw);max-block-size:85vh;overflow-y:auto;background:var(--_surface);border-radius:12px;padding:20px;display:flex;flex-direction:column;gap:14px;box-shadow:0 12px 32px #00000040}.fly-comment-thread__dialog-title{margin:0;font-size:16px;font-weight:700}.fly-comment-thread__reason-group{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;border:none}.fly-comment-thread__reason-group legend{font-weight:600;padding:0;margin-block-end:4px}.fly-comment-thread__reason-option{display:flex;align-items:center;gap:8px;cursor:pointer}.fly-comment-thread__reason-option input{accent-color:var(--_accent);cursor:pointer}:host(.fly-comment-thread--readonly) .fly-comment-thread__composer,:host(.fly-comment-thread--readonly) .fly-comment-thread__actions{display:none}\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.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: "directive", type: FlyTooltipDirective, selector: "[flyTooltip], [data-tooltip]", inputs: ["flyTooltip", "flyTooltipPlacement", "flyTooltipDisabled", "flyTooltipDelay"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
15038
15038
  }
15039
15039
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyCommentThreadComponent, decorators: [{
15040
15040
  type: Component,
@@ -15042,7 +15042,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
15042
15042
  class: 'fly-comment-thread',
15043
15043
  '[class.fly-comment-thread--locked]': 'isLocked()',
15044
15044
  '[class.fly-comment-thread--readonly]': 'isReadonly()',
15045
- }, template: "<div class=\"fly-comment-thread__body\">\r\n <!-- \u2500\u2500 Header: count + one combined sort/lock icon-button toolbar \u2500\u2500 -->\r\n <header class=\"fly-comment-thread__header\">\r\n <span class=\"fly-comment-thread__count\">\r\n {{ 'comment.count' | translate: { n: rootPage().total } }}\r\n </span>\r\n\r\n <div class=\"fly-comment-thread__toolbar\" role=\"group\" [attr.aria-label]=\"'comment.sort_label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"sort() === 'newest'\"\r\n [attr.aria-pressed]=\"sort() === 'newest'\"\r\n [flyTooltip]=\"'comment.sort_newest' | translate\"\r\n [attr.aria-label]=\"'comment.sort_newest' | translate\"\r\n (click)=\"onSortPick('newest')\">\r\n <i class=\"pi pi-sort-amount-down\" aria-hidden=\"true\"></i>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"sort() === 'oldest'\"\r\n [attr.aria-pressed]=\"sort() === 'oldest'\"\r\n [flyTooltip]=\"'comment.sort_oldest' | translate\"\r\n [attr.aria-label]=\"'comment.sort_oldest' | translate\"\r\n (click)=\"onSortPick('oldest')\">\r\n <i class=\"pi pi-sort-amount-up\" aria-hidden=\"true\"></i>\r\n </button>\r\n\r\n @if (canModerateThread() && !isReadonly()) {\r\n <span class=\"fly-comment-thread__toolbar-sep\" aria-hidden=\"true\"></span>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"isLocked()\"\r\n [attr.aria-pressed]=\"isLocked()\"\r\n [flyTooltip]=\"(isLocked() ? 'comment.unlock' : 'comment.lock') | translate\"\r\n [attr.aria-label]=\"(isLocked() ? 'comment.unlock' : 'comment.lock') | translate\"\r\n (click)=\"toggleLock()\">\r\n <i class=\"pi\" [class.pi-lock]=\"!isLocked()\" [class.pi-lock-open]=\"isLocked()\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n </div>\r\n </header>\r\n\r\n @if (isLocked()) {\r\n <p class=\"fly-comment-thread__locked-notice\">{{ 'comment.locked_notice' | translate }}</p>\r\n }\r\n\r\n <!-- \u2500\u2500 Root composer \u2500\u2500 -->\r\n @if (canReply()) {\r\n <div class=\"fly-comment-thread__composer\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [id]=\"fieldId('root-composer')\"\r\n [attr.aria-label]=\"'comment.composer_placeholder' | translate\"\r\n [placeholder]=\"'comment.composer_placeholder' | translate\"\r\n [ngModel]=\"rootDraft()\"\r\n (ngModelChange)=\"onRootDraftChange($event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__submit-btn\"\r\n [disabled]=\"!rootDraft().trim()\"\r\n (click)=\"submitRoot()\">\r\n {{ 'comment.post' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- \u2500\u2500 Root comments \u2500\u2500 -->\r\n @if (rootPage().items.length === 0) {\r\n <p class=\"fly-comment-thread__empty\">{{ 'comment.empty' | translate }}</p>\r\n } @else {\r\n <ul class=\"fly-comment-thread__list\" role=\"list\">\r\n @for (c of rootPage().items; track c.id) {\r\n <ng-container [ngTemplateOutlet]=\"commentNode\" [ngTemplateOutletContext]=\"{ $implicit: c }\"></ng-container>\r\n }\r\n </ul>\r\n\r\n @if (rootPage().hasMore) {\r\n <button type=\"button\" class=\"fly-comment-thread__load-more\" (click)=\"loadMoreRoot()\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 Recursive comment node template \u2500\u2500 -->\r\n<ng-template #commentNode let-comment>\r\n <li class=\"fly-comment-thread__item\" [attr.data-depth]=\"comment.depth\">\r\n <div class=\"fly-comment-thread__row\">\r\n <div class=\"fly-comment-thread__avatar\" aria-hidden=\"true\">\r\n @if (comment.authorAvatarUrl) {\r\n <img [src]=\"comment.authorAvatarUrl\" alt=\"\" />\r\n } @else {\r\n <span class=\"fly-comment-thread__avatar-fallback\">{{ authorInitial(comment) }}</span>\r\n }\r\n </div>\r\n\r\n <div class=\"fly-comment-thread__content\">\r\n <div class=\"fly-comment-thread__meta\">\r\n <span class=\"fly-comment-thread__author\">{{ authorLabel(comment) }}</span>\r\n <span class=\"fly-comment-thread__timestamp\">{{ formatDate(comment.createdAt) }}</span>\r\n @if (comment.isEdited && !comment.isDeleted) {\r\n <span class=\"fly-comment-thread__edited\">{{ 'comment.edited' | translate }}</span>\r\n }\r\n </div>\r\n\r\n @if (comment.isDeleted) {\r\n <p class=\"fly-comment-thread__tombstone\">{{ 'comment.deleted' | translate }}</p>\r\n } @else if (editingId() === comment.id) {\r\n <div class=\"fly-comment-thread__edit-box\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [ngModel]=\"comment.body\"\r\n (ngModelChange)=\"onEditDraftChange($event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"cancelEdit()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__submit-btn\" (click)=\"saveEdit(comment)\">\r\n {{ 'comment.save' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"fly-comment-thread__text-row\">\r\n <p class=\"fly-comment-thread__text\">{{ comment.body }}</p>\r\n @if (!isReadonly()) {\r\n <div class=\"fly-comment-thread__actions\">\r\n @if (canReply()) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.reply' | translate\"\r\n [attr.aria-label]=\"'comment.reply' | translate\"\r\n (click)=\"openReplyBox(comment.id)\">\r\n <i class=\"pi pi-reply\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canEditComment(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.edit' | translate\"\r\n [attr.aria-label]=\"'comment.edit' | translate\"\r\n (click)=\"startEdit(comment)\">\r\n <i class=\"pi pi-pencil\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canDeleteComment(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn fly-comment-thread__icon-btn--danger\"\r\n [flyTooltip]=\"'comment.delete' | translate\"\r\n [attr.aria-label]=\"'comment.delete' | translate\"\r\n (click)=\"requestDelete(comment)\">\r\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canReport(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.report' | translate\"\r\n [attr.aria-label]=\"'comment.report' | translate\"\r\n (click)=\"openReport(comment)\">\r\n <i class=\"pi pi-flag\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (confirmingDeleteId() === comment.id) {\r\n <div class=\"fly-comment-thread__confirm\">\r\n <span>{{ 'comment.delete_confirm' | translate }}</span>\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"cancelDelete()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__danger-btn\" (click)=\"confirmDelete(comment)\">\r\n {{ 'comment.delete' | translate }}\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (isReplyBoxOpen(comment.id)) {\r\n <div class=\"fly-comment-thread__composer fly-comment-thread__composer--reply\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"2\"\r\n [attr.aria-label]=\"'comment.reply_placeholder' | translate\"\r\n [placeholder]=\"'comment.reply_placeholder' | translate\"\r\n [ngModel]=\"replyDraft(comment.id)\"\r\n (ngModelChange)=\"onReplyDraftChange(comment.id, $event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"closeReplyBox(comment.id)\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__submit-btn\"\r\n [disabled]=\"!replyDraft(comment.id).trim()\"\r\n (click)=\"submitReply(comment.id)\">\r\n {{ 'comment.post' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (comment.replyCount > 0) {\r\n <button type=\"button\" class=\"fly-comment-thread__toggle-replies\" (click)=\"toggleReplies(comment)\">\r\n {{ (isExpanded(comment.id) ? 'comment.hide_replies' : 'comment.show_replies') | translate: { n: comment.replyCount } }}\r\n </button>\r\n }\r\n\r\n @if (isExpanded(comment.id)) {\r\n <ul class=\"fly-comment-thread__list fly-comment-thread__list--nested\" role=\"list\">\r\n @for (child of repliesFor(comment.id)?.items ?? []; track child.id) {\r\n <ng-container [ngTemplateOutlet]=\"commentNode\" [ngTemplateOutletContext]=\"{ $implicit: child }\"></ng-container>\r\n }\r\n </ul>\r\n @if (repliesFor(comment.id)?.hasMore) {\r\n <button type=\"button\" class=\"fly-comment-thread__load-more fly-comment-thread__load-more--nested\" (click)=\"loadMoreReplies(comment.id)\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </li>\r\n</ng-template>\r\n\r\n<!-- \u2500\u2500 Report dialog \u2500\u2500 -->\r\n@if (reportingId()) {\r\n <div class=\"fly-comment-thread__overlay\">\r\n <div class=\"fly-comment-thread__overlay-backdrop\" role=\"button\" tabindex=\"0\"\r\n [attr.aria-label]=\"'common.action.cancel' | translate\"\r\n (click)=\"closeReport()\"\r\n (keydown.enter)=\"closeReport()\"\r\n (keydown.space)=\"onOverlayBackdropSpace($event)\"></div>\r\n <div class=\"fly-comment-thread__dialog\" role=\"dialog\" [attr.aria-label]=\"'comment.report_title' | translate\">\r\n <h3 class=\"fly-comment-thread__dialog-title\">{{ 'comment.report_title' | translate }}</h3>\r\n\r\n <fieldset class=\"fly-comment-thread__reason-group\">\r\n <legend>{{ 'comment.report_reason_label' | translate }}</legend>\r\n @for (reason of reportReasons; track reason) {\r\n <label class=\"fly-comment-thread__reason-option\">\r\n <input\r\n type=\"radio\"\r\n name=\"fly-comment-report-reason\"\r\n [value]=\"reason\"\r\n [checked]=\"reportReason() === reason\"\r\n (change)=\"onReportReasonChange(reason)\" />\r\n <span>{{ 'comment.reason.' + reason | translate }}</span>\r\n </label>\r\n }\r\n </fieldset>\r\n\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [attr.aria-label]=\"'comment.report_detail_label' | translate\"\r\n [placeholder]=\"'comment.report_detail_label' | translate\"\r\n [ngModel]=\"reportDetail()\"\r\n (ngModelChange)=\"onReportDetailChange($event)\"></textarea>\r\n\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"closeReport()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__submit-btn\" [disabled]=\"!reportReason()\" (click)=\"submitReport()\">\r\n {{ 'comment.report_submit' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_text-tertiary: var(--label-tertiary, #94a3b8);--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-comment-thread__body{display:flex;flex-direction:column;gap:16px}.fly-comment-thread__header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.fly-comment-thread__count{font-weight:700;font-size:14px}.fly-comment-thread__toolbar{display:inline-flex;align-items:center;gap:2px;padding:2px;border:1px solid var(--_border);border-radius:calc(var(--_radius) + 2px);background:var(--_surface)}.fly-comment-thread__toolbar-sep{inline-size:1px;block-size:18px;margin-inline:2px;background:var(--_border)}.fly-comment-thread__icon-btn{display:inline-flex;align-items:center;justify-content:center;inline-size:26px;block-size:26px;flex:none;padding:0;border:none;border-radius:50%;background:transparent;color:var(--_text-subtle);cursor:pointer;transition:background var(--t-state, .15s),color var(--t-state, .15s)}.fly-comment-thread__icon-btn .pi{font-size:13px}.fly-comment-thread__icon-btn:hover{background:var(--_surface-hover);color:var(--_text)}.fly-comment-thread__icon-btn:focus-visible{outline:2px solid var(--_accent);outline-offset:1px}.fly-comment-thread__icon-btn--active{background:var(--_accent);color:#fff}.fly-comment-thread__icon-btn--active:hover{background:var(--_accent);opacity:.9}.fly-comment-thread__icon-btn--danger:hover{background:var(--_danger);color:#fff}.fly-comment-thread__locked-notice{margin:0;padding:8px 12px;border-radius:var(--_radius);background:var(--_fill);color:var(--_text-subtle);font-size:12px}.fly-comment-thread__empty{margin:0;color:var(--_text-subtle);text-align:center;padding:16px 0}.fly-comment-thread__composer{display:flex;flex-direction:column;gap:8px}.fly-comment-thread__composer--reply{margin-block-start:8px}.fly-comment-thread__textarea{inline-size:100%;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;line-height:1.5;resize:vertical}.fly-comment-thread__textarea:focus-visible{outline:2px solid var(--_accent);outline-offset:1px}.fly-comment-thread__composer-actions{display:flex;justify-content:flex-end;gap:8px}.fly-comment-thread__submit-btn{padding:6px 16px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__submit-btn:hover:not(:disabled){opacity:.9}.fly-comment-thread__submit-btn:disabled{opacity:.5;cursor:not-allowed}.fly-comment-thread__cancel-btn{padding:6px 14px;border:1px solid var(--_border);border-radius:var(--_radius);background:transparent;color:var(--_text-subtle);font:inherit;cursor:pointer}.fly-comment-thread__cancel-btn:hover{background:var(--_surface-hover)}.fly-comment-thread__danger-btn{padding:6px 14px;border:none;border-radius:var(--_radius);background:var(--_danger);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__danger-btn:hover{opacity:.9}.fly-comment-thread__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:14px}.fly-comment-thread__list--nested{margin-block-start:10px;margin-inline-start:20px;padding-inline-start:12px;border-inline-start:2px solid var(--_border);gap:12px}.fly-comment-thread__item{display:block}.fly-comment-thread__row{display:flex;gap:10px;align-items:flex-start}.fly-comment-thread__avatar{inline-size:32px;block-size:32px;border-radius:50%;overflow:hidden;flex:none;background:var(--_fill);display:flex;align-items:center;justify-content:center}.fly-comment-thread__avatar img{inline-size:100%;block-size:100%;object-fit:cover}.fly-comment-thread__avatar-fallback{font-weight:700;color:var(--_text-subtle);text-transform:uppercase}.fly-comment-thread__content{flex:1 1 auto;min-inline-size:0;display:flex;flex-direction:column;gap:4px}.fly-comment-thread__meta{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}.fly-comment-thread__author{font-weight:700;color:var(--_text)}.fly-comment-thread__timestamp{font-size:11px;color:var(--_text-tertiary)}.fly-comment-thread__edited{font-size:11px;color:var(--_text-tertiary);font-style:italic}.fly-comment-thread__text-row{display:flex;align-items:flex-start;gap:4px}.fly-comment-thread__text{flex:1 1 auto;min-inline-size:0;margin:0;color:var(--_text);line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}.fly-comment-thread__tombstone{margin:0;color:var(--_text-tertiary);font-style:italic}.fly-comment-thread__edit-box{display:flex;flex-direction:column;gap:6px}.fly-comment-thread__actions{display:flex;align-items:center;gap:2px;flex:none;margin-inline-start:auto}.fly-comment-thread__confirm{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:var(--_radius);background:var(--_fill);font-size:12px;color:var(--_text-subtle)}.fly-comment-thread__toggle-replies{align-self:flex-start;border:none;background:transparent;padding:0;margin-block-start:4px;color:var(--_accent);font:inherit;font-size:12px;font-weight:700;cursor:pointer}.fly-comment-thread__toggle-replies:hover{text-decoration:underline}.fly-comment-thread__load-more{align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:6px 14px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__load-more:hover{background:var(--_surface-hover)}.fly-comment-thread__load-more--nested{margin-inline-start:20px}.fly-comment-thread__overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:1000}.fly-comment-thread__overlay-backdrop{position:absolute;inset:0;background:#00000073;border:none;padding:0;margin:0;cursor:pointer}.fly-comment-thread__dialog{position:relative;z-index:1;inline-size:min(420px,90vw);max-block-size:85vh;overflow-y:auto;background:var(--_surface);border-radius:12px;padding:20px;display:flex;flex-direction:column;gap:14px;box-shadow:0 12px 32px #00000040}.fly-comment-thread__dialog-title{margin:0;font-size:16px;font-weight:700}.fly-comment-thread__reason-group{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;border:none}.fly-comment-thread__reason-group legend{font-weight:600;padding:0;margin-block-end:4px}.fly-comment-thread__reason-option{display:flex;align-items:center;gap:8px;cursor:pointer}.fly-comment-thread__reason-option input{accent-color:var(--_accent);cursor:pointer}:host(.fly-comment-thread--readonly) .fly-comment-thread__composer,:host(.fly-comment-thread--readonly) .fly-comment-thread__actions{display:none}\n"] }]
15045
+ }, template: "<div class=\"fly-comment-thread__body\">\r\n <!-- \u2500\u2500 Header: count + one combined sort/lock icon-button toolbar \u2500\u2500 -->\r\n <header class=\"fly-comment-thread__header\">\r\n <span class=\"fly-comment-thread__count\">\r\n {{ 'comment.count' | translate: { n: rootPage().total } }}\r\n </span>\r\n\r\n <div class=\"fly-comment-thread__toolbar\" role=\"group\" [attr.aria-label]=\"'comment.sort_label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"sort() === 'newest'\"\r\n [attr.aria-pressed]=\"sort() === 'newest'\"\r\n [flyTooltip]=\"'comment.sort_newest' | translate\"\r\n [attr.aria-label]=\"'comment.sort_newest' | translate\"\r\n (click)=\"onSortPick('newest')\">\r\n <i class=\"pi pi-sort-amount-down\" aria-hidden=\"true\"></i>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"sort() === 'oldest'\"\r\n [attr.aria-pressed]=\"sort() === 'oldest'\"\r\n [flyTooltip]=\"'comment.sort_oldest' | translate\"\r\n [attr.aria-label]=\"'comment.sort_oldest' | translate\"\r\n (click)=\"onSortPick('oldest')\">\r\n <i class=\"pi pi-sort-amount-up\" aria-hidden=\"true\"></i>\r\n </button>\r\n\r\n @if (canModerateThread() && !isReadonly()) {\r\n <span class=\"fly-comment-thread__toolbar-sep\" aria-hidden=\"true\"></span>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [class.fly-comment-thread__icon-btn--active]=\"isLocked()\"\r\n [attr.aria-pressed]=\"isLocked()\"\r\n [flyTooltip]=\"(isLocked() ? 'comment.unlock' : 'comment.lock') | translate\"\r\n [attr.aria-label]=\"(isLocked() ? 'comment.unlock' : 'comment.lock') | translate\"\r\n (click)=\"toggleLock()\">\r\n <i class=\"pi\" [class.pi-lock]=\"!isLocked()\" [class.pi-lock-open]=\"isLocked()\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n </div>\r\n </header>\r\n\r\n @if (isLocked()) {\r\n <p class=\"fly-comment-thread__locked-notice\">{{ 'comment.locked_notice' | translate }}</p>\r\n }\r\n\r\n <!-- \u2500\u2500 Root composer \u2500\u2500 -->\r\n @if (canReply()) {\r\n <div class=\"fly-comment-thread__composer\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [id]=\"fieldId('root-composer')\"\r\n [attr.aria-label]=\"'comment.composer_placeholder' | translate\"\r\n [placeholder]=\"'comment.composer_placeholder' | translate\"\r\n [ngModel]=\"rootDraft()\"\r\n (ngModelChange)=\"onRootDraftChange($event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__submit-btn\"\r\n [disabled]=\"!rootDraft().trim()\"\r\n (click)=\"submitRoot()\">\r\n {{ 'comment.post' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- \u2500\u2500 Root comments \u2500\u2500 -->\r\n @if (rootPage().items.length === 0) {\r\n <p class=\"fly-comment-thread__empty\">{{ 'comment.empty' | translate }}</p>\r\n } @else {\r\n <ul class=\"fly-comment-thread__list\" role=\"list\">\r\n @for (c of rootPage().items; track c.id) {\r\n <ng-container [ngTemplateOutlet]=\"commentNode\" [ngTemplateOutletContext]=\"{ $implicit: c }\"></ng-container>\r\n }\r\n </ul>\r\n\r\n @if (rootPage().hasMore) {\r\n <button type=\"button\" class=\"fly-comment-thread__load-more\" (click)=\"loadMoreRoot()\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 Recursive comment node template \u2500\u2500 -->\r\n<ng-template #commentNode let-comment>\r\n <li class=\"fly-comment-thread__item\" [attr.data-depth]=\"comment.depth\">\r\n <div class=\"fly-comment-thread__row\">\r\n <div class=\"fly-comment-thread__avatar\" aria-hidden=\"true\">\r\n @if (comment.authorAvatarUrl) {\r\n <img [src]=\"comment.authorAvatarUrl\" alt=\"\" />\r\n } @else {\r\n <span class=\"fly-comment-thread__avatar-fallback\">{{ authorInitial(comment) }}</span>\r\n }\r\n </div>\r\n\r\n <div class=\"fly-comment-thread__content\">\r\n <div class=\"fly-comment-thread__meta\">\r\n <span class=\"fly-comment-thread__author\">{{ authorLabel(comment) }}</span>\r\n <span class=\"fly-comment-thread__timestamp\">{{ formatDate(comment.createdAt) }}</span>\r\n @if (comment.isEdited && !comment.isDeleted) {\r\n <span class=\"fly-comment-thread__edited\">{{ 'comment.edited' | translate }}</span>\r\n }\r\n </div>\r\n\r\n @if (comment.isDeleted) {\r\n <p class=\"fly-comment-thread__tombstone\">{{ 'comment.deleted' | translate }}</p>\r\n } @else if (editingId() === comment.id) {\r\n <div class=\"fly-comment-thread__edit-box\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [ngModel]=\"comment.body\"\r\n (ngModelChange)=\"onEditDraftChange($event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"cancelEdit()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__submit-btn\" (click)=\"saveEdit(comment)\">\r\n {{ 'comment.save' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"fly-comment-thread__text-row\">\r\n <p class=\"fly-comment-thread__text\">{{ comment.body }}</p>\r\n @if (!isReadonly()) {\r\n <div class=\"fly-comment-thread__actions\">\r\n @if (canReply()) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.reply' | translate\"\r\n [attr.aria-label]=\"'comment.reply' | translate\"\r\n (click)=\"openReplyBox(comment.id)\">\r\n <i class=\"pi pi-reply\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canEditComment(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.edit' | translate\"\r\n [attr.aria-label]=\"'comment.edit' | translate\"\r\n (click)=\"startEdit(comment)\">\r\n <i class=\"pi pi-pencil\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canDeleteComment(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn fly-comment-thread__icon-btn--danger\"\r\n [flyTooltip]=\"'comment.delete' | translate\"\r\n [attr.aria-label]=\"'comment.delete' | translate\"\r\n (click)=\"requestDelete(comment)\">\r\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n @if (canReport(comment)) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__icon-btn\"\r\n [flyTooltip]=\"'comment.report' | translate\"\r\n [attr.aria-label]=\"'comment.report' | translate\"\r\n (click)=\"openReport(comment)\">\r\n <i class=\"pi pi-flag\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (confirmingDeleteId() === comment.id) {\r\n <div class=\"fly-comment-thread__confirm\">\r\n <span>{{ 'comment.delete_confirm' | translate }}</span>\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"cancelDelete()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__danger-btn\" (click)=\"confirmDelete(comment)\">\r\n {{ 'comment.delete' | translate }}\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (isReplyBoxOpen(comment.id)) {\r\n <div class=\"fly-comment-thread__composer fly-comment-thread__composer--reply\">\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"2\"\r\n [attr.aria-label]=\"'comment.reply_placeholder' | translate\"\r\n [placeholder]=\"'comment.reply_placeholder' | translate\"\r\n [ngModel]=\"replyDraft(comment.id)\"\r\n (ngModelChange)=\"onReplyDraftChange(comment.id, $event)\"></textarea>\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"closeReplyBox(comment.id)\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-comment-thread__submit-btn\"\r\n [disabled]=\"!replyDraft(comment.id).trim()\"\r\n (click)=\"submitReply(comment.id)\">\r\n {{ 'comment.post' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (comment.replyCount > 0) {\r\n <button type=\"button\" class=\"fly-comment-thread__toggle-replies\" (click)=\"toggleReplies(comment)\">\r\n {{ (isExpanded(comment.id) ? 'comment.hide_replies' : 'comment.show_replies') | translate: { n: comment.replyCount } }}\r\n </button>\r\n }\r\n\r\n @if (isExpanded(comment.id)) {\r\n <ul class=\"fly-comment-thread__list fly-comment-thread__list--nested\" role=\"list\">\r\n @for (child of repliesFor(comment.id)?.items ?? []; track child.id) {\r\n <ng-container [ngTemplateOutlet]=\"commentNode\" [ngTemplateOutletContext]=\"{ $implicit: child }\"></ng-container>\r\n }\r\n </ul>\r\n @if (repliesFor(comment.id)?.hasMore) {\r\n <button type=\"button\" class=\"fly-comment-thread__load-more fly-comment-thread__load-more--nested\" (click)=\"loadMoreReplies(comment.id)\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </li>\r\n</ng-template>\r\n\r\n<!-- \u2500\u2500 Report dialog \u2500\u2500 -->\r\n@if (reportingId()) {\r\n <div class=\"fly-comment-thread__overlay\">\r\n <div class=\"fly-comment-thread__overlay-backdrop\" role=\"button\" tabindex=\"0\"\r\n [attr.aria-label]=\"'common.action.cancel' | translate\"\r\n (click)=\"closeReport()\"\r\n (keydown.enter)=\"closeReport()\"\r\n (keydown.space)=\"onOverlayBackdropSpace($event)\"></div>\r\n <div class=\"fly-comment-thread__dialog\" role=\"dialog\" [attr.aria-label]=\"'comment.report_title' | translate\">\r\n <h3 class=\"fly-comment-thread__dialog-title\">{{ 'comment.report_title' | translate }}</h3>\r\n\r\n <fieldset class=\"fly-comment-thread__reason-group\">\r\n <legend>{{ 'comment.report_reason_label' | translate }}</legend>\r\n @for (reason of reportReasons; track reason) {\r\n <label class=\"fly-comment-thread__reason-option\">\r\n <input\r\n type=\"radio\"\r\n name=\"fly-comment-report-reason\"\r\n [value]=\"reason\"\r\n [checked]=\"reportReason() === reason\"\r\n (change)=\"onReportReasonChange(reason)\" />\r\n <span>{{ 'comment.reason.' + reason | translate }}</span>\r\n </label>\r\n }\r\n </fieldset>\r\n\r\n <textarea\r\n class=\"fly-comment-thread__textarea\"\r\n rows=\"3\"\r\n [attr.aria-label]=\"'comment.report_detail_label' | translate\"\r\n [placeholder]=\"'comment.report_detail_label' | translate\"\r\n [ngModel]=\"reportDetail()\"\r\n (ngModelChange)=\"onReportDetailChange($event)\"></textarea>\r\n\r\n <div class=\"fly-comment-thread__composer-actions\">\r\n <button type=\"button\" class=\"fly-comment-thread__cancel-btn\" (click)=\"closeReport()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-comment-thread__submit-btn\" [disabled]=\"!reportReason()\" (click)=\"submitReport()\">\r\n {{ 'comment.report_submit' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_text-tertiary: var(--label-tertiary, #94a3b8);--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-comment-thread__body{display:flex;flex-direction:column;gap:16px}.fly-comment-thread__header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.fly-comment-thread__count{font-weight:700;font-size:14px}.fly-comment-thread__toolbar{display:inline-flex;align-items:center;gap:2px;padding:2px;border:1px solid var(--_border);border-radius:calc(var(--_radius) + 2px);background:var(--_surface)}.fly-comment-thread__toolbar-sep{inline-size:1px;block-size:18px;margin-inline:2px;background:var(--_border)}.fly-comment-thread__icon-btn{display:inline-flex;align-items:center;justify-content:center;inline-size:26px;block-size:26px;flex:none;padding:0;border:none;border-radius:50%;background:transparent;color:var(--_text-subtle);cursor:pointer;transition:background var(--t-state, .15s),color var(--t-state, .15s)}.fly-comment-thread__icon-btn .pi{font-size:13px}.fly-comment-thread__icon-btn:hover{background:var(--_surface-hover);color:var(--_text)}.fly-comment-thread__icon-btn:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:1px}.fly-comment-thread__icon-btn--active{background:var(--_accent);color:#fff}.fly-comment-thread__icon-btn--active:hover{background:var(--_accent);opacity:.9}.fly-comment-thread__icon-btn--danger:hover{background:var(--_danger);color:#fff}.fly-comment-thread__locked-notice{margin:0;padding:8px 12px;border-radius:var(--_radius);background:var(--_fill);color:var(--_text-subtle);font-size:12px}.fly-comment-thread__empty{margin:0;color:var(--_text-subtle);text-align:center;padding:16px 0}.fly-comment-thread__composer{display:flex;flex-direction:column;gap:8px}.fly-comment-thread__composer--reply{margin-block-start:8px}.fly-comment-thread__textarea{inline-size:100%;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;line-height:1.5;resize:vertical}.fly-comment-thread__textarea:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:1px}.fly-comment-thread__composer-actions{display:flex;justify-content:flex-end;gap:8px}.fly-comment-thread__submit-btn{padding:6px 16px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__submit-btn:hover:not(:disabled){opacity:.9}.fly-comment-thread__submit-btn:disabled{opacity:.5;cursor:not-allowed}.fly-comment-thread__cancel-btn{padding:6px 14px;border:1px solid var(--_border);border-radius:var(--_radius);background:transparent;color:var(--_text-subtle);font:inherit;cursor:pointer}.fly-comment-thread__cancel-btn:hover{background:var(--_surface-hover)}.fly-comment-thread__danger-btn{padding:6px 14px;border:none;border-radius:var(--_radius);background:var(--_danger);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__danger-btn:hover{opacity:.9}.fly-comment-thread__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:14px}.fly-comment-thread__list--nested{margin-block-start:10px;margin-inline-start:20px;padding-inline-start:12px;border-inline-start:2px solid var(--_border);gap:12px}.fly-comment-thread__item{display:block}.fly-comment-thread__row{display:flex;gap:10px;align-items:flex-start}.fly-comment-thread__avatar{inline-size:32px;block-size:32px;border-radius:50%;overflow:hidden;flex:none;background:var(--_fill);display:flex;align-items:center;justify-content:center}.fly-comment-thread__avatar img{inline-size:100%;block-size:100%;object-fit:cover}.fly-comment-thread__avatar-fallback{font-weight:700;color:var(--_text-subtle);text-transform:uppercase}.fly-comment-thread__content{flex:1 1 auto;min-inline-size:0;display:flex;flex-direction:column;gap:4px}.fly-comment-thread__meta{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}.fly-comment-thread__author{font-weight:700;color:var(--_text)}.fly-comment-thread__timestamp{font-size:11px;color:var(--_text-tertiary)}.fly-comment-thread__edited{font-size:11px;color:var(--_text-tertiary);font-style:italic}.fly-comment-thread__text-row{display:flex;align-items:flex-start;gap:4px}.fly-comment-thread__text{flex:1 1 auto;min-inline-size:0;margin:0;color:var(--_text);line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}.fly-comment-thread__tombstone{margin:0;color:var(--_text-tertiary);font-style:italic}.fly-comment-thread__edit-box{display:flex;flex-direction:column;gap:6px}.fly-comment-thread__actions{display:flex;align-items:center;gap:2px;flex:none;margin-inline-start:auto}.fly-comment-thread__confirm{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:var(--_radius);background:var(--_fill);font-size:12px;color:var(--_text-subtle)}.fly-comment-thread__toggle-replies{align-self:flex-start;border:none;background:transparent;padding:0;margin-block-start:4px;color:var(--_accent);font:inherit;font-size:12px;font-weight:700;cursor:pointer}.fly-comment-thread__toggle-replies:hover{text-decoration:underline}.fly-comment-thread__load-more{align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:6px 14px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}.fly-comment-thread__load-more:hover{background:var(--_surface-hover)}.fly-comment-thread__load-more--nested{margin-inline-start:20px}.fly-comment-thread__overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:1000}.fly-comment-thread__overlay-backdrop{position:absolute;inset:0;background:#00000073;border:none;padding:0;margin:0;cursor:pointer}.fly-comment-thread__dialog{position:relative;z-index:1;inline-size:min(420px,90vw);max-block-size:85vh;overflow-y:auto;background:var(--_surface);border-radius:12px;padding:20px;display:flex;flex-direction:column;gap:14px;box-shadow:0 12px 32px #00000040}.fly-comment-thread__dialog-title{margin:0;font-size:16px;font-weight:700}.fly-comment-thread__reason-group{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;border:none}.fly-comment-thread__reason-group legend{font-weight:600;padding:0;margin-block-end:4px}.fly-comment-thread__reason-option{display:flex;align-items:center;gap:8px;cursor:pointer}.fly-comment-thread__reason-option input{accent-color:var(--_accent);cursor:pointer}:host(.fly-comment-thread--readonly) .fly-comment-thread__composer,:host(.fly-comment-thread--readonly) .fly-comment-thread__actions{display:none}\n"] }]
15046
15046
  }], propDecorators: { rootPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "rootPage", required: true }] }], repliesByParent: [{ type: i0.Input, args: [{ isSignal: true, alias: "repliesByParent", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], isLocked: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLocked", required: false }] }], currentUserId: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentUserId", required: false }] }], isReadonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], canModerateThread: [{ type: i0.Input, args: [{ isSignal: true, alias: "canModerateThread", required: false }] }], resolveDisplayName: [{ type: i0.Input, args: [{ isSignal: true, alias: "resolveDisplayName", required: false }] }], loadReplies: [{ type: i0.Output, args: ["loadReplies"] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], submit: [{ type: i0.Output, args: ["submit"] }], edit: [{ type: i0.Output, args: ["edit"] }], delete: [{ type: i0.Output, args: ["delete"] }], report: [{ type: i0.Output, args: ["report"] }], lockToggle: [{ type: i0.Output, args: ["lockToggle"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }] } });
15047
15047
 
15048
15048
  // ── Vendored synchronous SHA-256 (FIPS 180-4) ────────────────────────────────
@@ -17670,13 +17670,13 @@ class FlyMagicActionsComponent {
17670
17670
  this.isOverflowing.set(!!el && el.scrollWidth - el.clientWidth > 1);
17671
17671
  }
17672
17672
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyMagicActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
17673
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyMagicActionsComponent, isStandalone: true, selector: "fly-magic-actions", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: true, transformFunction: null }, primary: { classPropertyName: "primary", publicName: "primary", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.dir": "i18n.direction()" } }, viewQueries: [{ propertyName: "rowRef", first: true, predicate: ["row"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n Icon-only buttons carry the accessible name via [attr.aria-label] \u2014 the SVG\r\n glyph itself is aria-hidden (decorative, skill \u00A7accessibility rule 5). `kind:\r\n 'text'` actions rely on their own visible text instead. Disabled rows stay\r\n `aria-disabled` (never native `disabled`) so they remain focusable/hoverable \u2014\r\n a disabled action's whole point is to explain ITSELF via the auto-suffixed\r\n tooltip, which native `disabled` would suppress.\r\n\r\n The glyph is composed from ALLOWLISTED nodes bound as real attributes, never\r\n from `[innerHTML]`: `iconPath` is publisher-supplied, and an `<svg>` fragment\r\n is not a closed world (`<foreignObject>` is an HTML integration point, `<a\r\n xlink:href=\"javascript:\u2026\">` is live under the very click this button invites).\r\n `magic-actions-icon.ts` carries the full rationale; the shape below is its\r\n consequence \u2014 an attribute binding cannot introduce an element or a handler,\r\n so there is nothing left to sanitize.\r\n\r\n That block is authored ONCE, as `#actionButton`, and stamped by every place a\r\n contributed action is painted (group items and `primary`). It used to be\r\n inline in the group loop, which was fine while this component rendered groups\r\n only; with `primary` here too, a second copy would mean the next edit to the\r\n SECURITY-CRITICAL binding shape has to be made twice and can be made once.\r\n-->\r\n<!--\r\n `data-action` carries the publisher's action `id` verbatim \u2014 the one stable, LOCALE-INDEPENDENT\r\n handle on a rendered action. Every other identifying attribute here is translated\r\n (`aria-label`, the tooltip), so an e2e suite that targeted them had to assert in one language,\r\n and one that targeted a bespoke button lost its hook entirely when the action moved into the\r\n bar. That is not hypothetical: PPM's project-closure suite could not adopt the contract for\r\n exactly this reason. It is an ATTRIBUTE, not a class, so it never participates in styling, and\r\n `id` is already unique across the whole contribution (the projection enforces it), so it is\r\n unique in the DOM too.\r\n-->\r\n<ng-template #actionButton let-projected>\r\n <!--\r\n `let-projected` is `any` \u2014 Angular infers nothing for an `ngTemplateOutlet`\r\n context, and there is no built-in way to declare one. `asAction` is an\r\n identity function whose only job is to give this block a TYPED local, so\r\n every read below (`.kind`, `.disabled`, `.menu`) is checked by the template\r\n compiler instead of silently resolving to `undefined` on a typo. Without it\r\n the one place a `MagicBarActionView` is actually painted would be the one\r\n place its shape is not verified.\r\n -->\r\n @let action = asAction(projected);\r\n @if (action.kind === 'text') {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn fma-btn--text\"\r\n [attr.data-action]=\"action.id\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >{{ resolvedLabel(action) }}</button>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn\"\r\n [class.fma-btn--badge]=\"hasBadge(action)\"\r\n [attr.data-action]=\"action.id\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [attr.aria-haspopup]=\"action.menu ? 'menu' : null\"\r\n [attr.aria-expanded]=\"action.menu ? (openMenuActionId() === action.id ? 'true' : 'false') : null\"\r\n [attr.aria-label]=\"action.menu ? triggerAriaLabel(action) : resolvedLabel(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >\r\n <svg\r\n class=\"fma-btn__icon\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.8\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n @for (node of iconNodes(action); track $index) {\r\n @switch (node.tag) {\r\n @case ('path') {\r\n <svg:path\r\n [attr.d]=\"node.attrs['d']\"\r\n [attr.fill-rule]=\"node.attrs['fill-rule']\"\r\n [attr.clip-rule]=\"node.attrs['clip-rule']\"\r\n />\r\n }\r\n @case ('circle') {\r\n <svg:circle\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.r]=\"node.attrs['r']\"\r\n />\r\n }\r\n @case ('rect') {\r\n <svg:rect\r\n [attr.x]=\"node.attrs['x']\"\r\n [attr.y]=\"node.attrs['y']\"\r\n [attr.width]=\"node.attrs['width']\"\r\n [attr.height]=\"node.attrs['height']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('ellipse') {\r\n <svg:ellipse\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('line') {\r\n <svg:line\r\n [attr.x1]=\"node.attrs['x1']\"\r\n [attr.y1]=\"node.attrs['y1']\"\r\n [attr.x2]=\"node.attrs['x2']\"\r\n [attr.y2]=\"node.attrs['y2']\"\r\n />\r\n }\r\n @case ('polyline') {\r\n <svg:polyline [attr.points]=\"node.attrs['points']\" />\r\n }\r\n @case ('polygon') {\r\n <svg:polygon [attr.points]=\"node.attrs['points']\" />\r\n }\r\n }\r\n }\r\n </svg>\r\n @if (hasBadge(action)) {\r\n <span class=\"fma-btn__badge\" aria-hidden=\"true\"></span>\r\n }\r\n </button>\r\n }\r\n</ng-template>\r\n\r\n<!--\r\n `.fma` is the SCROLLING row and holds the contributed groups only. The accent\r\n CTA is a SIBLING of it, outside the fade mask and outside the scroll container,\r\n because it is the row's anchor \u2014 a call to action that dissolves into a\r\n gradient, or that you have to scroll sideways to reach, inverts the affordance.\r\n It is also what makes `isOverflowing` measurable at all: see the component.\r\n-->\r\n@if (groups().length) {\r\n <div #row class=\"fma\" [class.fma--overflow]=\"isOverflowing()\">\r\n @for (group of groups(); track group.id) {\r\n <div\r\n class=\"fma-group\"\r\n [class.fma-group--framed]=\"group.framed\"\r\n role=\"group\"\r\n [attr.aria-label]=\"i18n.t(group.labelKey)\"\r\n >\r\n @for (action of group.items; track action.id) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: action }\"\r\n />\r\n }\r\n </div>\r\n @if (group.framed) {\r\n <span class=\"fma-sep\" aria-hidden=\"true\"></span>\r\n }\r\n }\r\n </div>\r\n}\r\n\r\n<!--\r\n The accent CTA. The disc is a WRAPPER, not a modifier on the button, and that\r\n is load-bearing rather than cosmetic: `.fma-btn`'s hover/press feedback is an\r\n `animation` (`iconWiggle` / `iconBounce`), and an animation that touches\r\n `transform` beats a declared `transform` \u2014 so a hover lift authored on the\r\n button itself would simply never render. The wrapper owns the disc, the lift\r\n and the shadow; the button stays transparent and keeps the DS's own toolbar\r\n feedback. It re-points `--chrome-ink` rather than styling `.fma-btn` through a\r\n descendant selector so the glyph colour inherits the way custom properties do.\r\n-->\r\n@if (primary(); as p) {\r\n <span class=\"fma-primary\" [class.fma-primary--disabled]=\"p.disabled\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: p }\"\r\n />\r\n </span>\r\n}\r\n\r\n<!--\r\n ONE radio menu, hoisted out of the group loops (S1-review F9). Only one is open\r\n at a time (`openMenuActionId`), so a single instance is enough \u2014 and rendering\r\n it beside its button would insert a non-`.fma-btn` element into the group,\r\n silently shifting every later button's `:nth-child` index and with it the\r\n `toolbarPopIn` stagger delay the `.fma-btn` rule assigns. Keeping every\r\n staggered parent's children homogeneous is what makes that rule's comment true.\r\n It portals itself to <body>, so its position is unaffected by where it is\r\n declared.\r\n-->\r\n@if (openAction(); as open) {\r\n <fly-context-menu\r\n [anchor]=\"menuAnchorEl()\"\r\n [sections]=\"menuSections(open)\"\r\n (action)=\"onMenuAction(open, $event)\"\r\n (closed)=\"closeMenu()\"\r\n />\r\n}\r\n", styles: [":host{display:flex;align-items:center;gap:8px;min-inline-size:0}.fma{display:flex;align-items:center;gap:8px;flex:0 1 auto;min-inline-size:0;overflow:hidden;flex-wrap:nowrap}.fma--overflow{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%)}.fma--overflow::-webkit-scrollbar{display:none}:host([dir=rtl]) .fma--overflow{-webkit-mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%)}.fma-group{display:flex;align-items:center;gap:8px;flex:none}.fma-group--framed{gap:2px}.fma-sep{flex:0 0 auto;inline-size:1px;block-size:18px;background:var(--w14)}.fma-btn{position:relative;flex:0 0 auto;inline-size:30px;block-size:30px;display:grid;place-items:center;border:0;border-radius:50%;background:transparent;color:var(--chrome-ink);cursor:pointer;padding:0;animation:toolbarPopIn .3s var(--nova-ease-structural) both}.fma-btn:nth-child(1){animation-delay:0ms}.fma-btn:nth-child(2){animation-delay:40ms}.fma-btn:nth-child(3){animation-delay:80ms}.fma-btn:nth-child(4){animation-delay:.12s}.fma-btn:nth-child(5){animation-delay:.16s}.fma-btn:nth-child(6){animation-delay:.2s}.fma-btn:nth-child(7){animation-delay:.24s}.fma-btn:nth-child(8){animation-delay:.28s}.fma-btn:nth-child(9){animation-delay:.32s}.fma-btn:nth-child(10){animation-delay:.36s}.fma-btn:nth-child(11){animation-delay:.4s}.fma-btn:nth-child(12){animation-delay:.44s}.fma-btn:nth-child(n+13){animation-delay:.44s}.fma-btn:not([aria-disabled=true]):hover{background:var(--w1);color:var(--chrome-ink-hover);animation:iconWiggle .5s ease}.fma-btn:not([aria-disabled=true]):active{animation:iconBounce .38s var(--nova-ease-overshoot)}.fma-btn:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:inherit}.fma-btn[data-tone=danger]{color:var(--sys-red)}.fma-btn[data-tone=danger]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.fma-btn[data-tone=success]{color:var(--sys-green)}.fma-btn[data-tone=success]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-green) 18%,transparent);color:var(--sys-green)}.fma-btn[aria-pressed=true]{background:var(--tint-sel);color:var(--chrome-ink-hover)}.fma-btn[aria-pressed=true][data-tone=success]{background:color-mix(in oklab,var(--sys-green) 22%,transparent);color:var(--sys-green)}.fma-btn[aria-disabled=true]{opacity:.38;filter:saturate(.6);animation:none;cursor:default}.fma-btn__icon{inline-size:16px;block-size:16px;pointer-events:none}.fma-btn__badge{position:absolute;inset-block-start:3px;inset-inline-end:3px;inline-size:7px;block-size:7px;border-radius:50%;background:var(--accent);pointer-events:none}.fma-primary{--chrome-ink: var(--on-accent);--chrome-ink-hover: var(--on-accent);flex:none;display:grid;place-items:center;inline-size:30px;block-size:30px;border-radius:50%;background:var(--accent);transition:box-shadow var(--nova-duration-hover) var(--nova-ease-micro),transform var(--nova-duration-hover) var(--nova-ease-micro)}.fma-primary:hover{box-shadow:0 8px 20px var(--tint-sel);transform:translateY(-1px)}.fma-primary--disabled{opacity:.38;filter:saturate(.6)}.fma-primary--disabled:hover{box-shadow:none;transform:none}.fma-btn--text{inline-size:auto;block-size:30px;border-radius:99px;padding-inline:12px;font-family:inherit;font-size:12.5px;font-weight:600;line-height:1;white-space:nowrap}@media(pointer:coarse){.fma-btn{inline-size:44px;block-size:44px}.fma-btn--text{inline-size:auto;min-inline-size:44px}.fma-primary{inline-size:44px;block-size:44px}}\n"], dependencies: [{ kind: "component", type: ContextMenuComponent, selector: "fly-context-menu", inputs: ["x", "y", "anchor", "align", "placement", "sections", "boundary"], outputs: ["action", "closed"] }, { kind: "directive", type: FlyTooltipDirective, selector: "[flyTooltip], [data-tooltip]", inputs: ["flyTooltip", "flyTooltipPlacement", "flyTooltipDisabled", "flyTooltipDelay"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
17673
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyMagicActionsComponent, isStandalone: true, selector: "fly-magic-actions", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: true, transformFunction: null }, primary: { classPropertyName: "primary", publicName: "primary", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.dir": "i18n.direction()" } }, viewQueries: [{ propertyName: "rowRef", first: true, predicate: ["row"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n Icon-only buttons carry the accessible name via [attr.aria-label] \u2014 the SVG\r\n glyph itself is aria-hidden (decorative, skill \u00A7accessibility rule 5). `kind:\r\n 'text'` actions rely on their own visible text instead. Disabled rows stay\r\n `aria-disabled` (never native `disabled`) so they remain focusable/hoverable \u2014\r\n a disabled action's whole point is to explain ITSELF via the auto-suffixed\r\n tooltip, which native `disabled` would suppress.\r\n\r\n The glyph is composed from ALLOWLISTED nodes bound as real attributes, never\r\n from `[innerHTML]`: `iconPath` is publisher-supplied, and an `<svg>` fragment\r\n is not a closed world (`<foreignObject>` is an HTML integration point, `<a\r\n xlink:href=\"javascript:\u2026\">` is live under the very click this button invites).\r\n `magic-actions-icon.ts` carries the full rationale; the shape below is its\r\n consequence \u2014 an attribute binding cannot introduce an element or a handler,\r\n so there is nothing left to sanitize.\r\n\r\n That block is authored ONCE, as `#actionButton`, and stamped by every place a\r\n contributed action is painted (group items and `primary`). It used to be\r\n inline in the group loop, which was fine while this component rendered groups\r\n only; with `primary` here too, a second copy would mean the next edit to the\r\n SECURITY-CRITICAL binding shape has to be made twice and can be made once.\r\n-->\r\n<!--\r\n `data-action` carries the publisher's action `id` verbatim \u2014 the one stable, LOCALE-INDEPENDENT\r\n handle on a rendered action. Every other identifying attribute here is translated\r\n (`aria-label`, the tooltip), so an e2e suite that targeted them had to assert in one language,\r\n and one that targeted a bespoke button lost its hook entirely when the action moved into the\r\n bar. That is not hypothetical: PPM's project-closure suite could not adopt the contract for\r\n exactly this reason. It is an ATTRIBUTE, not a class, so it never participates in styling, and\r\n `id` is already unique across the whole contribution (the projection enforces it), so it is\r\n unique in the DOM too.\r\n-->\r\n<ng-template #actionButton let-projected>\r\n <!--\r\n `let-projected` is `any` \u2014 Angular infers nothing for an `ngTemplateOutlet`\r\n context, and there is no built-in way to declare one. `asAction` is an\r\n identity function whose only job is to give this block a TYPED local, so\r\n every read below (`.kind`, `.disabled`, `.menu`) is checked by the template\r\n compiler instead of silently resolving to `undefined` on a typo. Without it\r\n the one place a `MagicBarActionView` is actually painted would be the one\r\n place its shape is not verified.\r\n -->\r\n @let action = asAction(projected);\r\n @if (action.kind === 'text') {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn fma-btn--text\"\r\n [attr.data-action]=\"action.id\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >{{ resolvedLabel(action) }}</button>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn\"\r\n [class.fma-btn--badge]=\"hasBadge(action)\"\r\n [attr.data-action]=\"action.id\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [attr.aria-haspopup]=\"action.menu ? 'menu' : null\"\r\n [attr.aria-expanded]=\"action.menu ? (openMenuActionId() === action.id ? 'true' : 'false') : null\"\r\n [attr.aria-label]=\"action.menu ? triggerAriaLabel(action) : resolvedLabel(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >\r\n <svg\r\n class=\"fma-btn__icon\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.8\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n @for (node of iconNodes(action); track $index) {\r\n @switch (node.tag) {\r\n @case ('path') {\r\n <svg:path\r\n [attr.d]=\"node.attrs['d']\"\r\n [attr.fill-rule]=\"node.attrs['fill-rule']\"\r\n [attr.clip-rule]=\"node.attrs['clip-rule']\"\r\n />\r\n }\r\n @case ('circle') {\r\n <svg:circle\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.r]=\"node.attrs['r']\"\r\n />\r\n }\r\n @case ('rect') {\r\n <svg:rect\r\n [attr.x]=\"node.attrs['x']\"\r\n [attr.y]=\"node.attrs['y']\"\r\n [attr.width]=\"node.attrs['width']\"\r\n [attr.height]=\"node.attrs['height']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('ellipse') {\r\n <svg:ellipse\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('line') {\r\n <svg:line\r\n [attr.x1]=\"node.attrs['x1']\"\r\n [attr.y1]=\"node.attrs['y1']\"\r\n [attr.x2]=\"node.attrs['x2']\"\r\n [attr.y2]=\"node.attrs['y2']\"\r\n />\r\n }\r\n @case ('polyline') {\r\n <svg:polyline [attr.points]=\"node.attrs['points']\" />\r\n }\r\n @case ('polygon') {\r\n <svg:polygon [attr.points]=\"node.attrs['points']\" />\r\n }\r\n }\r\n }\r\n </svg>\r\n @if (hasBadge(action)) {\r\n <span class=\"fma-btn__badge\" aria-hidden=\"true\"></span>\r\n }\r\n </button>\r\n }\r\n</ng-template>\r\n\r\n<!--\r\n `.fma` is the SCROLLING row and holds the contributed groups only. The accent\r\n CTA is a SIBLING of it, outside the fade mask and outside the scroll container,\r\n because it is the row's anchor \u2014 a call to action that dissolves into a\r\n gradient, or that you have to scroll sideways to reach, inverts the affordance.\r\n It is also what makes `isOverflowing` measurable at all: see the component.\r\n-->\r\n@if (groups().length) {\r\n <div #row class=\"fma\" [class.fma--overflow]=\"isOverflowing()\">\r\n @for (group of groups(); track group.id) {\r\n <div\r\n class=\"fma-group\"\r\n [class.fma-group--framed]=\"group.framed\"\r\n role=\"group\"\r\n [attr.aria-label]=\"i18n.t(group.labelKey)\"\r\n >\r\n @for (action of group.items; track action.id) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: action }\"\r\n />\r\n }\r\n </div>\r\n @if (group.framed) {\r\n <span class=\"fma-sep\" aria-hidden=\"true\"></span>\r\n }\r\n }\r\n </div>\r\n}\r\n\r\n<!--\r\n The accent CTA. The disc is a WRAPPER, not a modifier on the button, and that\r\n is load-bearing rather than cosmetic: `.fma-btn`'s hover/press feedback is an\r\n `animation` (`iconWiggle` / `iconBounce`), and an animation that touches\r\n `transform` beats a declared `transform` \u2014 so a hover lift authored on the\r\n button itself would simply never render. The wrapper owns the disc, the lift\r\n and the shadow; the button stays transparent and keeps the DS's own toolbar\r\n feedback. It re-points `--chrome-ink` rather than styling `.fma-btn` through a\r\n descendant selector so the glyph colour inherits the way custom properties do.\r\n-->\r\n@if (primary(); as p) {\r\n <span class=\"fma-primary\" [class.fma-primary--disabled]=\"p.disabled\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: p }\"\r\n />\r\n </span>\r\n}\r\n\r\n<!--\r\n ONE radio menu, hoisted out of the group loops (S1-review F9). Only one is open\r\n at a time (`openMenuActionId`), so a single instance is enough \u2014 and rendering\r\n it beside its button would insert a non-`.fma-btn` element into the group,\r\n silently shifting every later button's `:nth-child` index and with it the\r\n `toolbarPopIn` stagger delay the `.fma-btn` rule assigns. Keeping every\r\n staggered parent's children homogeneous is what makes that rule's comment true.\r\n It portals itself to <body>, so its position is unaffected by where it is\r\n declared.\r\n-->\r\n@if (openAction(); as open) {\r\n <fly-context-menu\r\n [anchor]=\"menuAnchorEl()\"\r\n [sections]=\"menuSections(open)\"\r\n (action)=\"onMenuAction(open, $event)\"\r\n (closed)=\"closeMenu()\"\r\n />\r\n}\r\n", styles: [":host{display:flex;align-items:center;gap:8px;min-inline-size:0}.fma{display:flex;align-items:center;gap:8px;flex:0 1 auto;min-inline-size:0;overflow:hidden;flex-wrap:nowrap}.fma--overflow{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%)}.fma--overflow::-webkit-scrollbar{display:none}:host([dir=rtl]) .fma--overflow{-webkit-mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%)}.fma-group{display:flex;align-items:center;gap:8px;flex:none}.fma-group--framed{gap:2px}.fma-sep{flex:0 0 auto;inline-size:1px;block-size:18px;background:var(--w14)}.fma-btn{position:relative;flex:0 0 auto;inline-size:30px;block-size:30px;display:grid;place-items:center;border:0;border-radius:50%;background:transparent;color:var(--chrome-ink);cursor:pointer;padding:0;animation:toolbarPopIn .3s var(--nova-ease-structural) both}.fma-btn:nth-child(1){animation-delay:0ms}.fma-btn:nth-child(2){animation-delay:40ms}.fma-btn:nth-child(3){animation-delay:80ms}.fma-btn:nth-child(4){animation-delay:.12s}.fma-btn:nth-child(5){animation-delay:.16s}.fma-btn:nth-child(6){animation-delay:.2s}.fma-btn:nth-child(7){animation-delay:.24s}.fma-btn:nth-child(8){animation-delay:.28s}.fma-btn:nth-child(9){animation-delay:.32s}.fma-btn:nth-child(10){animation-delay:.36s}.fma-btn:nth-child(11){animation-delay:.4s}.fma-btn:nth-child(12){animation-delay:.44s}.fma-btn:nth-child(n+13){animation-delay:.44s}.fma-btn:not([aria-disabled=true]):hover{background:var(--w1);color:var(--chrome-ink-hover);animation:iconWiggle .5s ease}.fma-btn:not([aria-disabled=true]):active{animation:iconBounce .38s var(--nova-ease-overshoot)}.fma-btn:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px;border-radius:inherit}.fma-btn[data-tone=danger]{color:var(--sys-red)}.fma-btn[data-tone=danger]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.fma-btn[data-tone=success]{color:var(--sys-green)}.fma-btn[data-tone=success]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-green) 18%,transparent);color:var(--sys-green)}.fma-btn[aria-pressed=true]{background:var(--tint-sel);color:var(--chrome-ink-hover)}.fma-btn[aria-pressed=true][data-tone=success]{background:color-mix(in oklab,var(--sys-green) 22%,transparent);color:var(--sys-green)}.fma-btn[aria-disabled=true]{opacity:.38;filter:saturate(.6);animation:none;cursor:default}.fma-btn__icon{inline-size:16px;block-size:16px;pointer-events:none}.fma-btn__badge{position:absolute;inset-block-start:3px;inset-inline-end:3px;inline-size:7px;block-size:7px;border-radius:50%;background:var(--accent);pointer-events:none}.fma-primary{--chrome-ink: var(--on-accent);--chrome-ink-hover: var(--on-accent);flex:none;display:grid;place-items:center;inline-size:30px;block-size:30px;border-radius:50%;background:var(--accent);transition:box-shadow var(--nova-duration-hover) var(--nova-ease-micro),transform var(--nova-duration-hover) var(--nova-ease-micro)}.fma-primary:hover{box-shadow:0 8px 20px var(--tint-sel);transform:translateY(-1px)}.fma-primary--disabled{opacity:.38;filter:saturate(.6)}.fma-primary--disabled:hover{box-shadow:none;transform:none}.fma-btn--text{inline-size:auto;block-size:30px;border-radius:99px;padding-inline:12px;font-family:inherit;font-size:12.5px;font-weight:600;line-height:1;white-space:nowrap}@media(pointer:coarse){.fma-btn{inline-size:44px;block-size:44px}.fma-btn--text{inline-size:auto;min-inline-size:44px}.fma-primary{inline-size:44px;block-size:44px}}\n"], dependencies: [{ kind: "component", type: ContextMenuComponent, selector: "fly-context-menu", inputs: ["x", "y", "anchor", "align", "placement", "sections", "boundary"], outputs: ["action", "closed"] }, { kind: "directive", type: FlyTooltipDirective, selector: "[flyTooltip], [data-tooltip]", inputs: ["flyTooltip", "flyTooltipPlacement", "flyTooltipDisabled", "flyTooltipDelay"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
17674
17674
  }
17675
17675
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyMagicActionsComponent, decorators: [{
17676
17676
  type: Component,
17677
17677
  args: [{ selector: 'fly-magic-actions', standalone: true, imports: [ContextMenuComponent, FlyTooltipDirective, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
17678
17678
  '[attr.dir]': 'i18n.direction()',
17679
- }, template: "<!--\r\n Icon-only buttons carry the accessible name via [attr.aria-label] \u2014 the SVG\r\n glyph itself is aria-hidden (decorative, skill \u00A7accessibility rule 5). `kind:\r\n 'text'` actions rely on their own visible text instead. Disabled rows stay\r\n `aria-disabled` (never native `disabled`) so they remain focusable/hoverable \u2014\r\n a disabled action's whole point is to explain ITSELF via the auto-suffixed\r\n tooltip, which native `disabled` would suppress.\r\n\r\n The glyph is composed from ALLOWLISTED nodes bound as real attributes, never\r\n from `[innerHTML]`: `iconPath` is publisher-supplied, and an `<svg>` fragment\r\n is not a closed world (`<foreignObject>` is an HTML integration point, `<a\r\n xlink:href=\"javascript:\u2026\">` is live under the very click this button invites).\r\n `magic-actions-icon.ts` carries the full rationale; the shape below is its\r\n consequence \u2014 an attribute binding cannot introduce an element or a handler,\r\n so there is nothing left to sanitize.\r\n\r\n That block is authored ONCE, as `#actionButton`, and stamped by every place a\r\n contributed action is painted (group items and `primary`). It used to be\r\n inline in the group loop, which was fine while this component rendered groups\r\n only; with `primary` here too, a second copy would mean the next edit to the\r\n SECURITY-CRITICAL binding shape has to be made twice and can be made once.\r\n-->\r\n<!--\r\n `data-action` carries the publisher's action `id` verbatim \u2014 the one stable, LOCALE-INDEPENDENT\r\n handle on a rendered action. Every other identifying attribute here is translated\r\n (`aria-label`, the tooltip), so an e2e suite that targeted them had to assert in one language,\r\n and one that targeted a bespoke button lost its hook entirely when the action moved into the\r\n bar. That is not hypothetical: PPM's project-closure suite could not adopt the contract for\r\n exactly this reason. It is an ATTRIBUTE, not a class, so it never participates in styling, and\r\n `id` is already unique across the whole contribution (the projection enforces it), so it is\r\n unique in the DOM too.\r\n-->\r\n<ng-template #actionButton let-projected>\r\n <!--\r\n `let-projected` is `any` \u2014 Angular infers nothing for an `ngTemplateOutlet`\r\n context, and there is no built-in way to declare one. `asAction` is an\r\n identity function whose only job is to give this block a TYPED local, so\r\n every read below (`.kind`, `.disabled`, `.menu`) is checked by the template\r\n compiler instead of silently resolving to `undefined` on a typo. Without it\r\n the one place a `MagicBarActionView` is actually painted would be the one\r\n place its shape is not verified.\r\n -->\r\n @let action = asAction(projected);\r\n @if (action.kind === 'text') {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn fma-btn--text\"\r\n [attr.data-action]=\"action.id\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >{{ resolvedLabel(action) }}</button>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn\"\r\n [class.fma-btn--badge]=\"hasBadge(action)\"\r\n [attr.data-action]=\"action.id\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [attr.aria-haspopup]=\"action.menu ? 'menu' : null\"\r\n [attr.aria-expanded]=\"action.menu ? (openMenuActionId() === action.id ? 'true' : 'false') : null\"\r\n [attr.aria-label]=\"action.menu ? triggerAriaLabel(action) : resolvedLabel(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >\r\n <svg\r\n class=\"fma-btn__icon\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.8\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n @for (node of iconNodes(action); track $index) {\r\n @switch (node.tag) {\r\n @case ('path') {\r\n <svg:path\r\n [attr.d]=\"node.attrs['d']\"\r\n [attr.fill-rule]=\"node.attrs['fill-rule']\"\r\n [attr.clip-rule]=\"node.attrs['clip-rule']\"\r\n />\r\n }\r\n @case ('circle') {\r\n <svg:circle\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.r]=\"node.attrs['r']\"\r\n />\r\n }\r\n @case ('rect') {\r\n <svg:rect\r\n [attr.x]=\"node.attrs['x']\"\r\n [attr.y]=\"node.attrs['y']\"\r\n [attr.width]=\"node.attrs['width']\"\r\n [attr.height]=\"node.attrs['height']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('ellipse') {\r\n <svg:ellipse\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('line') {\r\n <svg:line\r\n [attr.x1]=\"node.attrs['x1']\"\r\n [attr.y1]=\"node.attrs['y1']\"\r\n [attr.x2]=\"node.attrs['x2']\"\r\n [attr.y2]=\"node.attrs['y2']\"\r\n />\r\n }\r\n @case ('polyline') {\r\n <svg:polyline [attr.points]=\"node.attrs['points']\" />\r\n }\r\n @case ('polygon') {\r\n <svg:polygon [attr.points]=\"node.attrs['points']\" />\r\n }\r\n }\r\n }\r\n </svg>\r\n @if (hasBadge(action)) {\r\n <span class=\"fma-btn__badge\" aria-hidden=\"true\"></span>\r\n }\r\n </button>\r\n }\r\n</ng-template>\r\n\r\n<!--\r\n `.fma` is the SCROLLING row and holds the contributed groups only. The accent\r\n CTA is a SIBLING of it, outside the fade mask and outside the scroll container,\r\n because it is the row's anchor \u2014 a call to action that dissolves into a\r\n gradient, or that you have to scroll sideways to reach, inverts the affordance.\r\n It is also what makes `isOverflowing` measurable at all: see the component.\r\n-->\r\n@if (groups().length) {\r\n <div #row class=\"fma\" [class.fma--overflow]=\"isOverflowing()\">\r\n @for (group of groups(); track group.id) {\r\n <div\r\n class=\"fma-group\"\r\n [class.fma-group--framed]=\"group.framed\"\r\n role=\"group\"\r\n [attr.aria-label]=\"i18n.t(group.labelKey)\"\r\n >\r\n @for (action of group.items; track action.id) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: action }\"\r\n />\r\n }\r\n </div>\r\n @if (group.framed) {\r\n <span class=\"fma-sep\" aria-hidden=\"true\"></span>\r\n }\r\n }\r\n </div>\r\n}\r\n\r\n<!--\r\n The accent CTA. The disc is a WRAPPER, not a modifier on the button, and that\r\n is load-bearing rather than cosmetic: `.fma-btn`'s hover/press feedback is an\r\n `animation` (`iconWiggle` / `iconBounce`), and an animation that touches\r\n `transform` beats a declared `transform` \u2014 so a hover lift authored on the\r\n button itself would simply never render. The wrapper owns the disc, the lift\r\n and the shadow; the button stays transparent and keeps the DS's own toolbar\r\n feedback. It re-points `--chrome-ink` rather than styling `.fma-btn` through a\r\n descendant selector so the glyph colour inherits the way custom properties do.\r\n-->\r\n@if (primary(); as p) {\r\n <span class=\"fma-primary\" [class.fma-primary--disabled]=\"p.disabled\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: p }\"\r\n />\r\n </span>\r\n}\r\n\r\n<!--\r\n ONE radio menu, hoisted out of the group loops (S1-review F9). Only one is open\r\n at a time (`openMenuActionId`), so a single instance is enough \u2014 and rendering\r\n it beside its button would insert a non-`.fma-btn` element into the group,\r\n silently shifting every later button's `:nth-child` index and with it the\r\n `toolbarPopIn` stagger delay the `.fma-btn` rule assigns. Keeping every\r\n staggered parent's children homogeneous is what makes that rule's comment true.\r\n It portals itself to <body>, so its position is unaffected by where it is\r\n declared.\r\n-->\r\n@if (openAction(); as open) {\r\n <fly-context-menu\r\n [anchor]=\"menuAnchorEl()\"\r\n [sections]=\"menuSections(open)\"\r\n (action)=\"onMenuAction(open, $event)\"\r\n (closed)=\"closeMenu()\"\r\n />\r\n}\r\n", styles: [":host{display:flex;align-items:center;gap:8px;min-inline-size:0}.fma{display:flex;align-items:center;gap:8px;flex:0 1 auto;min-inline-size:0;overflow:hidden;flex-wrap:nowrap}.fma--overflow{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%)}.fma--overflow::-webkit-scrollbar{display:none}:host([dir=rtl]) .fma--overflow{-webkit-mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%)}.fma-group{display:flex;align-items:center;gap:8px;flex:none}.fma-group--framed{gap:2px}.fma-sep{flex:0 0 auto;inline-size:1px;block-size:18px;background:var(--w14)}.fma-btn{position:relative;flex:0 0 auto;inline-size:30px;block-size:30px;display:grid;place-items:center;border:0;border-radius:50%;background:transparent;color:var(--chrome-ink);cursor:pointer;padding:0;animation:toolbarPopIn .3s var(--nova-ease-structural) both}.fma-btn:nth-child(1){animation-delay:0ms}.fma-btn:nth-child(2){animation-delay:40ms}.fma-btn:nth-child(3){animation-delay:80ms}.fma-btn:nth-child(4){animation-delay:.12s}.fma-btn:nth-child(5){animation-delay:.16s}.fma-btn:nth-child(6){animation-delay:.2s}.fma-btn:nth-child(7){animation-delay:.24s}.fma-btn:nth-child(8){animation-delay:.28s}.fma-btn:nth-child(9){animation-delay:.32s}.fma-btn:nth-child(10){animation-delay:.36s}.fma-btn:nth-child(11){animation-delay:.4s}.fma-btn:nth-child(12){animation-delay:.44s}.fma-btn:nth-child(n+13){animation-delay:.44s}.fma-btn:not([aria-disabled=true]):hover{background:var(--w1);color:var(--chrome-ink-hover);animation:iconWiggle .5s ease}.fma-btn:not([aria-disabled=true]):active{animation:iconBounce .38s var(--nova-ease-overshoot)}.fma-btn:focus-visible{outline:3px solid var(--accent);outline-offset:3px;border-radius:inherit}.fma-btn[data-tone=danger]{color:var(--sys-red)}.fma-btn[data-tone=danger]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.fma-btn[data-tone=success]{color:var(--sys-green)}.fma-btn[data-tone=success]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-green) 18%,transparent);color:var(--sys-green)}.fma-btn[aria-pressed=true]{background:var(--tint-sel);color:var(--chrome-ink-hover)}.fma-btn[aria-pressed=true][data-tone=success]{background:color-mix(in oklab,var(--sys-green) 22%,transparent);color:var(--sys-green)}.fma-btn[aria-disabled=true]{opacity:.38;filter:saturate(.6);animation:none;cursor:default}.fma-btn__icon{inline-size:16px;block-size:16px;pointer-events:none}.fma-btn__badge{position:absolute;inset-block-start:3px;inset-inline-end:3px;inline-size:7px;block-size:7px;border-radius:50%;background:var(--accent);pointer-events:none}.fma-primary{--chrome-ink: var(--on-accent);--chrome-ink-hover: var(--on-accent);flex:none;display:grid;place-items:center;inline-size:30px;block-size:30px;border-radius:50%;background:var(--accent);transition:box-shadow var(--nova-duration-hover) var(--nova-ease-micro),transform var(--nova-duration-hover) var(--nova-ease-micro)}.fma-primary:hover{box-shadow:0 8px 20px var(--tint-sel);transform:translateY(-1px)}.fma-primary--disabled{opacity:.38;filter:saturate(.6)}.fma-primary--disabled:hover{box-shadow:none;transform:none}.fma-btn--text{inline-size:auto;block-size:30px;border-radius:99px;padding-inline:12px;font-family:inherit;font-size:12.5px;font-weight:600;line-height:1;white-space:nowrap}@media(pointer:coarse){.fma-btn{inline-size:44px;block-size:44px}.fma-btn--text{inline-size:auto;min-inline-size:44px}.fma-primary{inline-size:44px;block-size:44px}}\n"] }]
17679
+ }, template: "<!--\r\n Icon-only buttons carry the accessible name via [attr.aria-label] \u2014 the SVG\r\n glyph itself is aria-hidden (decorative, skill \u00A7accessibility rule 5). `kind:\r\n 'text'` actions rely on their own visible text instead. Disabled rows stay\r\n `aria-disabled` (never native `disabled`) so they remain focusable/hoverable \u2014\r\n a disabled action's whole point is to explain ITSELF via the auto-suffixed\r\n tooltip, which native `disabled` would suppress.\r\n\r\n The glyph is composed from ALLOWLISTED nodes bound as real attributes, never\r\n from `[innerHTML]`: `iconPath` is publisher-supplied, and an `<svg>` fragment\r\n is not a closed world (`<foreignObject>` is an HTML integration point, `<a\r\n xlink:href=\"javascript:\u2026\">` is live under the very click this button invites).\r\n `magic-actions-icon.ts` carries the full rationale; the shape below is its\r\n consequence \u2014 an attribute binding cannot introduce an element or a handler,\r\n so there is nothing left to sanitize.\r\n\r\n That block is authored ONCE, as `#actionButton`, and stamped by every place a\r\n contributed action is painted (group items and `primary`). It used to be\r\n inline in the group loop, which was fine while this component rendered groups\r\n only; with `primary` here too, a second copy would mean the next edit to the\r\n SECURITY-CRITICAL binding shape has to be made twice and can be made once.\r\n-->\r\n<!--\r\n `data-action` carries the publisher's action `id` verbatim \u2014 the one stable, LOCALE-INDEPENDENT\r\n handle on a rendered action. Every other identifying attribute here is translated\r\n (`aria-label`, the tooltip), so an e2e suite that targeted them had to assert in one language,\r\n and one that targeted a bespoke button lost its hook entirely when the action moved into the\r\n bar. That is not hypothetical: PPM's project-closure suite could not adopt the contract for\r\n exactly this reason. It is an ATTRIBUTE, not a class, so it never participates in styling, and\r\n `id` is already unique across the whole contribution (the projection enforces it), so it is\r\n unique in the DOM too.\r\n-->\r\n<ng-template #actionButton let-projected>\r\n <!--\r\n `let-projected` is `any` \u2014 Angular infers nothing for an `ngTemplateOutlet`\r\n context, and there is no built-in way to declare one. `asAction` is an\r\n identity function whose only job is to give this block a TYPED local, so\r\n every read below (`.kind`, `.disabled`, `.menu`) is checked by the template\r\n compiler instead of silently resolving to `undefined` on a typo. Without it\r\n the one place a `MagicBarActionView` is actually painted would be the one\r\n place its shape is not verified.\r\n -->\r\n @let action = asAction(projected);\r\n @if (action.kind === 'text') {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn fma-btn--text\"\r\n [attr.data-action]=\"action.id\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >{{ resolvedLabel(action) }}</button>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n class=\"fma-btn\"\r\n [class.fma-btn--badge]=\"hasBadge(action)\"\r\n [attr.data-action]=\"action.id\"\r\n [attr.data-tone]=\"toneAttr(action)\"\r\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\r\n [attr.aria-pressed]=\"pressedAttr(action)\"\r\n [attr.aria-haspopup]=\"action.menu ? 'menu' : null\"\r\n [attr.aria-expanded]=\"action.menu ? (openMenuActionId() === action.id ? 'true' : 'false') : null\"\r\n [attr.aria-label]=\"action.menu ? triggerAriaLabel(action) : resolvedLabel(action)\"\r\n [flyTooltip]=\"tooltipFor(action)\"\r\n [flyTooltipDelay]=\"450\"\r\n (click)=\"activate(action, $event)\"\r\n >\r\n <svg\r\n class=\"fma-btn__icon\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"1.8\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n @for (node of iconNodes(action); track $index) {\r\n @switch (node.tag) {\r\n @case ('path') {\r\n <svg:path\r\n [attr.d]=\"node.attrs['d']\"\r\n [attr.fill-rule]=\"node.attrs['fill-rule']\"\r\n [attr.clip-rule]=\"node.attrs['clip-rule']\"\r\n />\r\n }\r\n @case ('circle') {\r\n <svg:circle\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.r]=\"node.attrs['r']\"\r\n />\r\n }\r\n @case ('rect') {\r\n <svg:rect\r\n [attr.x]=\"node.attrs['x']\"\r\n [attr.y]=\"node.attrs['y']\"\r\n [attr.width]=\"node.attrs['width']\"\r\n [attr.height]=\"node.attrs['height']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('ellipse') {\r\n <svg:ellipse\r\n [attr.cx]=\"node.attrs['cx']\"\r\n [attr.cy]=\"node.attrs['cy']\"\r\n [attr.rx]=\"node.attrs['rx']\"\r\n [attr.ry]=\"node.attrs['ry']\"\r\n />\r\n }\r\n @case ('line') {\r\n <svg:line\r\n [attr.x1]=\"node.attrs['x1']\"\r\n [attr.y1]=\"node.attrs['y1']\"\r\n [attr.x2]=\"node.attrs['x2']\"\r\n [attr.y2]=\"node.attrs['y2']\"\r\n />\r\n }\r\n @case ('polyline') {\r\n <svg:polyline [attr.points]=\"node.attrs['points']\" />\r\n }\r\n @case ('polygon') {\r\n <svg:polygon [attr.points]=\"node.attrs['points']\" />\r\n }\r\n }\r\n }\r\n </svg>\r\n @if (hasBadge(action)) {\r\n <span class=\"fma-btn__badge\" aria-hidden=\"true\"></span>\r\n }\r\n </button>\r\n }\r\n</ng-template>\r\n\r\n<!--\r\n `.fma` is the SCROLLING row and holds the contributed groups only. The accent\r\n CTA is a SIBLING of it, outside the fade mask and outside the scroll container,\r\n because it is the row's anchor \u2014 a call to action that dissolves into a\r\n gradient, or that you have to scroll sideways to reach, inverts the affordance.\r\n It is also what makes `isOverflowing` measurable at all: see the component.\r\n-->\r\n@if (groups().length) {\r\n <div #row class=\"fma\" [class.fma--overflow]=\"isOverflowing()\">\r\n @for (group of groups(); track group.id) {\r\n <div\r\n class=\"fma-group\"\r\n [class.fma-group--framed]=\"group.framed\"\r\n role=\"group\"\r\n [attr.aria-label]=\"i18n.t(group.labelKey)\"\r\n >\r\n @for (action of group.items; track action.id) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: action }\"\r\n />\r\n }\r\n </div>\r\n @if (group.framed) {\r\n <span class=\"fma-sep\" aria-hidden=\"true\"></span>\r\n }\r\n }\r\n </div>\r\n}\r\n\r\n<!--\r\n The accent CTA. The disc is a WRAPPER, not a modifier on the button, and that\r\n is load-bearing rather than cosmetic: `.fma-btn`'s hover/press feedback is an\r\n `animation` (`iconWiggle` / `iconBounce`), and an animation that touches\r\n `transform` beats a declared `transform` \u2014 so a hover lift authored on the\r\n button itself would simply never render. The wrapper owns the disc, the lift\r\n and the shadow; the button stays transparent and keeps the DS's own toolbar\r\n feedback. It re-points `--chrome-ink` rather than styling `.fma-btn` through a\r\n descendant selector so the glyph colour inherits the way custom properties do.\r\n-->\r\n@if (primary(); as p) {\r\n <span class=\"fma-primary\" [class.fma-primary--disabled]=\"p.disabled\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"actionButton\"\r\n [ngTemplateOutletContext]=\"{ $implicit: p }\"\r\n />\r\n </span>\r\n}\r\n\r\n<!--\r\n ONE radio menu, hoisted out of the group loops (S1-review F9). Only one is open\r\n at a time (`openMenuActionId`), so a single instance is enough \u2014 and rendering\r\n it beside its button would insert a non-`.fma-btn` element into the group,\r\n silently shifting every later button's `:nth-child` index and with it the\r\n `toolbarPopIn` stagger delay the `.fma-btn` rule assigns. Keeping every\r\n staggered parent's children homogeneous is what makes that rule's comment true.\r\n It portals itself to <body>, so its position is unaffected by where it is\r\n declared.\r\n-->\r\n@if (openAction(); as open) {\r\n <fly-context-menu\r\n [anchor]=\"menuAnchorEl()\"\r\n [sections]=\"menuSections(open)\"\r\n (action)=\"onMenuAction(open, $event)\"\r\n (closed)=\"closeMenu()\"\r\n />\r\n}\r\n", styles: [":host{display:flex;align-items:center;gap:8px;min-inline-size:0}.fma{display:flex;align-items:center;gap:8px;flex:0 1 auto;min-inline-size:0;overflow:hidden;flex-wrap:nowrap}.fma--overflow{overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent 100%)}.fma--overflow::-webkit-scrollbar{display:none}:host([dir=rtl]) .fma--overflow{-webkit-mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%);mask-image:linear-gradient(to left,#000 calc(100% - 28px),transparent 100%)}.fma-group{display:flex;align-items:center;gap:8px;flex:none}.fma-group--framed{gap:2px}.fma-sep{flex:0 0 auto;inline-size:1px;block-size:18px;background:var(--w14)}.fma-btn{position:relative;flex:0 0 auto;inline-size:30px;block-size:30px;display:grid;place-items:center;border:0;border-radius:50%;background:transparent;color:var(--chrome-ink);cursor:pointer;padding:0;animation:toolbarPopIn .3s var(--nova-ease-structural) both}.fma-btn:nth-child(1){animation-delay:0ms}.fma-btn:nth-child(2){animation-delay:40ms}.fma-btn:nth-child(3){animation-delay:80ms}.fma-btn:nth-child(4){animation-delay:.12s}.fma-btn:nth-child(5){animation-delay:.16s}.fma-btn:nth-child(6){animation-delay:.2s}.fma-btn:nth-child(7){animation-delay:.24s}.fma-btn:nth-child(8){animation-delay:.28s}.fma-btn:nth-child(9){animation-delay:.32s}.fma-btn:nth-child(10){animation-delay:.36s}.fma-btn:nth-child(11){animation-delay:.4s}.fma-btn:nth-child(12){animation-delay:.44s}.fma-btn:nth-child(n+13){animation-delay:.44s}.fma-btn:not([aria-disabled=true]):hover{background:var(--w1);color:var(--chrome-ink-hover);animation:iconWiggle .5s ease}.fma-btn:not([aria-disabled=true]):active{animation:iconBounce .38s var(--nova-ease-overshoot)}.fma-btn:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px;border-radius:inherit}.fma-btn[data-tone=danger]{color:var(--sys-red)}.fma-btn[data-tone=danger]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.fma-btn[data-tone=success]{color:var(--sys-green)}.fma-btn[data-tone=success]:not([aria-disabled=true]):hover{background:color-mix(in oklab,var(--sys-green) 18%,transparent);color:var(--sys-green)}.fma-btn[aria-pressed=true]{background:var(--tint-sel);color:var(--chrome-ink-hover)}.fma-btn[aria-pressed=true][data-tone=success]{background:color-mix(in oklab,var(--sys-green) 22%,transparent);color:var(--sys-green)}.fma-btn[aria-disabled=true]{opacity:.38;filter:saturate(.6);animation:none;cursor:default}.fma-btn__icon{inline-size:16px;block-size:16px;pointer-events:none}.fma-btn__badge{position:absolute;inset-block-start:3px;inset-inline-end:3px;inline-size:7px;block-size:7px;border-radius:50%;background:var(--accent);pointer-events:none}.fma-primary{--chrome-ink: var(--on-accent);--chrome-ink-hover: var(--on-accent);flex:none;display:grid;place-items:center;inline-size:30px;block-size:30px;border-radius:50%;background:var(--accent);transition:box-shadow var(--nova-duration-hover) var(--nova-ease-micro),transform var(--nova-duration-hover) var(--nova-ease-micro)}.fma-primary:hover{box-shadow:0 8px 20px var(--tint-sel);transform:translateY(-1px)}.fma-primary--disabled{opacity:.38;filter:saturate(.6)}.fma-primary--disabled:hover{box-shadow:none;transform:none}.fma-btn--text{inline-size:auto;block-size:30px;border-radius:99px;padding-inline:12px;font-family:inherit;font-size:12.5px;font-weight:600;line-height:1;white-space:nowrap}@media(pointer:coarse){.fma-btn{inline-size:44px;block-size:44px}.fma-btn--text{inline-size:auto;min-inline-size:44px}.fma-primary{inline-size:44px;block-size:44px}}\n"] }]
17680
17680
  }], ctorParameters: () => [], propDecorators: { groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: true }] }], primary: [{ type: i0.Input, args: [{ isSignal: true, alias: "primary", required: false }] }], rowRef: [{ type: i0.ViewChild, args: ['row', { isSignal: true }] }] } });
17681
17681
 
17682
17682
  /**
@@ -17719,6 +17719,15 @@ const VERBATIM_FROM_UX_DROP = {
17719
17719
  export: '<path d="M12 16V7M8 11l4-4 4 4"/><path d="M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3"/>',
17720
17720
  /** `Home.dc.html:616`. */
17721
17721
  import: '<path d="M12 4v9M8 9l4 4 4-4"/><path d="M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3"/>',
17722
+ /**
17723
+ * `Home.dc.html:362` — the chrome's own reload arrow, reused verbatim so a
17724
+ * contributed "Refresh" action reads identically to the shell's reload button
17725
+ * sitting a few pixels away in the same bar.
17726
+ *
17727
+ * NEVER mirror this under RTL. Its arrow is circular, and the mirrored form reads
17728
+ * as "undo" (design §9 rule 7: only directional arrow/chevron glyphs mirror).
17729
+ */
17730
+ refresh: '<path d="M20.2 12a8.2 8.2 0 1 1-2.7-6.1"/><path d="M20.4 4.1v4.6h-4.6"/>',
17722
17731
  /** `Home.dc.html:547` — "Mark as complete". */
17723
17732
  check: '<circle cx="12" cy="12" r="8.6"/><path d="M8.4 12.3l2.6 2.6 4.6-5"/>',
17724
17733
  /** `Home.dc.html:550` — "Watch task". */
@@ -17733,6 +17742,22 @@ const VERBATIM_FROM_UX_DROP = {
17733
17742
  today: '<path d="M3.5 8.5h17M7 3.2v3.4M17 3.2v3.4"/><rect x="3.5" y="5.5" width="17" height="15" rx="2.6"/><path d="M8 13l2.2 2.2L14 11"/>',
17734
17743
  };
17735
17744
  const ORIGINAL_SAME_CONVENTION = {
17745
+ /**
17746
+ * "Download …" — an action that hands the user a FILE (Export to Excel/PDF, a
17747
+ * generated report). Arrow down onto a baseline, the Material-style download mark.
17748
+ *
17749
+ * Distinct from {@link VERBATIM_FROM_UX_DROP.export} on purpose, and the distinction
17750
+ * is the point of this entry. The drop's Export/Import pair reads the tray as the
17751
+ * APP — data leaves it upward on export — which is coherent but inverts the reading
17752
+ * users bring to a file transfer, where down means "arriving on my machine". Every
17753
+ * consumer of `export` on the platform is in fact a download, so the up arrow was
17754
+ * being read as "upload" on all of them. `export` keeps its drop geometry for a
17755
+ * genuine data-exchange pair; anything that produces a file for the user takes this.
17756
+ *
17757
+ * The baseline rather than a tray also keeps it apart from `import`, which is the
17758
+ * tray-and-down-arrow shape a download glyph would otherwise collide with.
17759
+ */
17760
+ download: '<path d="M12 4v11M7.5 10.5l4.5 4.5 4.5-4.5"/><path d="M5 20h14"/>',
17736
17761
  /** Signal-detail "View trace" — no standalone path in the drop; an activity/pulse line. */
17737
17762
  viewTrace: '<path d="M3 12h4l2-7 4 14 2-7h6"/>',
17738
17763
  /** Signal-detail "Archive". */
@@ -19505,11 +19530,11 @@ class FlyModerationQueueComponent {
19505
19530
  btn?.focus({ preventScroll: true });
19506
19531
  }
19507
19532
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyModerationQueueComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19508
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyModerationQueueComponent, isStandalone: true, selector: "fly-moderation-queue", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: true, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, resolveDisplayName: { classPropertyName: "resolveDisplayName", publicName: "resolveDisplayName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loadPage: "loadPage", resolve: "resolve", lockThread: "lockThread", openSubject: "openSubject" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, classAttribute: "fly-moderation-queue" }, ngImport: i0, template: "<div class=\"fly-moderation-queue__body\">\r\n <!-- \u2500\u2500 Header: count + status filter \u2500\u2500 -->\r\n <header class=\"fly-moderation-queue__header\">\r\n <span class=\"fly-moderation-queue__count\">\r\n {{ 'moderation.count' | translate: { n: page().total } }}\r\n </span>\r\n\r\n <div class=\"fly-moderation-queue__status-filter\" role=\"group\" [attr.aria-label]=\"'moderation.status_label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__status-btn\"\r\n [class.fly-moderation-queue__status-btn--active]=\"status() === null\"\r\n [attr.aria-pressed]=\"status() === null\"\r\n [disabled]=\"loading()\"\r\n (click)=\"onStatusPick(null)\">\r\n {{ 'moderation.status_all' | translate }}\r\n </button>\r\n @for (s of statuses; track s) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__status-btn\"\r\n [class.fly-moderation-queue__status-btn--active]=\"status() === s\"\r\n [attr.aria-pressed]=\"status() === s\"\r\n [disabled]=\"loading()\"\r\n (click)=\"onStatusPick(s)\">\r\n {{ 'moderation.status.' + s | translate }}\r\n </button>\r\n }\r\n </div>\r\n </header>\r\n\r\n <!-- \u2500\u2500 States \u2500\u2500 -->\r\n @if (error()) {\r\n <p class=\"fly-moderation-queue__error\" role=\"alert\">{{ error() }}</p>\r\n } @else if (loading() && page().items.length === 0) {\r\n <p class=\"fly-moderation-queue__status-msg\">{{ 'moderation.loading' | translate }}</p>\r\n } @else if (page().items.length === 0) {\r\n <p class=\"fly-moderation-queue__empty\">{{ 'moderation.empty' | translate }}</p>\r\n } @else {\r\n <!-- \u2500\u2500 Report table \u2500\u2500 -->\r\n <div class=\"fly-moderation-queue__table-wrap\">\r\n <table class=\"fly-moderation-queue__table\">\r\n <caption class=\"fly-moderation-queue__sr-only\">{{ 'moderation.table_caption' | translate }}</caption>\r\n <thead>\r\n <tr>\r\n <th scope=\"col\">{{ 'moderation.col_reason' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_reporter' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_reported' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_excerpt' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_subject' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_status' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_actions' | translate }}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (r of page().items; track r.id) {\r\n <tr>\r\n <td class=\"fly-moderation-queue__reason-cell\">\r\n <span class=\"fly-moderation-queue__reason\">{{ 'comment.reason.' + r.reason | translate }}</span>\r\n @if (r.detail) {\r\n <span class=\"fly-moderation-queue__detail\" [title]=\"r.detail\">{{ r.detail }}</span>\r\n }\r\n </td>\r\n <td>{{ reporterLabel(r) }}</td>\r\n <td>{{ formatDate(r.createdAt) }}</td>\r\n <td class=\"fly-moderation-queue__excerpt\">{{ r.commentExcerpt || '\u2014' }}</td>\r\n <td>\r\n <button type=\"button\" class=\"fly-moderation-queue__subject-link\" [title]=\"subjectHref(r)\" (click)=\"onOpenSubject(r)\">\r\n {{ subjectDisplay(r) }}\r\n </button>\r\n </td>\r\n <td>\r\n <span class=\"fly-moderation-queue__badge\" [class]=\"'fly-moderation-queue__badge--' + r.status\">\r\n {{ 'moderation.status.' + r.status | translate }}\r\n </span>\r\n @if (r.resolutionNote) {\r\n <div class=\"fly-moderation-queue__resolution-note\">{{ r.resolutionNote }}</div>\r\n }\r\n </td>\r\n <td class=\"fly-moderation-queue__actions\">\r\n @if (isResolvable(r.status)) {\r\n <button type=\"button\" class=\"fly-moderation-queue__action-btn\" [disabled]=\"loading()\" (click)=\"openResolve(r)\">\r\n {{ 'moderation.resolve' | translate }}\r\n </button>\r\n }\r\n @if (confirmingLockId() === r.id) {\r\n <span class=\"fly-moderation-queue__lock-confirm\">\r\n <button type=\"button\" class=\"fly-moderation-queue__cancel-btn\" (click)=\"cancelLock()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-moderation-queue__danger-btn\" (click)=\"confirmLock(r)\">\r\n {{ 'moderation.lock_thread' | translate }}\r\n </button>\r\n </span>\r\n } @else {\r\n <button type=\"button\" class=\"fly-moderation-queue__action-btn\" [disabled]=\"loading()\" (click)=\"requestLock(r)\">\r\n {{ 'moderation.lock_thread' | translate }}\r\n </button>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n @if (page().hasMore) {\r\n <button type=\"button\" class=\"fly-moderation-queue__load-more\" [disabled]=\"loading()\" (click)=\"loadMore()\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 Resolve dialog \u2500\u2500 -->\r\n@if (resolvingReport(); as r) {\r\n <div class=\"fly-moderation-queue__overlay\">\r\n <div class=\"fly-moderation-queue__overlay-backdrop\" role=\"button\" tabindex=\"0\"\r\n [attr.aria-label]=\"'common.action.cancel' | translate\"\r\n (click)=\"closeResolve()\"\r\n (keydown.enter)=\"closeResolve()\"\r\n (keydown.space)=\"onOverlayBackdropSpace($event)\"></div>\r\n <div\r\n class=\"fly-moderation-queue__dialog\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"'moderation.resolve_title' | translate\">\r\n <h3 class=\"fly-moderation-queue__dialog-title\">{{ 'moderation.resolve_title' | translate }}</h3>\r\n\r\n <fieldset class=\"fly-moderation-queue__resolution-group\">\r\n <legend>{{ 'moderation.resolution_label' | translate }}</legend>\r\n <label class=\"fly-moderation-queue__resolution-option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"resolutionGroupName\"\r\n [checked]=\"resolutionStatus() === 'ActionTaken'\"\r\n (change)=\"onResolutionStatusChange('ActionTaken')\" />\r\n <span>{{ 'moderation.resolution.ActionTaken' | translate }}</span>\r\n </label>\r\n <label class=\"fly-moderation-queue__resolution-option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"resolutionGroupName\"\r\n [checked]=\"resolutionStatus() === 'Dismissed'\"\r\n (change)=\"onResolutionStatusChange('Dismissed')\" />\r\n <span>{{ 'moderation.resolution.Dismissed' | translate }}</span>\r\n </label>\r\n </fieldset>\r\n\r\n @if (resolutionStatus() === 'ActionTaken') {\r\n <label class=\"fly-moderation-queue__checkbox-row\">\r\n <input type=\"checkbox\" [checked]=\"deleteComment()\" (change)=\"onDeleteCommentToggle($event)\" />\r\n <span>{{ 'moderation.delete_comment_label' | translate }}</span>\r\n </label>\r\n }\r\n\r\n <textarea\r\n class=\"fly-moderation-queue__textarea\"\r\n rows=\"3\"\r\n [attr.aria-label]=\"'moderation.resolution_note_label' | translate\"\r\n [placeholder]=\"'moderation.resolution_note_label' | translate\"\r\n [ngModel]=\"resolutionNote()\"\r\n (ngModelChange)=\"onResolutionNoteChange($event)\"></textarea>\r\n\r\n <div class=\"fly-moderation-queue__dialog-actions\">\r\n <button type=\"button\" class=\"fly-moderation-queue__cancel-btn\" (click)=\"closeResolve()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__submit-btn\"\r\n [disabled]=\"!resolutionStatus()\"\r\n (click)=\"submitResolve(r)\">\r\n {{ 'moderation.resolve_submit' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_text-tertiary: var(--label-tertiary, #94a3b8);--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_blue: var(--system-blue, #0a84ff);--_orange: var(--system-orange, #ff9f0a);--_green: var(--system-green, #32d74b);--_radius: 8px;--_blue-text: #1d4ed8;--_orange-text: #9a3412;--_green-text: #166534;--_danger-text: #b91c1c;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-moderation-queue__body{display:flex;flex-direction:column;gap:16px}.fly-moderation-queue__header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.fly-moderation-queue__count{font-weight:700;font-size:14px}.fly-moderation-queue__status-filter{display:inline-flex;flex-wrap:wrap;border:1px solid var(--_border);border-radius:var(--_radius);overflow:hidden}.fly-moderation-queue__status-btn{padding:5px 12px;border:none;border-inline-end:1px solid var(--_border);background:transparent;color:var(--_text-subtle);font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__status-btn:last-child{border-inline-end:none}.fly-moderation-queue__status-btn:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__status-btn--active{background:var(--_accent);color:#fff}.fly-moderation-queue__empty,.fly-moderation-queue__status-msg{margin:0;color:var(--_text-subtle);text-align:center;padding:16px 0}.fly-moderation-queue__error{margin:0;padding:8px 12px;border-radius:var(--_radius);background:color-mix(in srgb,var(--_danger) 12%,transparent);color:var(--_danger);font-size:12px}.fly-moderation-queue__sr-only{position:absolute;inline-size:1px;block-size:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.fly-moderation-queue__table-wrap{overflow-x:auto}.fly-moderation-queue__table{inline-size:100%;border-collapse:collapse;font-size:12px}.fly-moderation-queue__table th{text-align:start;padding:6px 10px;color:var(--_text-subtle);font-weight:600;border-block-end:1px solid var(--_border);white-space:nowrap}.fly-moderation-queue__table td{padding:8px 10px;border-block-end:1px solid var(--_border);vertical-align:top}.fly-moderation-queue__reason-cell{display:table-cell}.fly-moderation-queue__reason{display:block;font-weight:600}.fly-moderation-queue__detail{display:block;margin-block-start:2px;color:var(--_text-tertiary);font-size:11px;max-inline-size:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-moderation-queue__excerpt{max-inline-size:260px;color:var(--_text-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-moderation-queue__subject-link{border:none;background:transparent;padding:0;color:var(--_accent);font:inherit;font-weight:600;cursor:pointer;text-align:start}.fly-moderation-queue__subject-link:hover{text-decoration:underline}.fly-moderation-queue__badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;white-space:nowrap}.fly-moderation-queue__badge--Open{background:color-mix(in srgb,var(--_blue) 12%,#fff);color:var(--_blue-text)}.fly-moderation-queue__badge--UnderReview{background:color-mix(in srgb,var(--_orange) 12%,#fff);color:var(--_orange-text)}.fly-moderation-queue__badge--ActionTaken{background:color-mix(in srgb,var(--_danger) 12%,#fff);color:var(--_danger-text)}.fly-moderation-queue__badge--Dismissed{background:color-mix(in srgb,var(--_green) 12%,#fff);color:var(--_green-text)}.fly-moderation-queue__resolution-note{margin-block-start:4px;color:var(--_text-tertiary);font-size:11px;max-inline-size:200px}.fly-moderation-queue__actions{display:flex;flex-direction:column;align-items:flex-start;gap:6px;white-space:nowrap}.fly-moderation-queue__action-btn{border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:4px 10px;color:var(--_text);font:inherit;font-size:11px;font-weight:600;cursor:pointer}.fly-moderation-queue__action-btn:hover:not(:disabled){background:var(--_surface-hover)}.fly-moderation-queue__action-btn:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__lock-confirm{display:inline-flex;align-items:center;gap:6px}.fly-moderation-queue__load-more{align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:6px 14px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__load-more:hover:not(:disabled){background:var(--_surface-hover)}.fly-moderation-queue__load-more:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:1000}.fly-moderation-queue__overlay-backdrop{position:absolute;inset:0;background:#00000073;border:none;padding:0;margin:0;cursor:pointer}.fly-moderation-queue__dialog{position:relative;z-index:1;inline-size:min(440px,90vw);max-block-size:85vh;overflow-y:auto;background:var(--_surface);border-radius:12px;padding:20px;display:flex;flex-direction:column;gap:14px;box-shadow:0 12px 32px #00000040}.fly-moderation-queue__dialog:focus-visible{outline:2px solid var(--_accent);outline-offset:2px}.fly-moderation-queue__dialog-title{margin:0;font-size:16px;font-weight:700}.fly-moderation-queue__resolution-group{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;border:none}.fly-moderation-queue__resolution-group legend{font-weight:600;padding:0;margin-block-end:4px}.fly-moderation-queue__resolution-option,.fly-moderation-queue__checkbox-row{display:flex;align-items:center;gap:8px;cursor:pointer}.fly-moderation-queue__resolution-option input,.fly-moderation-queue__checkbox-row input{accent-color:var(--_accent);cursor:pointer}.fly-moderation-queue__textarea{inline-size:100%;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;line-height:1.5;resize:vertical}.fly-moderation-queue__textarea:focus-visible{outline:2px solid var(--_accent);outline-offset:1px}.fly-moderation-queue__dialog-actions{display:flex;justify-content:flex-end;gap:8px}.fly-moderation-queue__submit-btn{padding:6px 16px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__submit-btn:hover:not(:disabled){opacity:.9}.fly-moderation-queue__submit-btn:disabled{opacity:.5;cursor:not-allowed}.fly-moderation-queue__cancel-btn{padding:6px 14px;border:1px solid var(--_border);border-radius:var(--_radius);background:transparent;color:var(--_text-subtle);font:inherit;cursor:pointer}.fly-moderation-queue__cancel-btn:hover{background:var(--_surface-hover)}.fly-moderation-queue__danger-btn{padding:6px 14px;border:none;border-radius:var(--_radius);background:var(--_danger);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__danger-btn:hover{opacity:.9}\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 });
19533
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyModerationQueueComponent, isStandalone: true, selector: "fly-moderation-queue", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: true, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, resolveDisplayName: { classPropertyName: "resolveDisplayName", publicName: "resolveDisplayName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loadPage: "loadPage", resolve: "resolve", lockThread: "lockThread", openSubject: "openSubject" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, classAttribute: "fly-moderation-queue" }, ngImport: i0, template: "<div class=\"fly-moderation-queue__body\">\r\n <!-- \u2500\u2500 Header: count + status filter \u2500\u2500 -->\r\n <header class=\"fly-moderation-queue__header\">\r\n <span class=\"fly-moderation-queue__count\">\r\n {{ 'moderation.count' | translate: { n: page().total } }}\r\n </span>\r\n\r\n <div class=\"fly-moderation-queue__status-filter\" role=\"group\" [attr.aria-label]=\"'moderation.status_label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__status-btn\"\r\n [class.fly-moderation-queue__status-btn--active]=\"status() === null\"\r\n [attr.aria-pressed]=\"status() === null\"\r\n [disabled]=\"loading()\"\r\n (click)=\"onStatusPick(null)\">\r\n {{ 'moderation.status_all' | translate }}\r\n </button>\r\n @for (s of statuses; track s) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__status-btn\"\r\n [class.fly-moderation-queue__status-btn--active]=\"status() === s\"\r\n [attr.aria-pressed]=\"status() === s\"\r\n [disabled]=\"loading()\"\r\n (click)=\"onStatusPick(s)\">\r\n {{ 'moderation.status.' + s | translate }}\r\n </button>\r\n }\r\n </div>\r\n </header>\r\n\r\n <!-- \u2500\u2500 States \u2500\u2500 -->\r\n @if (error()) {\r\n <p class=\"fly-moderation-queue__error\" role=\"alert\">{{ error() }}</p>\r\n } @else if (loading() && page().items.length === 0) {\r\n <p class=\"fly-moderation-queue__status-msg\">{{ 'moderation.loading' | translate }}</p>\r\n } @else if (page().items.length === 0) {\r\n <p class=\"fly-moderation-queue__empty\">{{ 'moderation.empty' | translate }}</p>\r\n } @else {\r\n <!-- \u2500\u2500 Report table \u2500\u2500 -->\r\n <div class=\"fly-moderation-queue__table-wrap\">\r\n <table class=\"fly-moderation-queue__table\">\r\n <caption class=\"fly-moderation-queue__sr-only\">{{ 'moderation.table_caption' | translate }}</caption>\r\n <thead>\r\n <tr>\r\n <th scope=\"col\">{{ 'moderation.col_reason' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_reporter' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_reported' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_excerpt' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_subject' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_status' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_actions' | translate }}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (r of page().items; track r.id) {\r\n <tr>\r\n <td class=\"fly-moderation-queue__reason-cell\">\r\n <span class=\"fly-moderation-queue__reason\">{{ 'comment.reason.' + r.reason | translate }}</span>\r\n @if (r.detail) {\r\n <span class=\"fly-moderation-queue__detail\" [title]=\"r.detail\">{{ r.detail }}</span>\r\n }\r\n </td>\r\n <td>{{ reporterLabel(r) }}</td>\r\n <td>{{ formatDate(r.createdAt) }}</td>\r\n <td class=\"fly-moderation-queue__excerpt\">{{ r.commentExcerpt || '\u2014' }}</td>\r\n <td>\r\n <button type=\"button\" class=\"fly-moderation-queue__subject-link\" [title]=\"subjectHref(r)\" (click)=\"onOpenSubject(r)\">\r\n {{ subjectDisplay(r) }}\r\n </button>\r\n </td>\r\n <td>\r\n <span class=\"fly-moderation-queue__badge\" [class]=\"'fly-moderation-queue__badge--' + r.status\">\r\n {{ 'moderation.status.' + r.status | translate }}\r\n </span>\r\n @if (r.resolutionNote) {\r\n <div class=\"fly-moderation-queue__resolution-note\">{{ r.resolutionNote }}</div>\r\n }\r\n </td>\r\n <td class=\"fly-moderation-queue__actions\">\r\n @if (isResolvable(r.status)) {\r\n <button type=\"button\" class=\"fly-moderation-queue__action-btn\" [disabled]=\"loading()\" (click)=\"openResolve(r)\">\r\n {{ 'moderation.resolve' | translate }}\r\n </button>\r\n }\r\n @if (confirmingLockId() === r.id) {\r\n <span class=\"fly-moderation-queue__lock-confirm\">\r\n <button type=\"button\" class=\"fly-moderation-queue__cancel-btn\" (click)=\"cancelLock()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-moderation-queue__danger-btn\" (click)=\"confirmLock(r)\">\r\n {{ 'moderation.lock_thread' | translate }}\r\n </button>\r\n </span>\r\n } @else {\r\n <button type=\"button\" class=\"fly-moderation-queue__action-btn\" [disabled]=\"loading()\" (click)=\"requestLock(r)\">\r\n {{ 'moderation.lock_thread' | translate }}\r\n </button>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n @if (page().hasMore) {\r\n <button type=\"button\" class=\"fly-moderation-queue__load-more\" [disabled]=\"loading()\" (click)=\"loadMore()\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 Resolve dialog \u2500\u2500 -->\r\n@if (resolvingReport(); as r) {\r\n <div class=\"fly-moderation-queue__overlay\">\r\n <div class=\"fly-moderation-queue__overlay-backdrop\" role=\"button\" tabindex=\"0\"\r\n [attr.aria-label]=\"'common.action.cancel' | translate\"\r\n (click)=\"closeResolve()\"\r\n (keydown.enter)=\"closeResolve()\"\r\n (keydown.space)=\"onOverlayBackdropSpace($event)\"></div>\r\n <div\r\n class=\"fly-moderation-queue__dialog\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"'moderation.resolve_title' | translate\">\r\n <h3 class=\"fly-moderation-queue__dialog-title\">{{ 'moderation.resolve_title' | translate }}</h3>\r\n\r\n <fieldset class=\"fly-moderation-queue__resolution-group\">\r\n <legend>{{ 'moderation.resolution_label' | translate }}</legend>\r\n <label class=\"fly-moderation-queue__resolution-option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"resolutionGroupName\"\r\n [checked]=\"resolutionStatus() === 'ActionTaken'\"\r\n (change)=\"onResolutionStatusChange('ActionTaken')\" />\r\n <span>{{ 'moderation.resolution.ActionTaken' | translate }}</span>\r\n </label>\r\n <label class=\"fly-moderation-queue__resolution-option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"resolutionGroupName\"\r\n [checked]=\"resolutionStatus() === 'Dismissed'\"\r\n (change)=\"onResolutionStatusChange('Dismissed')\" />\r\n <span>{{ 'moderation.resolution.Dismissed' | translate }}</span>\r\n </label>\r\n </fieldset>\r\n\r\n @if (resolutionStatus() === 'ActionTaken') {\r\n <label class=\"fly-moderation-queue__checkbox-row\">\r\n <input type=\"checkbox\" [checked]=\"deleteComment()\" (change)=\"onDeleteCommentToggle($event)\" />\r\n <span>{{ 'moderation.delete_comment_label' | translate }}</span>\r\n </label>\r\n }\r\n\r\n <textarea\r\n class=\"fly-moderation-queue__textarea\"\r\n rows=\"3\"\r\n [attr.aria-label]=\"'moderation.resolution_note_label' | translate\"\r\n [placeholder]=\"'moderation.resolution_note_label' | translate\"\r\n [ngModel]=\"resolutionNote()\"\r\n (ngModelChange)=\"onResolutionNoteChange($event)\"></textarea>\r\n\r\n <div class=\"fly-moderation-queue__dialog-actions\">\r\n <button type=\"button\" class=\"fly-moderation-queue__cancel-btn\" (click)=\"closeResolve()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__submit-btn\"\r\n [disabled]=\"!resolutionStatus()\"\r\n (click)=\"submitResolve(r)\">\r\n {{ 'moderation.resolve_submit' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_text-tertiary: var(--label-tertiary, #94a3b8);--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_blue: var(--system-blue, #0a84ff);--_orange: var(--system-orange, #ff9f0a);--_green: var(--system-green, #32d74b);--_radius: 8px;--_blue-text: #1d4ed8;--_orange-text: #9a3412;--_green-text: #166534;--_danger-text: #b91c1c;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-moderation-queue__body{display:flex;flex-direction:column;gap:16px}.fly-moderation-queue__header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.fly-moderation-queue__count{font-weight:700;font-size:14px}.fly-moderation-queue__status-filter{display:inline-flex;flex-wrap:wrap;border:1px solid var(--_border);border-radius:var(--_radius);overflow:hidden}.fly-moderation-queue__status-btn{padding:5px 12px;border:none;border-inline-end:1px solid var(--_border);background:transparent;color:var(--_text-subtle);font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__status-btn:last-child{border-inline-end:none}.fly-moderation-queue__status-btn:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__status-btn--active{background:var(--_accent);color:#fff}.fly-moderation-queue__empty,.fly-moderation-queue__status-msg{margin:0;color:var(--_text-subtle);text-align:center;padding:16px 0}.fly-moderation-queue__error{margin:0;padding:8px 12px;border-radius:var(--_radius);background:color-mix(in srgb,var(--_danger) 12%,transparent);color:var(--_danger);font-size:12px}.fly-moderation-queue__sr-only{position:absolute;inline-size:1px;block-size:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.fly-moderation-queue__table-wrap{overflow-x:auto}.fly-moderation-queue__table{inline-size:100%;border-collapse:collapse;font-size:12px}.fly-moderation-queue__table th{text-align:start;padding:6px 10px;color:var(--_text-subtle);font-weight:600;border-block-end:1px solid var(--_border);white-space:nowrap}.fly-moderation-queue__table td{padding:8px 10px;border-block-end:1px solid var(--_border);vertical-align:top}.fly-moderation-queue__reason-cell{display:table-cell}.fly-moderation-queue__reason{display:block;font-weight:600}.fly-moderation-queue__detail{display:block;margin-block-start:2px;color:var(--_text-tertiary);font-size:11px;max-inline-size:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-moderation-queue__excerpt{max-inline-size:260px;color:var(--_text-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-moderation-queue__subject-link{border:none;background:transparent;padding:0;color:var(--_accent);font:inherit;font-weight:600;cursor:pointer;text-align:start}.fly-moderation-queue__subject-link:hover{text-decoration:underline}.fly-moderation-queue__badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;white-space:nowrap}.fly-moderation-queue__badge--Open{background:color-mix(in srgb,var(--_blue) 12%,#fff);color:var(--_blue-text)}.fly-moderation-queue__badge--UnderReview{background:color-mix(in srgb,var(--_orange) 12%,#fff);color:var(--_orange-text)}.fly-moderation-queue__badge--ActionTaken{background:color-mix(in srgb,var(--_danger) 12%,#fff);color:var(--_danger-text)}.fly-moderation-queue__badge--Dismissed{background:color-mix(in srgb,var(--_green) 12%,#fff);color:var(--_green-text)}.fly-moderation-queue__resolution-note{margin-block-start:4px;color:var(--_text-tertiary);font-size:11px;max-inline-size:200px}.fly-moderation-queue__actions{display:flex;flex-direction:column;align-items:flex-start;gap:6px;white-space:nowrap}.fly-moderation-queue__action-btn{border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:4px 10px;color:var(--_text);font:inherit;font-size:11px;font-weight:600;cursor:pointer}.fly-moderation-queue__action-btn:hover:not(:disabled){background:var(--_surface-hover)}.fly-moderation-queue__action-btn:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__lock-confirm{display:inline-flex;align-items:center;gap:6px}.fly-moderation-queue__load-more{align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:6px 14px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__load-more:hover:not(:disabled){background:var(--_surface-hover)}.fly-moderation-queue__load-more:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:1000}.fly-moderation-queue__overlay-backdrop{position:absolute;inset:0;background:#00000073;border:none;padding:0;margin:0;cursor:pointer}.fly-moderation-queue__dialog{position:relative;z-index:1;inline-size:min(440px,90vw);max-block-size:85vh;overflow-y:auto;background:var(--_surface);border-radius:12px;padding:20px;display:flex;flex-direction:column;gap:14px;box-shadow:0 12px 32px #00000040}.fly-moderation-queue__dialog:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:2px}.fly-moderation-queue__dialog-title{margin:0;font-size:16px;font-weight:700}.fly-moderation-queue__resolution-group{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;border:none}.fly-moderation-queue__resolution-group legend{font-weight:600;padding:0;margin-block-end:4px}.fly-moderation-queue__resolution-option,.fly-moderation-queue__checkbox-row{display:flex;align-items:center;gap:8px;cursor:pointer}.fly-moderation-queue__resolution-option input,.fly-moderation-queue__checkbox-row input{accent-color:var(--_accent);cursor:pointer}.fly-moderation-queue__textarea{inline-size:100%;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;line-height:1.5;resize:vertical}.fly-moderation-queue__textarea:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:1px}.fly-moderation-queue__dialog-actions{display:flex;justify-content:flex-end;gap:8px}.fly-moderation-queue__submit-btn{padding:6px 16px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__submit-btn:hover:not(:disabled){opacity:.9}.fly-moderation-queue__submit-btn:disabled{opacity:.5;cursor:not-allowed}.fly-moderation-queue__cancel-btn{padding:6px 14px;border:1px solid var(--_border);border-radius:var(--_radius);background:transparent;color:var(--_text-subtle);font:inherit;cursor:pointer}.fly-moderation-queue__cancel-btn:hover{background:var(--_surface-hover)}.fly-moderation-queue__danger-btn{padding:6px 14px;border:none;border-radius:var(--_radius);background:var(--_danger);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__danger-btn:hover{opacity:.9}\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 });
19509
19534
  }
19510
19535
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyModerationQueueComponent, decorators: [{
19511
19536
  type: Component,
19512
- args: [{ selector: 'fly-moderation-queue', standalone: true, imports: [CommonModule, FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'fly-moderation-queue' }, template: "<div class=\"fly-moderation-queue__body\">\r\n <!-- \u2500\u2500 Header: count + status filter \u2500\u2500 -->\r\n <header class=\"fly-moderation-queue__header\">\r\n <span class=\"fly-moderation-queue__count\">\r\n {{ 'moderation.count' | translate: { n: page().total } }}\r\n </span>\r\n\r\n <div class=\"fly-moderation-queue__status-filter\" role=\"group\" [attr.aria-label]=\"'moderation.status_label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__status-btn\"\r\n [class.fly-moderation-queue__status-btn--active]=\"status() === null\"\r\n [attr.aria-pressed]=\"status() === null\"\r\n [disabled]=\"loading()\"\r\n (click)=\"onStatusPick(null)\">\r\n {{ 'moderation.status_all' | translate }}\r\n </button>\r\n @for (s of statuses; track s) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__status-btn\"\r\n [class.fly-moderation-queue__status-btn--active]=\"status() === s\"\r\n [attr.aria-pressed]=\"status() === s\"\r\n [disabled]=\"loading()\"\r\n (click)=\"onStatusPick(s)\">\r\n {{ 'moderation.status.' + s | translate }}\r\n </button>\r\n }\r\n </div>\r\n </header>\r\n\r\n <!-- \u2500\u2500 States \u2500\u2500 -->\r\n @if (error()) {\r\n <p class=\"fly-moderation-queue__error\" role=\"alert\">{{ error() }}</p>\r\n } @else if (loading() && page().items.length === 0) {\r\n <p class=\"fly-moderation-queue__status-msg\">{{ 'moderation.loading' | translate }}</p>\r\n } @else if (page().items.length === 0) {\r\n <p class=\"fly-moderation-queue__empty\">{{ 'moderation.empty' | translate }}</p>\r\n } @else {\r\n <!-- \u2500\u2500 Report table \u2500\u2500 -->\r\n <div class=\"fly-moderation-queue__table-wrap\">\r\n <table class=\"fly-moderation-queue__table\">\r\n <caption class=\"fly-moderation-queue__sr-only\">{{ 'moderation.table_caption' | translate }}</caption>\r\n <thead>\r\n <tr>\r\n <th scope=\"col\">{{ 'moderation.col_reason' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_reporter' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_reported' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_excerpt' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_subject' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_status' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_actions' | translate }}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (r of page().items; track r.id) {\r\n <tr>\r\n <td class=\"fly-moderation-queue__reason-cell\">\r\n <span class=\"fly-moderation-queue__reason\">{{ 'comment.reason.' + r.reason | translate }}</span>\r\n @if (r.detail) {\r\n <span class=\"fly-moderation-queue__detail\" [title]=\"r.detail\">{{ r.detail }}</span>\r\n }\r\n </td>\r\n <td>{{ reporterLabel(r) }}</td>\r\n <td>{{ formatDate(r.createdAt) }}</td>\r\n <td class=\"fly-moderation-queue__excerpt\">{{ r.commentExcerpt || '\u2014' }}</td>\r\n <td>\r\n <button type=\"button\" class=\"fly-moderation-queue__subject-link\" [title]=\"subjectHref(r)\" (click)=\"onOpenSubject(r)\">\r\n {{ subjectDisplay(r) }}\r\n </button>\r\n </td>\r\n <td>\r\n <span class=\"fly-moderation-queue__badge\" [class]=\"'fly-moderation-queue__badge--' + r.status\">\r\n {{ 'moderation.status.' + r.status | translate }}\r\n </span>\r\n @if (r.resolutionNote) {\r\n <div class=\"fly-moderation-queue__resolution-note\">{{ r.resolutionNote }}</div>\r\n }\r\n </td>\r\n <td class=\"fly-moderation-queue__actions\">\r\n @if (isResolvable(r.status)) {\r\n <button type=\"button\" class=\"fly-moderation-queue__action-btn\" [disabled]=\"loading()\" (click)=\"openResolve(r)\">\r\n {{ 'moderation.resolve' | translate }}\r\n </button>\r\n }\r\n @if (confirmingLockId() === r.id) {\r\n <span class=\"fly-moderation-queue__lock-confirm\">\r\n <button type=\"button\" class=\"fly-moderation-queue__cancel-btn\" (click)=\"cancelLock()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-moderation-queue__danger-btn\" (click)=\"confirmLock(r)\">\r\n {{ 'moderation.lock_thread' | translate }}\r\n </button>\r\n </span>\r\n } @else {\r\n <button type=\"button\" class=\"fly-moderation-queue__action-btn\" [disabled]=\"loading()\" (click)=\"requestLock(r)\">\r\n {{ 'moderation.lock_thread' | translate }}\r\n </button>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n @if (page().hasMore) {\r\n <button type=\"button\" class=\"fly-moderation-queue__load-more\" [disabled]=\"loading()\" (click)=\"loadMore()\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 Resolve dialog \u2500\u2500 -->\r\n@if (resolvingReport(); as r) {\r\n <div class=\"fly-moderation-queue__overlay\">\r\n <div class=\"fly-moderation-queue__overlay-backdrop\" role=\"button\" tabindex=\"0\"\r\n [attr.aria-label]=\"'common.action.cancel' | translate\"\r\n (click)=\"closeResolve()\"\r\n (keydown.enter)=\"closeResolve()\"\r\n (keydown.space)=\"onOverlayBackdropSpace($event)\"></div>\r\n <div\r\n class=\"fly-moderation-queue__dialog\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"'moderation.resolve_title' | translate\">\r\n <h3 class=\"fly-moderation-queue__dialog-title\">{{ 'moderation.resolve_title' | translate }}</h3>\r\n\r\n <fieldset class=\"fly-moderation-queue__resolution-group\">\r\n <legend>{{ 'moderation.resolution_label' | translate }}</legend>\r\n <label class=\"fly-moderation-queue__resolution-option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"resolutionGroupName\"\r\n [checked]=\"resolutionStatus() === 'ActionTaken'\"\r\n (change)=\"onResolutionStatusChange('ActionTaken')\" />\r\n <span>{{ 'moderation.resolution.ActionTaken' | translate }}</span>\r\n </label>\r\n <label class=\"fly-moderation-queue__resolution-option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"resolutionGroupName\"\r\n [checked]=\"resolutionStatus() === 'Dismissed'\"\r\n (change)=\"onResolutionStatusChange('Dismissed')\" />\r\n <span>{{ 'moderation.resolution.Dismissed' | translate }}</span>\r\n </label>\r\n </fieldset>\r\n\r\n @if (resolutionStatus() === 'ActionTaken') {\r\n <label class=\"fly-moderation-queue__checkbox-row\">\r\n <input type=\"checkbox\" [checked]=\"deleteComment()\" (change)=\"onDeleteCommentToggle($event)\" />\r\n <span>{{ 'moderation.delete_comment_label' | translate }}</span>\r\n </label>\r\n }\r\n\r\n <textarea\r\n class=\"fly-moderation-queue__textarea\"\r\n rows=\"3\"\r\n [attr.aria-label]=\"'moderation.resolution_note_label' | translate\"\r\n [placeholder]=\"'moderation.resolution_note_label' | translate\"\r\n [ngModel]=\"resolutionNote()\"\r\n (ngModelChange)=\"onResolutionNoteChange($event)\"></textarea>\r\n\r\n <div class=\"fly-moderation-queue__dialog-actions\">\r\n <button type=\"button\" class=\"fly-moderation-queue__cancel-btn\" (click)=\"closeResolve()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__submit-btn\"\r\n [disabled]=\"!resolutionStatus()\"\r\n (click)=\"submitResolve(r)\">\r\n {{ 'moderation.resolve_submit' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_text-tertiary: var(--label-tertiary, #94a3b8);--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_blue: var(--system-blue, #0a84ff);--_orange: var(--system-orange, #ff9f0a);--_green: var(--system-green, #32d74b);--_radius: 8px;--_blue-text: #1d4ed8;--_orange-text: #9a3412;--_green-text: #166534;--_danger-text: #b91c1c;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-moderation-queue__body{display:flex;flex-direction:column;gap:16px}.fly-moderation-queue__header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.fly-moderation-queue__count{font-weight:700;font-size:14px}.fly-moderation-queue__status-filter{display:inline-flex;flex-wrap:wrap;border:1px solid var(--_border);border-radius:var(--_radius);overflow:hidden}.fly-moderation-queue__status-btn{padding:5px 12px;border:none;border-inline-end:1px solid var(--_border);background:transparent;color:var(--_text-subtle);font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__status-btn:last-child{border-inline-end:none}.fly-moderation-queue__status-btn:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__status-btn--active{background:var(--_accent);color:#fff}.fly-moderation-queue__empty,.fly-moderation-queue__status-msg{margin:0;color:var(--_text-subtle);text-align:center;padding:16px 0}.fly-moderation-queue__error{margin:0;padding:8px 12px;border-radius:var(--_radius);background:color-mix(in srgb,var(--_danger) 12%,transparent);color:var(--_danger);font-size:12px}.fly-moderation-queue__sr-only{position:absolute;inline-size:1px;block-size:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.fly-moderation-queue__table-wrap{overflow-x:auto}.fly-moderation-queue__table{inline-size:100%;border-collapse:collapse;font-size:12px}.fly-moderation-queue__table th{text-align:start;padding:6px 10px;color:var(--_text-subtle);font-weight:600;border-block-end:1px solid var(--_border);white-space:nowrap}.fly-moderation-queue__table td{padding:8px 10px;border-block-end:1px solid var(--_border);vertical-align:top}.fly-moderation-queue__reason-cell{display:table-cell}.fly-moderation-queue__reason{display:block;font-weight:600}.fly-moderation-queue__detail{display:block;margin-block-start:2px;color:var(--_text-tertiary);font-size:11px;max-inline-size:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-moderation-queue__excerpt{max-inline-size:260px;color:var(--_text-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-moderation-queue__subject-link{border:none;background:transparent;padding:0;color:var(--_accent);font:inherit;font-weight:600;cursor:pointer;text-align:start}.fly-moderation-queue__subject-link:hover{text-decoration:underline}.fly-moderation-queue__badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;white-space:nowrap}.fly-moderation-queue__badge--Open{background:color-mix(in srgb,var(--_blue) 12%,#fff);color:var(--_blue-text)}.fly-moderation-queue__badge--UnderReview{background:color-mix(in srgb,var(--_orange) 12%,#fff);color:var(--_orange-text)}.fly-moderation-queue__badge--ActionTaken{background:color-mix(in srgb,var(--_danger) 12%,#fff);color:var(--_danger-text)}.fly-moderation-queue__badge--Dismissed{background:color-mix(in srgb,var(--_green) 12%,#fff);color:var(--_green-text)}.fly-moderation-queue__resolution-note{margin-block-start:4px;color:var(--_text-tertiary);font-size:11px;max-inline-size:200px}.fly-moderation-queue__actions{display:flex;flex-direction:column;align-items:flex-start;gap:6px;white-space:nowrap}.fly-moderation-queue__action-btn{border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:4px 10px;color:var(--_text);font:inherit;font-size:11px;font-weight:600;cursor:pointer}.fly-moderation-queue__action-btn:hover:not(:disabled){background:var(--_surface-hover)}.fly-moderation-queue__action-btn:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__lock-confirm{display:inline-flex;align-items:center;gap:6px}.fly-moderation-queue__load-more{align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:6px 14px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__load-more:hover:not(:disabled){background:var(--_surface-hover)}.fly-moderation-queue__load-more:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:1000}.fly-moderation-queue__overlay-backdrop{position:absolute;inset:0;background:#00000073;border:none;padding:0;margin:0;cursor:pointer}.fly-moderation-queue__dialog{position:relative;z-index:1;inline-size:min(440px,90vw);max-block-size:85vh;overflow-y:auto;background:var(--_surface);border-radius:12px;padding:20px;display:flex;flex-direction:column;gap:14px;box-shadow:0 12px 32px #00000040}.fly-moderation-queue__dialog:focus-visible{outline:2px solid var(--_accent);outline-offset:2px}.fly-moderation-queue__dialog-title{margin:0;font-size:16px;font-weight:700}.fly-moderation-queue__resolution-group{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;border:none}.fly-moderation-queue__resolution-group legend{font-weight:600;padding:0;margin-block-end:4px}.fly-moderation-queue__resolution-option,.fly-moderation-queue__checkbox-row{display:flex;align-items:center;gap:8px;cursor:pointer}.fly-moderation-queue__resolution-option input,.fly-moderation-queue__checkbox-row input{accent-color:var(--_accent);cursor:pointer}.fly-moderation-queue__textarea{inline-size:100%;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;line-height:1.5;resize:vertical}.fly-moderation-queue__textarea:focus-visible{outline:2px solid var(--_accent);outline-offset:1px}.fly-moderation-queue__dialog-actions{display:flex;justify-content:flex-end;gap:8px}.fly-moderation-queue__submit-btn{padding:6px 16px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__submit-btn:hover:not(:disabled){opacity:.9}.fly-moderation-queue__submit-btn:disabled{opacity:.5;cursor:not-allowed}.fly-moderation-queue__cancel-btn{padding:6px 14px;border:1px solid var(--_border);border-radius:var(--_radius);background:transparent;color:var(--_text-subtle);font:inherit;cursor:pointer}.fly-moderation-queue__cancel-btn:hover{background:var(--_surface-hover)}.fly-moderation-queue__danger-btn{padding:6px 14px;border:none;border-radius:var(--_radius);background:var(--_danger);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__danger-btn:hover{opacity:.9}\n"] }]
19537
+ args: [{ selector: 'fly-moderation-queue', standalone: true, imports: [CommonModule, FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'fly-moderation-queue' }, template: "<div class=\"fly-moderation-queue__body\">\r\n <!-- \u2500\u2500 Header: count + status filter \u2500\u2500 -->\r\n <header class=\"fly-moderation-queue__header\">\r\n <span class=\"fly-moderation-queue__count\">\r\n {{ 'moderation.count' | translate: { n: page().total } }}\r\n </span>\r\n\r\n <div class=\"fly-moderation-queue__status-filter\" role=\"group\" [attr.aria-label]=\"'moderation.status_label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__status-btn\"\r\n [class.fly-moderation-queue__status-btn--active]=\"status() === null\"\r\n [attr.aria-pressed]=\"status() === null\"\r\n [disabled]=\"loading()\"\r\n (click)=\"onStatusPick(null)\">\r\n {{ 'moderation.status_all' | translate }}\r\n </button>\r\n @for (s of statuses; track s) {\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__status-btn\"\r\n [class.fly-moderation-queue__status-btn--active]=\"status() === s\"\r\n [attr.aria-pressed]=\"status() === s\"\r\n [disabled]=\"loading()\"\r\n (click)=\"onStatusPick(s)\">\r\n {{ 'moderation.status.' + s | translate }}\r\n </button>\r\n }\r\n </div>\r\n </header>\r\n\r\n <!-- \u2500\u2500 States \u2500\u2500 -->\r\n @if (error()) {\r\n <p class=\"fly-moderation-queue__error\" role=\"alert\">{{ error() }}</p>\r\n } @else if (loading() && page().items.length === 0) {\r\n <p class=\"fly-moderation-queue__status-msg\">{{ 'moderation.loading' | translate }}</p>\r\n } @else if (page().items.length === 0) {\r\n <p class=\"fly-moderation-queue__empty\">{{ 'moderation.empty' | translate }}</p>\r\n } @else {\r\n <!-- \u2500\u2500 Report table \u2500\u2500 -->\r\n <div class=\"fly-moderation-queue__table-wrap\">\r\n <table class=\"fly-moderation-queue__table\">\r\n <caption class=\"fly-moderation-queue__sr-only\">{{ 'moderation.table_caption' | translate }}</caption>\r\n <thead>\r\n <tr>\r\n <th scope=\"col\">{{ 'moderation.col_reason' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_reporter' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_reported' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_excerpt' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_subject' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_status' | translate }}</th>\r\n <th scope=\"col\">{{ 'moderation.col_actions' | translate }}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (r of page().items; track r.id) {\r\n <tr>\r\n <td class=\"fly-moderation-queue__reason-cell\">\r\n <span class=\"fly-moderation-queue__reason\">{{ 'comment.reason.' + r.reason | translate }}</span>\r\n @if (r.detail) {\r\n <span class=\"fly-moderation-queue__detail\" [title]=\"r.detail\">{{ r.detail }}</span>\r\n }\r\n </td>\r\n <td>{{ reporterLabel(r) }}</td>\r\n <td>{{ formatDate(r.createdAt) }}</td>\r\n <td class=\"fly-moderation-queue__excerpt\">{{ r.commentExcerpt || '\u2014' }}</td>\r\n <td>\r\n <button type=\"button\" class=\"fly-moderation-queue__subject-link\" [title]=\"subjectHref(r)\" (click)=\"onOpenSubject(r)\">\r\n {{ subjectDisplay(r) }}\r\n </button>\r\n </td>\r\n <td>\r\n <span class=\"fly-moderation-queue__badge\" [class]=\"'fly-moderation-queue__badge--' + r.status\">\r\n {{ 'moderation.status.' + r.status | translate }}\r\n </span>\r\n @if (r.resolutionNote) {\r\n <div class=\"fly-moderation-queue__resolution-note\">{{ r.resolutionNote }}</div>\r\n }\r\n </td>\r\n <td class=\"fly-moderation-queue__actions\">\r\n @if (isResolvable(r.status)) {\r\n <button type=\"button\" class=\"fly-moderation-queue__action-btn\" [disabled]=\"loading()\" (click)=\"openResolve(r)\">\r\n {{ 'moderation.resolve' | translate }}\r\n </button>\r\n }\r\n @if (confirmingLockId() === r.id) {\r\n <span class=\"fly-moderation-queue__lock-confirm\">\r\n <button type=\"button\" class=\"fly-moderation-queue__cancel-btn\" (click)=\"cancelLock()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button type=\"button\" class=\"fly-moderation-queue__danger-btn\" (click)=\"confirmLock(r)\">\r\n {{ 'moderation.lock_thread' | translate }}\r\n </button>\r\n </span>\r\n } @else {\r\n <button type=\"button\" class=\"fly-moderation-queue__action-btn\" [disabled]=\"loading()\" (click)=\"requestLock(r)\">\r\n {{ 'moderation.lock_thread' | translate }}\r\n </button>\r\n }\r\n </td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n @if (page().hasMore) {\r\n <button type=\"button\" class=\"fly-moderation-queue__load-more\" [disabled]=\"loading()\" (click)=\"loadMore()\">\r\n {{ 'comment.load_more' | translate }}\r\n </button>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 Resolve dialog \u2500\u2500 -->\r\n@if (resolvingReport(); as r) {\r\n <div class=\"fly-moderation-queue__overlay\">\r\n <div class=\"fly-moderation-queue__overlay-backdrop\" role=\"button\" tabindex=\"0\"\r\n [attr.aria-label]=\"'common.action.cancel' | translate\"\r\n (click)=\"closeResolve()\"\r\n (keydown.enter)=\"closeResolve()\"\r\n (keydown.space)=\"onOverlayBackdropSpace($event)\"></div>\r\n <div\r\n class=\"fly-moderation-queue__dialog\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"'moderation.resolve_title' | translate\">\r\n <h3 class=\"fly-moderation-queue__dialog-title\">{{ 'moderation.resolve_title' | translate }}</h3>\r\n\r\n <fieldset class=\"fly-moderation-queue__resolution-group\">\r\n <legend>{{ 'moderation.resolution_label' | translate }}</legend>\r\n <label class=\"fly-moderation-queue__resolution-option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"resolutionGroupName\"\r\n [checked]=\"resolutionStatus() === 'ActionTaken'\"\r\n (change)=\"onResolutionStatusChange('ActionTaken')\" />\r\n <span>{{ 'moderation.resolution.ActionTaken' | translate }}</span>\r\n </label>\r\n <label class=\"fly-moderation-queue__resolution-option\">\r\n <input\r\n type=\"radio\"\r\n [name]=\"resolutionGroupName\"\r\n [checked]=\"resolutionStatus() === 'Dismissed'\"\r\n (change)=\"onResolutionStatusChange('Dismissed')\" />\r\n <span>{{ 'moderation.resolution.Dismissed' | translate }}</span>\r\n </label>\r\n </fieldset>\r\n\r\n @if (resolutionStatus() === 'ActionTaken') {\r\n <label class=\"fly-moderation-queue__checkbox-row\">\r\n <input type=\"checkbox\" [checked]=\"deleteComment()\" (change)=\"onDeleteCommentToggle($event)\" />\r\n <span>{{ 'moderation.delete_comment_label' | translate }}</span>\r\n </label>\r\n }\r\n\r\n <textarea\r\n class=\"fly-moderation-queue__textarea\"\r\n rows=\"3\"\r\n [attr.aria-label]=\"'moderation.resolution_note_label' | translate\"\r\n [placeholder]=\"'moderation.resolution_note_label' | translate\"\r\n [ngModel]=\"resolutionNote()\"\r\n (ngModelChange)=\"onResolutionNoteChange($event)\"></textarea>\r\n\r\n <div class=\"fly-moderation-queue__dialog-actions\">\r\n <button type=\"button\" class=\"fly-moderation-queue__cancel-btn\" (click)=\"closeResolve()\">\r\n {{ 'common.action.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fly-moderation-queue__submit-btn\"\r\n [disabled]=\"!resolutionStatus()\"\r\n (click)=\"submitResolve(r)\">\r\n {{ 'moderation.resolve_submit' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-hover: var(--surface-hover, #f1f5f9);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_text-tertiary: var(--label-tertiary, #94a3b8);--_fill: var(--fill-tertiary, #f3f4f6);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_blue: var(--system-blue, #0a84ff);--_orange: var(--system-orange, #ff9f0a);--_green: var(--system-green, #32d74b);--_radius: 8px;--_blue-text: #1d4ed8;--_orange-text: #9a3412;--_green-text: #166534;--_danger-text: #b91c1c;display:block;inline-size:100%;color:var(--_text);font-size:13px}.fly-moderation-queue__body{display:flex;flex-direction:column;gap:16px}.fly-moderation-queue__header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.fly-moderation-queue__count{font-weight:700;font-size:14px}.fly-moderation-queue__status-filter{display:inline-flex;flex-wrap:wrap;border:1px solid var(--_border);border-radius:var(--_radius);overflow:hidden}.fly-moderation-queue__status-btn{padding:5px 12px;border:none;border-inline-end:1px solid var(--_border);background:transparent;color:var(--_text-subtle);font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__status-btn:last-child{border-inline-end:none}.fly-moderation-queue__status-btn:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__status-btn--active{background:var(--_accent);color:#fff}.fly-moderation-queue__empty,.fly-moderation-queue__status-msg{margin:0;color:var(--_text-subtle);text-align:center;padding:16px 0}.fly-moderation-queue__error{margin:0;padding:8px 12px;border-radius:var(--_radius);background:color-mix(in srgb,var(--_danger) 12%,transparent);color:var(--_danger);font-size:12px}.fly-moderation-queue__sr-only{position:absolute;inline-size:1px;block-size:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.fly-moderation-queue__table-wrap{overflow-x:auto}.fly-moderation-queue__table{inline-size:100%;border-collapse:collapse;font-size:12px}.fly-moderation-queue__table th{text-align:start;padding:6px 10px;color:var(--_text-subtle);font-weight:600;border-block-end:1px solid var(--_border);white-space:nowrap}.fly-moderation-queue__table td{padding:8px 10px;border-block-end:1px solid var(--_border);vertical-align:top}.fly-moderation-queue__reason-cell{display:table-cell}.fly-moderation-queue__reason{display:block;font-weight:600}.fly-moderation-queue__detail{display:block;margin-block-start:2px;color:var(--_text-tertiary);font-size:11px;max-inline-size:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-moderation-queue__excerpt{max-inline-size:260px;color:var(--_text-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-moderation-queue__subject-link{border:none;background:transparent;padding:0;color:var(--_accent);font:inherit;font-weight:600;cursor:pointer;text-align:start}.fly-moderation-queue__subject-link:hover{text-decoration:underline}.fly-moderation-queue__badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;white-space:nowrap}.fly-moderation-queue__badge--Open{background:color-mix(in srgb,var(--_blue) 12%,#fff);color:var(--_blue-text)}.fly-moderation-queue__badge--UnderReview{background:color-mix(in srgb,var(--_orange) 12%,#fff);color:var(--_orange-text)}.fly-moderation-queue__badge--ActionTaken{background:color-mix(in srgb,var(--_danger) 12%,#fff);color:var(--_danger-text)}.fly-moderation-queue__badge--Dismissed{background:color-mix(in srgb,var(--_green) 12%,#fff);color:var(--_green-text)}.fly-moderation-queue__resolution-note{margin-block-start:4px;color:var(--_text-tertiary);font-size:11px;max-inline-size:200px}.fly-moderation-queue__actions{display:flex;flex-direction:column;align-items:flex-start;gap:6px;white-space:nowrap}.fly-moderation-queue__action-btn{border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:4px 10px;color:var(--_text);font:inherit;font-size:11px;font-weight:600;cursor:pointer}.fly-moderation-queue__action-btn:hover:not(:disabled){background:var(--_surface-hover)}.fly-moderation-queue__action-btn:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__lock-confirm{display:inline-flex;align-items:center;gap:6px}.fly-moderation-queue__load-more{align-self:flex-start;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);padding:6px 14px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__load-more:hover:not(:disabled){background:var(--_surface-hover)}.fly-moderation-queue__load-more:disabled{opacity:.6;cursor:not-allowed}.fly-moderation-queue__overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:1000}.fly-moderation-queue__overlay-backdrop{position:absolute;inset:0;background:#00000073;border:none;padding:0;margin:0;cursor:pointer}.fly-moderation-queue__dialog{position:relative;z-index:1;inline-size:min(440px,90vw);max-block-size:85vh;overflow-y:auto;background:var(--_surface);border-radius:12px;padding:20px;display:flex;flex-direction:column;gap:14px;box-shadow:0 12px 32px #00000040}.fly-moderation-queue__dialog:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:2px}.fly-moderation-queue__dialog-title{margin:0;font-size:16px;font-weight:700}.fly-moderation-queue__resolution-group{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;border:none}.fly-moderation-queue__resolution-group legend{font-weight:600;padding:0;margin-block-end:4px}.fly-moderation-queue__resolution-option,.fly-moderation-queue__checkbox-row{display:flex;align-items:center;gap:8px;cursor:pointer}.fly-moderation-queue__resolution-option input,.fly-moderation-queue__checkbox-row input{accent-color:var(--_accent);cursor:pointer}.fly-moderation-queue__textarea{inline-size:100%;padding:8px 12px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;line-height:1.5;resize:vertical}.fly-moderation-queue__textarea:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:1px}.fly-moderation-queue__dialog-actions{display:flex;justify-content:flex-end;gap:8px}.fly-moderation-queue__submit-btn{padding:6px 16px;border:none;border-radius:var(--_radius);background:var(--_accent);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__submit-btn:hover:not(:disabled){opacity:.9}.fly-moderation-queue__submit-btn:disabled{opacity:.5;cursor:not-allowed}.fly-moderation-queue__cancel-btn{padding:6px 14px;border:1px solid var(--_border);border-radius:var(--_radius);background:transparent;color:var(--_text-subtle);font:inherit;cursor:pointer}.fly-moderation-queue__cancel-btn:hover{background:var(--_surface-hover)}.fly-moderation-queue__danger-btn{padding:6px 14px;border:none;border-radius:var(--_radius);background:var(--_danger);color:#fff;font:inherit;font-weight:600;cursor:pointer}.fly-moderation-queue__danger-btn:hover{opacity:.9}\n"] }]
19513
19538
  }], propDecorators: { page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: true }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], resolveDisplayName: [{ type: i0.Input, args: [{ isSignal: true, alias: "resolveDisplayName", required: false }] }], loadPage: [{ type: i0.Output, args: ["loadPage"] }], resolve: [{ type: i0.Output, args: ["resolve"] }], lockThread: [{ type: i0.Output, args: ["lockThread"] }], openSubject: [{ type: i0.Output, args: ["openSubject"] }], onEscape: [{
19514
19539
  type: HostListener,
19515
19540
  args: ['document:keydown.escape']
@@ -19945,11 +19970,11 @@ class FlyStrategySelectorComponent {
19945
19970
  this.selectionChange.emit(null);
19946
19971
  }
19947
19972
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyStrategySelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19948
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyStrategySelectorComponent, isStandalone: true, selector: "fly-strategy-selector", inputs: { searchFn: { classPropertyName: "searchFn", publicName: "searchFn", isSignal: true, isRequired: false, transformFunction: null }, initialSelection: { classPropertyName: "initialSelection", publicName: "initialSelection", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)" }, properties: { "class.fly-strategy-selector--open": "isOpen()" }, classAttribute: "fly-strategy-selector" }, viewQueries: [{ propertyName: "searchEl", first: true, predicate: ["searchRef"], descendants: true }], ngImport: i0, template: "@if (selected(); as pick) {\r\n <div class=\"fly-strategy-selector__chip\" role=\"group\" [attr.aria-label]=\"pick.title\">\r\n <span class=\"fly-strategy-selector__chip-icon\" aria-hidden=\"true\">\r\n @if (pick.strategyIcon) {\r\n <i class=\"pi {{ pick.strategyIcon }}\"></i>\r\n } @else {\r\n <i class=\"pi pi-compass\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-strategy-selector__chip-body\">\r\n <span class=\"fly-strategy-selector__chip-title\" [title]=\"pick.title\">{{ pick.title }}</span>\r\n <span class=\"fly-strategy-selector__chip-strategy\" [title]=\"pick.strategyTitle\">{{ pick.strategyTitle }}</span>\r\n </span>\r\n <button\r\n type=\"button\"\r\n class=\"fly-strategy-selector__chip-remove\"\r\n [attr.aria-label]=\"'strategy_selector.remove' | translate: { name: pick.title }\"\r\n (click)=\"remove()\">\r\n \u2715\r\n </button>\r\n </div>\r\n} @else {\r\n <div\r\n class=\"fly-strategy-selector__wrap\"\r\n [flyClickOutsideEnabled]=\"isOpen()\"\r\n (flyClickOutside)=\"close()\"\r\n >\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-strategy-selector__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-controls=\"fly-strategy-selector-listbox\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"placeholder() || ('strategy_selector.search_placeholder' | translate)\"\r\n [placeholder]=\"placeholder() || ('strategy_selector.search_placeholder' | translate)\"\r\n [value]=\"searchTerm()\"\r\n (focus)=\"open()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n (keydown)=\"onPanelKeydown($event)\"\r\n />\r\n\r\n @if (isOpen()) {\r\n <div class=\"fly-strategy-selector__panel\">\r\n <div\r\n class=\"fly-strategy-selector__listbox\"\r\n role=\"listbox\"\r\n id=\"fly-strategy-selector-listbox\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n >\r\n @if (loading()) {\r\n <div class=\"fly-strategy-selector__status\" role=\"status\">\r\n {{ 'strategy_selector.loading' | translate }}\r\n </div>\r\n } @else if (loadFailed()) {\r\n <div class=\"fly-strategy-selector__status fly-strategy-selector__status--error\" role=\"alert\">\r\n <span>{{ 'strategy_selector.error' | translate }}</span>\r\n <button type=\"button\" class=\"fly-strategy-selector__retry\" (click)=\"retry()\">\r\n {{ 'strategy_selector.retry' | translate }}\r\n </button>\r\n </div>\r\n } @else {\r\n @for (group of groups(); track group.strategyId) {\r\n <div class=\"fly-strategy-selector__group\" role=\"presentation\">\r\n <i class=\"pi {{ group.strategyIcon || 'pi-compass' }}\" aria-hidden=\"true\"></i>\r\n <span class=\"fly-strategy-selector__group-title\">{{ group.strategyTitle }}</span>\r\n </div>\r\n @for (item of group.items; track item.id) {\r\n <div\r\n class=\"fly-strategy-selector__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"optionId(navIndexOf(item.id))\"\r\n [attr.aria-selected]=\"false\"\r\n [class.fly-strategy-selector__option--active]=\"navIndexOf(item.id) === activeIndex()\"\r\n (click)=\"pick(item)\"\r\n (keydown.enter)=\"pick(item)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(item.id))\"\r\n >\r\n <span class=\"fly-strategy-selector__option-title\">{{ item.title }}</span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (groups().length === 0) {\r\n <div class=\"fly-strategy-selector__status\" role=\"presentation\">\r\n {{ 'strategy_selector.no_results' | translate }}\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n}\r\n", styles: [":host{--_surface: var(--surface-card, #fff);--_surface-panel: var(--glass-bg-elevated, var(--surface-card, #fff));--_panel-blur: var(--glass-blur, 40px);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_fill: var(--fill-tertiary, #f3f4f6);--_surface-hover: var(--surface-hover, #f1f5f9);--_accent: var(--accent);--_primary: var(--primary-color, var(--_accent));--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}:host,:host *,:host *:before,:host *:after{box-sizing:border-box}.fly-strategy-selector__chip{display:flex;align-items:center;gap:8px;padding-block:5px;padding-inline:8px;border:1px solid var(--_border);border-radius:10px;background:var(--_fill);max-inline-size:100%}.fly-strategy-selector__chip-icon{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:22px;block-size:22px;border-radius:50%;background:color-mix(in srgb,var(--_accent, var(--_text-subtle)) 14%,transparent);color:var(--_accent, var(--_text-subtle));font-size:12px;line-height:1}.fly-strategy-selector__chip-body{display:flex;flex-direction:column;min-inline-size:0;flex:1}.fly-strategy-selector__chip-title{font-size:12px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__chip-strategy{font-size:11px;color:var(--_text-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__chip-remove{border:none;background:transparent;padding:4px;border-radius:50%;color:var(--_text-subtle);font-size:10px;line-height:1;cursor:pointer;flex:none}.fly-strategy-selector__chip-remove:hover{background:color-mix(in srgb,var(--_danger) 18%,transparent);color:var(--_danger)}.fly-strategy-selector__wrap{position:relative;inline-size:100%}.fly-strategy-selector__search-input{inline-size:100%;min-block-size:2.25rem;padding-block:5px;padding-inline:10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-strategy-selector__search-input:focus-visible{outline:2px solid var(--_primary);outline-offset:-1px}.fly-strategy-selector__panel{position:absolute;z-index:60;inset-inline:0;inset-block-start:calc(100% + 4px);display:flex;flex-direction:column;max-block-size:19rem;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-panel);-webkit-backdrop-filter:blur(var(--_panel-blur));backdrop-filter:blur(var(--_panel-blur));box-shadow:0 12px 32px #0000002e;overflow:hidden}.fly-strategy-selector__listbox{flex:1 1 auto;overflow-y:auto;padding-block:4px}.fly-strategy-selector__group{display:flex;align-items:center;gap:6px;padding-block:6px 3px;padding-inline:10px;color:var(--_text-subtle);font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.fly-strategy-selector__group .pi{font-size:11px}.fly-strategy-selector__group-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__option{padding-block:6px;padding-inline:26px 10px;cursor:pointer}.fly-strategy-selector__option--active{background:var(--_surface-hover)}.fly-strategy-selector__option-title{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__status{display:flex;align-items:center;gap:8px;padding-block:10px;padding-inline:10px;color:var(--_text-subtle)}.fly-strategy-selector__status--error{color:var(--_danger)}.fly-strategy-selector__retry{border:1px solid var(--_border);border-radius:6px;background:var(--_surface);padding-block:2px;padding-inline:8px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled", "flyClickOutsideIgnore"], outputs: ["flyClickOutside"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
19973
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyStrategySelectorComponent, isStandalone: true, selector: "fly-strategy-selector", inputs: { searchFn: { classPropertyName: "searchFn", publicName: "searchFn", isSignal: true, isRequired: false, transformFunction: null }, initialSelection: { classPropertyName: "initialSelection", publicName: "initialSelection", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event)" }, properties: { "class.fly-strategy-selector--open": "isOpen()" }, classAttribute: "fly-strategy-selector" }, viewQueries: [{ propertyName: "searchEl", first: true, predicate: ["searchRef"], descendants: true }], ngImport: i0, template: "@if (selected(); as pick) {\r\n <div class=\"fly-strategy-selector__chip\" role=\"group\" [attr.aria-label]=\"pick.title\">\r\n <span class=\"fly-strategy-selector__chip-icon\" aria-hidden=\"true\">\r\n @if (pick.strategyIcon) {\r\n <i class=\"pi {{ pick.strategyIcon }}\"></i>\r\n } @else {\r\n <i class=\"pi pi-compass\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-strategy-selector__chip-body\">\r\n <span class=\"fly-strategy-selector__chip-title\" [title]=\"pick.title\">{{ pick.title }}</span>\r\n <span class=\"fly-strategy-selector__chip-strategy\" [title]=\"pick.strategyTitle\">{{ pick.strategyTitle }}</span>\r\n </span>\r\n <button\r\n type=\"button\"\r\n class=\"fly-strategy-selector__chip-remove\"\r\n [attr.aria-label]=\"'strategy_selector.remove' | translate: { name: pick.title }\"\r\n (click)=\"remove()\">\r\n \u2715\r\n </button>\r\n </div>\r\n} @else {\r\n <div\r\n class=\"fly-strategy-selector__wrap\"\r\n [flyClickOutsideEnabled]=\"isOpen()\"\r\n (flyClickOutside)=\"close()\"\r\n >\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-strategy-selector__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-controls=\"fly-strategy-selector-listbox\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"placeholder() || ('strategy_selector.search_placeholder' | translate)\"\r\n [placeholder]=\"placeholder() || ('strategy_selector.search_placeholder' | translate)\"\r\n [value]=\"searchTerm()\"\r\n (focus)=\"open()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n (keydown)=\"onPanelKeydown($event)\"\r\n />\r\n\r\n @if (isOpen()) {\r\n <div class=\"fly-strategy-selector__panel\">\r\n <div\r\n class=\"fly-strategy-selector__listbox\"\r\n role=\"listbox\"\r\n id=\"fly-strategy-selector-listbox\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n >\r\n @if (loading()) {\r\n <div class=\"fly-strategy-selector__status\" role=\"status\">\r\n {{ 'strategy_selector.loading' | translate }}\r\n </div>\r\n } @else if (loadFailed()) {\r\n <div class=\"fly-strategy-selector__status fly-strategy-selector__status--error\" role=\"alert\">\r\n <span>{{ 'strategy_selector.error' | translate }}</span>\r\n <button type=\"button\" class=\"fly-strategy-selector__retry\" (click)=\"retry()\">\r\n {{ 'strategy_selector.retry' | translate }}\r\n </button>\r\n </div>\r\n } @else {\r\n @for (group of groups(); track group.strategyId) {\r\n <div class=\"fly-strategy-selector__group\" role=\"presentation\">\r\n <i class=\"pi {{ group.strategyIcon || 'pi-compass' }}\" aria-hidden=\"true\"></i>\r\n <span class=\"fly-strategy-selector__group-title\">{{ group.strategyTitle }}</span>\r\n </div>\r\n @for (item of group.items; track item.id) {\r\n <div\r\n class=\"fly-strategy-selector__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"optionId(navIndexOf(item.id))\"\r\n [attr.aria-selected]=\"false\"\r\n [class.fly-strategy-selector__option--active]=\"navIndexOf(item.id) === activeIndex()\"\r\n (click)=\"pick(item)\"\r\n (keydown.enter)=\"pick(item)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(item.id))\"\r\n >\r\n <span class=\"fly-strategy-selector__option-title\">{{ item.title }}</span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (groups().length === 0) {\r\n <div class=\"fly-strategy-selector__status\" role=\"presentation\">\r\n {{ 'strategy_selector.no_results' | translate }}\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n}\r\n", styles: [":host{--_surface: var(--surface-card, #fff);--_surface-panel: var(--glass-bg-elevated, var(--surface-card, #fff));--_panel-blur: var(--glass-blur, 40px);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_fill: var(--fill-tertiary, #f3f4f6);--_surface-hover: var(--surface-hover, #f1f5f9);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}:host,:host *,:host *:before,:host *:after{box-sizing:border-box}.fly-strategy-selector__chip{display:flex;align-items:center;gap:8px;padding-block:5px;padding-inline:8px;border:1px solid var(--_border);border-radius:10px;background:var(--_fill);max-inline-size:100%}.fly-strategy-selector__chip-icon{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:22px;block-size:22px;border-radius:50%;background:color-mix(in srgb,var(--_accent, var(--_text-subtle)) 14%,transparent);color:var(--_accent, var(--_text-subtle));font-size:12px;line-height:1}.fly-strategy-selector__chip-body{display:flex;flex-direction:column;min-inline-size:0;flex:1}.fly-strategy-selector__chip-title{font-size:12px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__chip-strategy{font-size:11px;color:var(--_text-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__chip-remove{border:none;background:transparent;padding:4px;border-radius:50%;color:var(--_text-subtle);font-size:10px;line-height:1;cursor:pointer;flex:none}.fly-strategy-selector__chip-remove:hover{background:color-mix(in srgb,var(--_danger) 18%,transparent);color:var(--_danger)}.fly-strategy-selector__wrap{position:relative;inline-size:100%}.fly-strategy-selector__search-input{inline-size:100%;min-block-size:2.25rem;padding-block:5px;padding-inline:10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-strategy-selector__search-input:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:-1px}.fly-strategy-selector__panel{position:absolute;z-index:60;inset-inline:0;inset-block-start:calc(100% + 4px);display:flex;flex-direction:column;max-block-size:19rem;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-panel);-webkit-backdrop-filter:blur(var(--_panel-blur));backdrop-filter:blur(var(--_panel-blur));box-shadow:0 12px 32px #0000002e;overflow:hidden}.fly-strategy-selector__listbox{flex:1 1 auto;overflow-y:auto;padding-block:4px}.fly-strategy-selector__group{display:flex;align-items:center;gap:6px;padding-block:6px 3px;padding-inline:10px;color:var(--_text-subtle);font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.fly-strategy-selector__group .pi{font-size:11px}.fly-strategy-selector__group-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__option{padding-block:6px;padding-inline:26px 10px;cursor:pointer}.fly-strategy-selector__option--active{background:var(--_surface-hover)}.fly-strategy-selector__option-title{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__status{display:flex;align-items:center;gap:8px;padding-block:10px;padding-inline:10px;color:var(--_text-subtle)}.fly-strategy-selector__status--error{color:var(--_danger)}.fly-strategy-selector__retry{border:1px solid var(--_border);border-radius:6px;background:var(--_surface);padding-block:2px;padding-inline:8px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled", "flyClickOutsideIgnore"], outputs: ["flyClickOutside"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
19949
19974
  }
19950
19975
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyStrategySelectorComponent, decorators: [{
19951
19976
  type: Component,
19952
- args: [{ selector: 'fly-strategy-selector', standalone: true, imports: [CommonModule, TranslatePipe, FlyClickOutsideDirective], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'fly-strategy-selector', '[class.fly-strategy-selector--open]': 'isOpen()' }, template: "@if (selected(); as pick) {\r\n <div class=\"fly-strategy-selector__chip\" role=\"group\" [attr.aria-label]=\"pick.title\">\r\n <span class=\"fly-strategy-selector__chip-icon\" aria-hidden=\"true\">\r\n @if (pick.strategyIcon) {\r\n <i class=\"pi {{ pick.strategyIcon }}\"></i>\r\n } @else {\r\n <i class=\"pi pi-compass\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-strategy-selector__chip-body\">\r\n <span class=\"fly-strategy-selector__chip-title\" [title]=\"pick.title\">{{ pick.title }}</span>\r\n <span class=\"fly-strategy-selector__chip-strategy\" [title]=\"pick.strategyTitle\">{{ pick.strategyTitle }}</span>\r\n </span>\r\n <button\r\n type=\"button\"\r\n class=\"fly-strategy-selector__chip-remove\"\r\n [attr.aria-label]=\"'strategy_selector.remove' | translate: { name: pick.title }\"\r\n (click)=\"remove()\">\r\n \u2715\r\n </button>\r\n </div>\r\n} @else {\r\n <div\r\n class=\"fly-strategy-selector__wrap\"\r\n [flyClickOutsideEnabled]=\"isOpen()\"\r\n (flyClickOutside)=\"close()\"\r\n >\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-strategy-selector__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-controls=\"fly-strategy-selector-listbox\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"placeholder() || ('strategy_selector.search_placeholder' | translate)\"\r\n [placeholder]=\"placeholder() || ('strategy_selector.search_placeholder' | translate)\"\r\n [value]=\"searchTerm()\"\r\n (focus)=\"open()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n (keydown)=\"onPanelKeydown($event)\"\r\n />\r\n\r\n @if (isOpen()) {\r\n <div class=\"fly-strategy-selector__panel\">\r\n <div\r\n class=\"fly-strategy-selector__listbox\"\r\n role=\"listbox\"\r\n id=\"fly-strategy-selector-listbox\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n >\r\n @if (loading()) {\r\n <div class=\"fly-strategy-selector__status\" role=\"status\">\r\n {{ 'strategy_selector.loading' | translate }}\r\n </div>\r\n } @else if (loadFailed()) {\r\n <div class=\"fly-strategy-selector__status fly-strategy-selector__status--error\" role=\"alert\">\r\n <span>{{ 'strategy_selector.error' | translate }}</span>\r\n <button type=\"button\" class=\"fly-strategy-selector__retry\" (click)=\"retry()\">\r\n {{ 'strategy_selector.retry' | translate }}\r\n </button>\r\n </div>\r\n } @else {\r\n @for (group of groups(); track group.strategyId) {\r\n <div class=\"fly-strategy-selector__group\" role=\"presentation\">\r\n <i class=\"pi {{ group.strategyIcon || 'pi-compass' }}\" aria-hidden=\"true\"></i>\r\n <span class=\"fly-strategy-selector__group-title\">{{ group.strategyTitle }}</span>\r\n </div>\r\n @for (item of group.items; track item.id) {\r\n <div\r\n class=\"fly-strategy-selector__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"optionId(navIndexOf(item.id))\"\r\n [attr.aria-selected]=\"false\"\r\n [class.fly-strategy-selector__option--active]=\"navIndexOf(item.id) === activeIndex()\"\r\n (click)=\"pick(item)\"\r\n (keydown.enter)=\"pick(item)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(item.id))\"\r\n >\r\n <span class=\"fly-strategy-selector__option-title\">{{ item.title }}</span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (groups().length === 0) {\r\n <div class=\"fly-strategy-selector__status\" role=\"presentation\">\r\n {{ 'strategy_selector.no_results' | translate }}\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n}\r\n", styles: [":host{--_surface: var(--surface-card, #fff);--_surface-panel: var(--glass-bg-elevated, var(--surface-card, #fff));--_panel-blur: var(--glass-blur, 40px);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_fill: var(--fill-tertiary, #f3f4f6);--_surface-hover: var(--surface-hover, #f1f5f9);--_accent: var(--accent);--_primary: var(--primary-color, var(--_accent));--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}:host,:host *,:host *:before,:host *:after{box-sizing:border-box}.fly-strategy-selector__chip{display:flex;align-items:center;gap:8px;padding-block:5px;padding-inline:8px;border:1px solid var(--_border);border-radius:10px;background:var(--_fill);max-inline-size:100%}.fly-strategy-selector__chip-icon{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:22px;block-size:22px;border-radius:50%;background:color-mix(in srgb,var(--_accent, var(--_text-subtle)) 14%,transparent);color:var(--_accent, var(--_text-subtle));font-size:12px;line-height:1}.fly-strategy-selector__chip-body{display:flex;flex-direction:column;min-inline-size:0;flex:1}.fly-strategy-selector__chip-title{font-size:12px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__chip-strategy{font-size:11px;color:var(--_text-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__chip-remove{border:none;background:transparent;padding:4px;border-radius:50%;color:var(--_text-subtle);font-size:10px;line-height:1;cursor:pointer;flex:none}.fly-strategy-selector__chip-remove:hover{background:color-mix(in srgb,var(--_danger) 18%,transparent);color:var(--_danger)}.fly-strategy-selector__wrap{position:relative;inline-size:100%}.fly-strategy-selector__search-input{inline-size:100%;min-block-size:2.25rem;padding-block:5px;padding-inline:10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-strategy-selector__search-input:focus-visible{outline:2px solid var(--_primary);outline-offset:-1px}.fly-strategy-selector__panel{position:absolute;z-index:60;inset-inline:0;inset-block-start:calc(100% + 4px);display:flex;flex-direction:column;max-block-size:19rem;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-panel);-webkit-backdrop-filter:blur(var(--_panel-blur));backdrop-filter:blur(var(--_panel-blur));box-shadow:0 12px 32px #0000002e;overflow:hidden}.fly-strategy-selector__listbox{flex:1 1 auto;overflow-y:auto;padding-block:4px}.fly-strategy-selector__group{display:flex;align-items:center;gap:6px;padding-block:6px 3px;padding-inline:10px;color:var(--_text-subtle);font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.fly-strategy-selector__group .pi{font-size:11px}.fly-strategy-selector__group-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__option{padding-block:6px;padding-inline:26px 10px;cursor:pointer}.fly-strategy-selector__option--active{background:var(--_surface-hover)}.fly-strategy-selector__option-title{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__status{display:flex;align-items:center;gap:8px;padding-block:10px;padding-inline:10px;color:var(--_text-subtle)}.fly-strategy-selector__status--error{color:var(--_danger)}.fly-strategy-selector__retry{border:1px solid var(--_border);border-radius:6px;background:var(--_surface);padding-block:2px;padding-inline:8px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}\n"] }]
19977
+ args: [{ selector: 'fly-strategy-selector', standalone: true, imports: [CommonModule, TranslatePipe, FlyClickOutsideDirective], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'fly-strategy-selector', '[class.fly-strategy-selector--open]': 'isOpen()' }, template: "@if (selected(); as pick) {\r\n <div class=\"fly-strategy-selector__chip\" role=\"group\" [attr.aria-label]=\"pick.title\">\r\n <span class=\"fly-strategy-selector__chip-icon\" aria-hidden=\"true\">\r\n @if (pick.strategyIcon) {\r\n <i class=\"pi {{ pick.strategyIcon }}\"></i>\r\n } @else {\r\n <i class=\"pi pi-compass\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-strategy-selector__chip-body\">\r\n <span class=\"fly-strategy-selector__chip-title\" [title]=\"pick.title\">{{ pick.title }}</span>\r\n <span class=\"fly-strategy-selector__chip-strategy\" [title]=\"pick.strategyTitle\">{{ pick.strategyTitle }}</span>\r\n </span>\r\n <button\r\n type=\"button\"\r\n class=\"fly-strategy-selector__chip-remove\"\r\n [attr.aria-label]=\"'strategy_selector.remove' | translate: { name: pick.title }\"\r\n (click)=\"remove()\">\r\n \u2715\r\n </button>\r\n </div>\r\n} @else {\r\n <div\r\n class=\"fly-strategy-selector__wrap\"\r\n [flyClickOutsideEnabled]=\"isOpen()\"\r\n (flyClickOutside)=\"close()\"\r\n >\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-strategy-selector__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-controls=\"fly-strategy-selector-listbox\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"placeholder() || ('strategy_selector.search_placeholder' | translate)\"\r\n [placeholder]=\"placeholder() || ('strategy_selector.search_placeholder' | translate)\"\r\n [value]=\"searchTerm()\"\r\n (focus)=\"open()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n (keydown)=\"onPanelKeydown($event)\"\r\n />\r\n\r\n @if (isOpen()) {\r\n <div class=\"fly-strategy-selector__panel\">\r\n <div\r\n class=\"fly-strategy-selector__listbox\"\r\n role=\"listbox\"\r\n id=\"fly-strategy-selector-listbox\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n >\r\n @if (loading()) {\r\n <div class=\"fly-strategy-selector__status\" role=\"status\">\r\n {{ 'strategy_selector.loading' | translate }}\r\n </div>\r\n } @else if (loadFailed()) {\r\n <div class=\"fly-strategy-selector__status fly-strategy-selector__status--error\" role=\"alert\">\r\n <span>{{ 'strategy_selector.error' | translate }}</span>\r\n <button type=\"button\" class=\"fly-strategy-selector__retry\" (click)=\"retry()\">\r\n {{ 'strategy_selector.retry' | translate }}\r\n </button>\r\n </div>\r\n } @else {\r\n @for (group of groups(); track group.strategyId) {\r\n <div class=\"fly-strategy-selector__group\" role=\"presentation\">\r\n <i class=\"pi {{ group.strategyIcon || 'pi-compass' }}\" aria-hidden=\"true\"></i>\r\n <span class=\"fly-strategy-selector__group-title\">{{ group.strategyTitle }}</span>\r\n </div>\r\n @for (item of group.items; track item.id) {\r\n <div\r\n class=\"fly-strategy-selector__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"optionId(navIndexOf(item.id))\"\r\n [attr.aria-selected]=\"false\"\r\n [class.fly-strategy-selector__option--active]=\"navIndexOf(item.id) === activeIndex()\"\r\n (click)=\"pick(item)\"\r\n (keydown.enter)=\"pick(item)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(item.id))\"\r\n >\r\n <span class=\"fly-strategy-selector__option-title\">{{ item.title }}</span>\r\n </div>\r\n }\r\n }\r\n\r\n @if (groups().length === 0) {\r\n <div class=\"fly-strategy-selector__status\" role=\"presentation\">\r\n {{ 'strategy_selector.no_results' | translate }}\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n}\r\n", styles: [":host{--_surface: var(--surface-card, #fff);--_surface-panel: var(--glass-bg-elevated, var(--surface-card, #fff));--_panel-blur: var(--glass-blur, 40px);--_border: var(--separator, var(--surface-border, #e2e8f0));--_text: var(--label-primary, var(--text-color, #0f172a));--_text-subtle: var(--label-secondary, var(--text-color-secondary, #64748b));--_fill: var(--fill-tertiary, #f3f4f6);--_surface-hover: var(--surface-hover, #f1f5f9);--_accent: var(--accent);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:block;inline-size:100%;color:var(--_text);font-size:13px}:host,:host *,:host *:before,:host *:after{box-sizing:border-box}.fly-strategy-selector__chip{display:flex;align-items:center;gap:8px;padding-block:5px;padding-inline:8px;border:1px solid var(--_border);border-radius:10px;background:var(--_fill);max-inline-size:100%}.fly-strategy-selector__chip-icon{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:22px;block-size:22px;border-radius:50%;background:color-mix(in srgb,var(--_accent, var(--_text-subtle)) 14%,transparent);color:var(--_accent, var(--_text-subtle));font-size:12px;line-height:1}.fly-strategy-selector__chip-body{display:flex;flex-direction:column;min-inline-size:0;flex:1}.fly-strategy-selector__chip-title{font-size:12px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__chip-strategy{font-size:11px;color:var(--_text-subtle);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__chip-remove{border:none;background:transparent;padding:4px;border-radius:50%;color:var(--_text-subtle);font-size:10px;line-height:1;cursor:pointer;flex:none}.fly-strategy-selector__chip-remove:hover{background:color-mix(in srgb,var(--_danger) 18%,transparent);color:var(--_danger)}.fly-strategy-selector__wrap{position:relative;inline-size:100%}.fly-strategy-selector__search-input{inline-size:100%;min-block-size:2.25rem;padding-block:5px;padding-inline:10px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit}.fly-strategy-selector__search-input:focus-visible{outline:2px solid;outline-color:var(--_accent);outline-offset:-1px}.fly-strategy-selector__panel{position:absolute;z-index:60;inset-inline:0;inset-block-start:calc(100% + 4px);display:flex;flex-direction:column;max-block-size:19rem;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-panel);-webkit-backdrop-filter:blur(var(--_panel-blur));backdrop-filter:blur(var(--_panel-blur));box-shadow:0 12px 32px #0000002e;overflow:hidden}.fly-strategy-selector__listbox{flex:1 1 auto;overflow-y:auto;padding-block:4px}.fly-strategy-selector__group{display:flex;align-items:center;gap:6px;padding-block:6px 3px;padding-inline:10px;color:var(--_text-subtle);font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.fly-strategy-selector__group .pi{font-size:11px}.fly-strategy-selector__group-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__option{padding-block:6px;padding-inline:26px 10px;cursor:pointer}.fly-strategy-selector__option--active{background:var(--_surface-hover)}.fly-strategy-selector__option-title{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-strategy-selector__status{display:flex;align-items:center;gap:8px;padding-block:10px;padding-inline:10px;color:var(--_text-subtle)}.fly-strategy-selector__status--error{color:var(--_danger)}.fly-strategy-selector__retry{border:1px solid var(--_border);border-radius:6px;background:var(--_surface);padding-block:2px;padding-inline:8px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}\n"] }]
19953
19978
  }], ctorParameters: () => [], propDecorators: { searchFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchFn", required: false }] }], initialSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialSelection", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], debounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceMs", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], searchEl: [{
19954
19979
  type: ViewChild,
19955
19980
  args: ['searchRef']
@@ -20710,7 +20735,7 @@ class FlyCurrencySelectorComponent {
20710
20735
  useExisting: forwardRef(() => FlyCurrencySelectorComponent),
20711
20736
  multi: true,
20712
20737
  },
20713
- ], viewQueries: [{ propertyName: "searchEl", first: true, predicate: ["searchRef"], descendants: true }, { propertyName: "triggerEl", first: true, predicate: ["triggerRef"], descendants: true }], ngImport: i0, template: "<div\r\n class=\"fly-currency-selector__wrap\"\r\n [flyClickOutsideEnabled]=\"isOpen()\"\r\n (flyClickOutside)=\"close()\"\r\n>\r\n @if (locked()) {\r\n <!-- \u2500\u2500 Locked readout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n NOT a dimmed `disabled` trigger: there is no dropdown affordance here at all \u2014 the\r\n value is frozen on purpose, not merely unavailable right now. `role=\"group\"` +\r\n `aria-label` name the field the way the combobox trigger's `aria-label` does; the\r\n reason is REAL, always-rendered text (not a `title` attribute, which many screen\r\n readers never announce and which no sighted user sees without hovering) and is\r\n additionally wired via `aria-describedby` for AT that reads by relationship rather\r\n than document order. -->\r\n <div\r\n class=\"fly-currency-selector__locked\"\r\n role=\"group\"\r\n [attr.aria-label]=\"ariaLabel() || placeholderText()\"\r\n [attr.aria-describedby]=\"lockedReasonId\"\r\n >\r\n @if (selected().length === 0) {\r\n <span class=\"fly-currency-selector__placeholder\">{{ placeholderText() }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__chips\">\r\n @for (c of selected(); track c.code) {\r\n <span class=\"fly-currency-selector__chip\">\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n <span class=\"fly-currency-selector__chip-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__chip-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n </span>\r\n }\r\n </span>\r\n }\r\n <span class=\"fly-currency-selector__lock-icon\" aria-hidden=\"true\">&#128274;</span>\r\n </div>\r\n <p class=\"fly-currency-selector__locked-reason\" [id]=\"lockedReasonId\">{{ lockedReasonText() }}</p>\r\n } @else {\r\n\r\n <!-- \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n `aria-label` is never null: a `combobox` does NOT take its accessible name from its\r\n contents the way a plain button does, so the chips/placeholder painted inside it name\r\n nothing. Absent a consumer label the localized placeholder supplies the control's\r\n purpose; its VALUE is still announced from the contents. -->\r\n <button\r\n #triggerRef\r\n type=\"button\"\r\n [id]=\"triggerId\"\r\n class=\"fly-currency-selector__trigger\"\r\n role=\"combobox\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-label]=\"ariaLabel() || placeholderText()\"\r\n [class.fly-currency-selector__trigger--empty]=\"!hasSelection()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleOpen()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n >\r\n @if (selected().length === 0) {\r\n <span class=\"fly-currency-selector__placeholder\">{{ placeholderText() }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__chips\">\r\n @for (c of selected(); track c.code) {\r\n <span class=\"fly-currency-selector__chip\">\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n <span class=\"fly-currency-selector__chip-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__chip-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n @if (isMulti() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-currency-selector__chip-remove\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"'\u2715 ' + c.code\"\r\n (click)=\"remove(c.code, $event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n </span>\r\n }\r\n </span>\r\n }\r\n\r\n @if (clearable() && hasSelection() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-currency-selector__clear\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"clearText()\"\r\n [title]=\"clearText()\"\r\n (click)=\"clear($event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n\r\n <span class=\"fly-currency-selector__chevron\" aria-hidden=\"true\">\u25BE</span>\r\n </button>\r\n\r\n <!-- \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n @if (isOpen()) {\r\n <div class=\"fly-currency-selector__panel\" tabindex=\"-1\" (keydown)=\"onPanelKeydown($event)\">\r\n <div class=\"fly-currency-selector__search\">\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-currency-selector__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"true\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"searchPlaceholderText()\"\r\n [placeholder]=\"searchPlaceholderText()\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n @if (loading()) {\r\n <div class=\"fly-currency-selector__status\" role=\"status\">{{ loadingText() }}</div>\r\n } @else if (loadFailed()) {\r\n <div class=\"fly-currency-selector__status fly-currency-selector__status--error\" role=\"alert\">\r\n <span>{{ errorText() }}</span>\r\n <button type=\"button\" class=\"fly-currency-selector__retry\" (click)=\"retry()\">\r\n {{ retryText() }}\r\n </button>\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"fly-currency-selector__listbox\"\r\n role=\"listbox\"\r\n [id]=\"listboxId\"\r\n [attr.aria-multiselectable]=\"isMulti() ? true : null\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n >\r\n @if (pinned().length > 0) {\r\n <div class=\"fly-currency-selector__group\" role=\"presentation\">{{ pinnedGroupText() }}</div>\r\n @for (c of pinned(); track c.code) {\r\n <ng-container *ngTemplateOutlet=\"row; context: { $implicit: c }\" />\r\n }\r\n @if (rest().length > 0) {\r\n <div class=\"fly-currency-selector__group\" role=\"presentation\">{{ allGroupText() }}</div>\r\n }\r\n }\r\n @for (c of rest(); track c.code) {\r\n <ng-container *ngTemplateOutlet=\"row; context: { $implicit: c }\" />\r\n }\r\n\r\n @if (!loading() && !loadFailed() && filtered().length === 0) {\r\n <div class=\"fly-currency-selector__status\" role=\"presentation\">{{ noResultsText() }}</div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 One option row, shared by the pinned and full groups \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<ng-template #row let-c>\r\n <div\r\n class=\"fly-currency-selector__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"optionId(navIndexOf(c.code))\"\r\n [attr.aria-selected]=\"isSelected(c.code)\"\r\n [class.fly-currency-selector__option--selected]=\"isSelected(c.code)\"\r\n [class.fly-currency-selector__option--active]=\"navIndexOf(c.code) === activeIndex()\"\r\n (click)=\"pick(c)\"\r\n (keydown.enter)=\"pick(c)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(c.code))\"\r\n >\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n\r\n <span class=\"fly-currency-selector__option-text\">\r\n <span class=\"fly-currency-selector__option-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__option-name\">{{ c.name }}</span>\r\n </span>\r\n\r\n <span class=\"fly-currency-selector__option-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n\r\n <span class=\"fly-currency-selector__check\" aria-hidden=\"true\">\r\n @if (isSelected(c.code)) { \u2713 }\r\n </span>\r\n </div>\r\n</ng-template>\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-panel: var(--glass-bg-elevated, var(--surface-card, #fff));--_panel-blur: var(--glass-blur, 40px);--_surface-hover: var(--surface-hover, #f1f5f9);--_surface-active: var(--surface-active, #eef2ff);--_border: var(--surface-border, #e2e8f0);--_text: var(--text-color, #0f172a);--_text-subtle: var(--text-color-secondary, #64748b);--_fill: var(--fill-tertiary, #f3f4f6);--_primary: var(--primary-color);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:inline-block;inline-size:100%;min-inline-size:11rem;font-size:13px;color:var(--_text)}.fly-currency-selector__wrap{position:relative;inline-size:100%}.fly-currency-selector__trigger{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:2.25rem;padding-block:4px;padding-inline:8px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;text-align:start;cursor:pointer}.fly-currency-selector__trigger:focus-visible{outline:2px solid var(--_primary);outline-offset:2px}.fly-currency-selector__trigger:disabled{opacity:.55;cursor:not-allowed}.fly-currency-selector__placeholder{flex:1 1 auto;padding-inline-start:4px;color:var(--_text-subtle);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-currency-selector__chips{display:flex;flex:1 1 auto;flex-wrap:wrap;gap:4px;min-inline-size:0}.fly-currency-selector__chip{display:inline-flex;align-items:center;gap:5px;padding-block:2px;padding-inline:3px 7px;border-radius:999px;background:var(--_fill);font-size:12px}.fly-currency-selector__chip-code{font-weight:700;letter-spacing:.02em}.fly-currency-selector__chip-symbol{color:var(--_text-subtle)}.fly-currency-selector__chip-remove{padding:1px 3px;border-radius:50%;color:var(--_text-subtle);font-size:10px;line-height:1;cursor:pointer}.fly-currency-selector__chip-remove:hover{background:color-mix(in srgb,var(--_danger) 18%,transparent);color:var(--_danger)}.fly-currency-selector__clear,.fly-currency-selector__chevron{flex:none;color:var(--_text-subtle);font-size:11px;line-height:1}.fly-currency-selector__clear{padding:3px;border-radius:50%;cursor:pointer}.fly-currency-selector__clear:hover{background:var(--_surface-hover);color:var(--_text)}.fly-currency-selector__tile{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:26px;block-size:19px;border-radius:4px;background:var(--_fill);overflow:hidden}.fly-currency-selector__tile-flag{font-size:15px;line-height:1}.fly-currency-selector__tile-code{font-size:9px;font-weight:800;letter-spacing:.04em;color:var(--_text-subtle);direction:ltr;unicode-bidi:isolate}.fly-currency-selector__locked{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:2.25rem;padding-block:4px;padding-inline:8px;border:1px dashed var(--_border);border-radius:var(--_radius);background:var(--_fill);color:var(--_text);cursor:default}.fly-currency-selector__lock-icon{flex:none;margin-inline-start:auto;font-size:12px;opacity:.7}.fly-currency-selector__locked-reason{margin:4px 0 0;color:var(--_text-subtle);font-size:11px;line-height:1.4}.fly-currency-selector__panel{position:absolute;z-index:60;inset-inline:0;inset-block-start:calc(100% + 4px);display:flex;flex-direction:column;max-block-size:19rem;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-panel);-webkit-backdrop-filter:blur(var(--_panel-blur));backdrop-filter:blur(var(--_panel-blur));box-shadow:0 12px 32px #0000002e;overflow:hidden}.fly-currency-selector__search{padding:6px;border-block-end:1px solid var(--_border)}.fly-currency-selector__search-input{inline-size:100%;padding-block:5px;padding-inline:8px;border:1px solid var(--_border);border-radius:6px;background:var(--_surface);color:var(--_text);font:inherit}.fly-currency-selector__search-input:focus-visible{outline:2px solid var(--_primary);outline-offset:-1px}.fly-currency-selector__listbox{flex:1 1 auto;overflow-y:auto;padding-block:4px}.fly-currency-selector__group{padding-block:6px 3px;padding-inline:10px;color:var(--_text-subtle);font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}.fly-currency-selector__option{display:flex;align-items:center;gap:9px;padding-block:5px;padding-inline:10px;cursor:pointer}.fly-currency-selector__option--active{background:var(--_surface-hover)}.fly-currency-selector__option--selected{background:var(--_surface-active)}.fly-currency-selector__option-text{display:flex;flex:1 1 auto;align-items:baseline;gap:8px;min-inline-size:0}.fly-currency-selector__option-code{flex:none;font-weight:700;letter-spacing:.02em;direction:ltr;unicode-bidi:isolate}.fly-currency-selector__option-name{flex:1 1 auto;min-inline-size:0;color:var(--_text-subtle);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-currency-selector__option-symbol{flex:none;min-inline-size:2.2em;color:var(--_text);text-align:end}.fly-currency-selector__check{flex:none;inline-size:1em;color:var(--_primary)}.fly-currency-selector__status{display:flex;align-items:center;gap:8px;padding-block:10px;padding-inline:10px;color:var(--_text-subtle)}.fly-currency-selector__status--error{color:var(--_danger)}.fly-currency-selector__retry{border:1px solid var(--_border);border-radius:6px;background:var(--_surface);padding-block:2px;padding-inline:8px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled", "flyClickOutsideIgnore"], outputs: ["flyClickOutside"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
20738
+ ], viewQueries: [{ propertyName: "searchEl", first: true, predicate: ["searchRef"], descendants: true }, { propertyName: "triggerEl", first: true, predicate: ["triggerRef"], descendants: true }], ngImport: i0, template: "<div\r\n class=\"fly-currency-selector__wrap\"\r\n [flyClickOutsideEnabled]=\"isOpen()\"\r\n (flyClickOutside)=\"close()\"\r\n>\r\n @if (locked()) {\r\n <!-- \u2500\u2500 Locked readout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n NOT a dimmed `disabled` trigger: there is no dropdown affordance here at all \u2014 the\r\n value is frozen on purpose, not merely unavailable right now. `role=\"group\"` +\r\n `aria-label` name the field the way the combobox trigger's `aria-label` does; the\r\n reason is REAL, always-rendered text (not a `title` attribute, which many screen\r\n readers never announce and which no sighted user sees without hovering) and is\r\n additionally wired via `aria-describedby` for AT that reads by relationship rather\r\n than document order. -->\r\n <div\r\n class=\"fly-currency-selector__locked\"\r\n role=\"group\"\r\n [attr.aria-label]=\"ariaLabel() || placeholderText()\"\r\n [attr.aria-describedby]=\"lockedReasonId\"\r\n >\r\n @if (selected().length === 0) {\r\n <span class=\"fly-currency-selector__placeholder\">{{ placeholderText() }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__chips\">\r\n @for (c of selected(); track c.code) {\r\n <span class=\"fly-currency-selector__chip\">\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n <span class=\"fly-currency-selector__chip-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__chip-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n </span>\r\n }\r\n </span>\r\n }\r\n <span class=\"fly-currency-selector__lock-icon\" aria-hidden=\"true\">&#128274;</span>\r\n </div>\r\n <p class=\"fly-currency-selector__locked-reason\" [id]=\"lockedReasonId\">{{ lockedReasonText() }}</p>\r\n } @else {\r\n\r\n <!-- \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n `aria-label` is never null: a `combobox` does NOT take its accessible name from its\r\n contents the way a plain button does, so the chips/placeholder painted inside it name\r\n nothing. Absent a consumer label the localized placeholder supplies the control's\r\n purpose; its VALUE is still announced from the contents. -->\r\n <button\r\n #triggerRef\r\n type=\"button\"\r\n [id]=\"triggerId\"\r\n class=\"fly-currency-selector__trigger\"\r\n role=\"combobox\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-label]=\"ariaLabel() || placeholderText()\"\r\n [class.fly-currency-selector__trigger--empty]=\"!hasSelection()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleOpen()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n >\r\n @if (selected().length === 0) {\r\n <span class=\"fly-currency-selector__placeholder\">{{ placeholderText() }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__chips\">\r\n @for (c of selected(); track c.code) {\r\n <span class=\"fly-currency-selector__chip\">\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n <span class=\"fly-currency-selector__chip-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__chip-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n @if (isMulti() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-currency-selector__chip-remove\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"'\u2715 ' + c.code\"\r\n (click)=\"remove(c.code, $event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n </span>\r\n }\r\n </span>\r\n }\r\n\r\n @if (clearable() && hasSelection() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-currency-selector__clear\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"clearText()\"\r\n [title]=\"clearText()\"\r\n (click)=\"clear($event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n\r\n <span class=\"fly-currency-selector__chevron\" aria-hidden=\"true\">\u25BE</span>\r\n </button>\r\n\r\n <!-- \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n @if (isOpen()) {\r\n <div class=\"fly-currency-selector__panel\" tabindex=\"-1\" (keydown)=\"onPanelKeydown($event)\">\r\n <div class=\"fly-currency-selector__search\">\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-currency-selector__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"true\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"searchPlaceholderText()\"\r\n [placeholder]=\"searchPlaceholderText()\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n @if (loading()) {\r\n <div class=\"fly-currency-selector__status\" role=\"status\">{{ loadingText() }}</div>\r\n } @else if (loadFailed()) {\r\n <div class=\"fly-currency-selector__status fly-currency-selector__status--error\" role=\"alert\">\r\n <span>{{ errorText() }}</span>\r\n <button type=\"button\" class=\"fly-currency-selector__retry\" (click)=\"retry()\">\r\n {{ retryText() }}\r\n </button>\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"fly-currency-selector__listbox\"\r\n role=\"listbox\"\r\n [id]=\"listboxId\"\r\n [attr.aria-multiselectable]=\"isMulti() ? true : null\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n >\r\n @if (pinned().length > 0) {\r\n <div class=\"fly-currency-selector__group\" role=\"presentation\">{{ pinnedGroupText() }}</div>\r\n @for (c of pinned(); track c.code) {\r\n <ng-container *ngTemplateOutlet=\"row; context: { $implicit: c }\" />\r\n }\r\n @if (rest().length > 0) {\r\n <div class=\"fly-currency-selector__group\" role=\"presentation\">{{ allGroupText() }}</div>\r\n }\r\n }\r\n @for (c of rest(); track c.code) {\r\n <ng-container *ngTemplateOutlet=\"row; context: { $implicit: c }\" />\r\n }\r\n\r\n @if (!loading() && !loadFailed() && filtered().length === 0) {\r\n <div class=\"fly-currency-selector__status\" role=\"presentation\">{{ noResultsText() }}</div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 One option row, shared by the pinned and full groups \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<ng-template #row let-c>\r\n <div\r\n class=\"fly-currency-selector__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"optionId(navIndexOf(c.code))\"\r\n [attr.aria-selected]=\"isSelected(c.code)\"\r\n [class.fly-currency-selector__option--selected]=\"isSelected(c.code)\"\r\n [class.fly-currency-selector__option--active]=\"navIndexOf(c.code) === activeIndex()\"\r\n (click)=\"pick(c)\"\r\n (keydown.enter)=\"pick(c)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(c.code))\"\r\n >\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n\r\n <span class=\"fly-currency-selector__option-text\">\r\n <span class=\"fly-currency-selector__option-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__option-name\">{{ c.name }}</span>\r\n </span>\r\n\r\n <span class=\"fly-currency-selector__option-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n\r\n <span class=\"fly-currency-selector__check\" aria-hidden=\"true\">\r\n @if (isSelected(c.code)) { \u2713 }\r\n </span>\r\n </div>\r\n</ng-template>\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-panel: var(--glass-bg-elevated, var(--surface-card, #fff));--_panel-blur: var(--glass-blur, 40px);--_surface-hover: var(--surface-hover, #f1f5f9);--_surface-active: var(--surface-active, #eef2ff);--_border: var(--surface-border, #e2e8f0);--_text: var(--text-color, #0f172a);--_text-subtle: var(--text-color-secondary, #64748b);--_fill: var(--fill-tertiary, #f3f4f6);--_primary: var(--primary-color);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:inline-block;inline-size:100%;min-inline-size:11rem;font-size:13px;color:var(--_text)}.fly-currency-selector__wrap{position:relative;inline-size:100%}.fly-currency-selector__trigger{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:2.25rem;padding-block:4px;padding-inline:8px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;text-align:start;cursor:pointer}.fly-currency-selector__trigger:focus-visible{outline:2px solid;outline-color:var(--_primary);outline-offset:2px}.fly-currency-selector__trigger:disabled{opacity:.55;cursor:not-allowed}.fly-currency-selector__placeholder{flex:1 1 auto;padding-inline-start:4px;color:var(--_text-subtle);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-currency-selector__chips{display:flex;flex:1 1 auto;flex-wrap:wrap;gap:4px;min-inline-size:0}.fly-currency-selector__chip{display:inline-flex;align-items:center;gap:5px;padding-block:2px;padding-inline:3px 7px;border-radius:999px;background:var(--_fill);font-size:12px}.fly-currency-selector__chip-code{font-weight:700;letter-spacing:.02em}.fly-currency-selector__chip-symbol{color:var(--_text-subtle)}.fly-currency-selector__chip-remove{padding:1px 3px;border-radius:50%;color:var(--_text-subtle);font-size:10px;line-height:1;cursor:pointer}.fly-currency-selector__chip-remove:hover{background:color-mix(in srgb,var(--_danger) 18%,transparent);color:var(--_danger)}.fly-currency-selector__clear,.fly-currency-selector__chevron{flex:none;color:var(--_text-subtle);font-size:11px;line-height:1}.fly-currency-selector__clear{padding:3px;border-radius:50%;cursor:pointer}.fly-currency-selector__clear:hover{background:var(--_surface-hover);color:var(--_text)}.fly-currency-selector__tile{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:26px;block-size:19px;border-radius:4px;background:var(--_fill);overflow:hidden}.fly-currency-selector__tile-flag{font-size:15px;line-height:1}.fly-currency-selector__tile-code{font-size:9px;font-weight:800;letter-spacing:.04em;color:var(--_text-subtle);direction:ltr;unicode-bidi:isolate}.fly-currency-selector__locked{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:2.25rem;padding-block:4px;padding-inline:8px;border:1px dashed var(--_border);border-radius:var(--_radius);background:var(--_fill);color:var(--_text);cursor:default}.fly-currency-selector__lock-icon{flex:none;margin-inline-start:auto;font-size:12px;opacity:.7}.fly-currency-selector__locked-reason{margin:4px 0 0;color:var(--_text-subtle);font-size:11px;line-height:1.4}.fly-currency-selector__panel{position:absolute;z-index:60;inset-inline:0;inset-block-start:calc(100% + 4px);display:flex;flex-direction:column;max-block-size:19rem;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-panel);-webkit-backdrop-filter:blur(var(--_panel-blur));backdrop-filter:blur(var(--_panel-blur));box-shadow:0 12px 32px #0000002e;overflow:hidden}.fly-currency-selector__search{padding:6px;border-block-end:1px solid var(--_border)}.fly-currency-selector__search-input{inline-size:100%;padding-block:5px;padding-inline:8px;border:1px solid var(--_border);border-radius:6px;background:var(--_surface);color:var(--_text);font:inherit}.fly-currency-selector__search-input:focus-visible{outline:2px solid;outline-color:var(--_primary);outline-offset:-1px}.fly-currency-selector__listbox{flex:1 1 auto;overflow-y:auto;padding-block:4px}.fly-currency-selector__group{padding-block:6px 3px;padding-inline:10px;color:var(--_text-subtle);font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}.fly-currency-selector__option{display:flex;align-items:center;gap:9px;padding-block:5px;padding-inline:10px;cursor:pointer}.fly-currency-selector__option--active{background:var(--_surface-hover)}.fly-currency-selector__option--selected{background:var(--_surface-active)}.fly-currency-selector__option-text{display:flex;flex:1 1 auto;align-items:baseline;gap:8px;min-inline-size:0}.fly-currency-selector__option-code{flex:none;font-weight:700;letter-spacing:.02em;direction:ltr;unicode-bidi:isolate}.fly-currency-selector__option-name{flex:1 1 auto;min-inline-size:0;color:var(--_text-subtle);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-currency-selector__option-symbol{flex:none;min-inline-size:2.2em;color:var(--_text);text-align:end}.fly-currency-selector__check{flex:none;inline-size:1em;color:var(--_primary)}.fly-currency-selector__status{display:flex;align-items:center;gap:8px;padding-block:10px;padding-inline:10px;color:var(--_text-subtle)}.fly-currency-selector__status--error{color:var(--_danger)}.fly-currency-selector__retry{border:1px solid var(--_border);border-radius:6px;background:var(--_surface);padding-block:2px;padding-inline:8px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled", "flyClickOutsideIgnore"], outputs: ["flyClickOutside"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
20714
20739
  }
20715
20740
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyCurrencySelectorComponent, decorators: [{
20716
20741
  type: Component,
@@ -20725,7 +20750,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
20725
20750
  '[class.fly-currency-selector--open]': 'isOpen()',
20726
20751
  '[class.fly-currency-selector--disabled]': 'effectiveDisabled()',
20727
20752
  '[class.fly-currency-selector--locked]': 'locked()',
20728
- }, template: "<div\r\n class=\"fly-currency-selector__wrap\"\r\n [flyClickOutsideEnabled]=\"isOpen()\"\r\n (flyClickOutside)=\"close()\"\r\n>\r\n @if (locked()) {\r\n <!-- \u2500\u2500 Locked readout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n NOT a dimmed `disabled` trigger: there is no dropdown affordance here at all \u2014 the\r\n value is frozen on purpose, not merely unavailable right now. `role=\"group\"` +\r\n `aria-label` name the field the way the combobox trigger's `aria-label` does; the\r\n reason is REAL, always-rendered text (not a `title` attribute, which many screen\r\n readers never announce and which no sighted user sees without hovering) and is\r\n additionally wired via `aria-describedby` for AT that reads by relationship rather\r\n than document order. -->\r\n <div\r\n class=\"fly-currency-selector__locked\"\r\n role=\"group\"\r\n [attr.aria-label]=\"ariaLabel() || placeholderText()\"\r\n [attr.aria-describedby]=\"lockedReasonId\"\r\n >\r\n @if (selected().length === 0) {\r\n <span class=\"fly-currency-selector__placeholder\">{{ placeholderText() }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__chips\">\r\n @for (c of selected(); track c.code) {\r\n <span class=\"fly-currency-selector__chip\">\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n <span class=\"fly-currency-selector__chip-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__chip-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n </span>\r\n }\r\n </span>\r\n }\r\n <span class=\"fly-currency-selector__lock-icon\" aria-hidden=\"true\">&#128274;</span>\r\n </div>\r\n <p class=\"fly-currency-selector__locked-reason\" [id]=\"lockedReasonId\">{{ lockedReasonText() }}</p>\r\n } @else {\r\n\r\n <!-- \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n `aria-label` is never null: a `combobox` does NOT take its accessible name from its\r\n contents the way a plain button does, so the chips/placeholder painted inside it name\r\n nothing. Absent a consumer label the localized placeholder supplies the control's\r\n purpose; its VALUE is still announced from the contents. -->\r\n <button\r\n #triggerRef\r\n type=\"button\"\r\n [id]=\"triggerId\"\r\n class=\"fly-currency-selector__trigger\"\r\n role=\"combobox\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-label]=\"ariaLabel() || placeholderText()\"\r\n [class.fly-currency-selector__trigger--empty]=\"!hasSelection()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleOpen()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n >\r\n @if (selected().length === 0) {\r\n <span class=\"fly-currency-selector__placeholder\">{{ placeholderText() }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__chips\">\r\n @for (c of selected(); track c.code) {\r\n <span class=\"fly-currency-selector__chip\">\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n <span class=\"fly-currency-selector__chip-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__chip-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n @if (isMulti() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-currency-selector__chip-remove\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"'\u2715 ' + c.code\"\r\n (click)=\"remove(c.code, $event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n </span>\r\n }\r\n </span>\r\n }\r\n\r\n @if (clearable() && hasSelection() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-currency-selector__clear\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"clearText()\"\r\n [title]=\"clearText()\"\r\n (click)=\"clear($event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n\r\n <span class=\"fly-currency-selector__chevron\" aria-hidden=\"true\">\u25BE</span>\r\n </button>\r\n\r\n <!-- \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n @if (isOpen()) {\r\n <div class=\"fly-currency-selector__panel\" tabindex=\"-1\" (keydown)=\"onPanelKeydown($event)\">\r\n <div class=\"fly-currency-selector__search\">\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-currency-selector__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"true\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"searchPlaceholderText()\"\r\n [placeholder]=\"searchPlaceholderText()\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n @if (loading()) {\r\n <div class=\"fly-currency-selector__status\" role=\"status\">{{ loadingText() }}</div>\r\n } @else if (loadFailed()) {\r\n <div class=\"fly-currency-selector__status fly-currency-selector__status--error\" role=\"alert\">\r\n <span>{{ errorText() }}</span>\r\n <button type=\"button\" class=\"fly-currency-selector__retry\" (click)=\"retry()\">\r\n {{ retryText() }}\r\n </button>\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"fly-currency-selector__listbox\"\r\n role=\"listbox\"\r\n [id]=\"listboxId\"\r\n [attr.aria-multiselectable]=\"isMulti() ? true : null\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n >\r\n @if (pinned().length > 0) {\r\n <div class=\"fly-currency-selector__group\" role=\"presentation\">{{ pinnedGroupText() }}</div>\r\n @for (c of pinned(); track c.code) {\r\n <ng-container *ngTemplateOutlet=\"row; context: { $implicit: c }\" />\r\n }\r\n @if (rest().length > 0) {\r\n <div class=\"fly-currency-selector__group\" role=\"presentation\">{{ allGroupText() }}</div>\r\n }\r\n }\r\n @for (c of rest(); track c.code) {\r\n <ng-container *ngTemplateOutlet=\"row; context: { $implicit: c }\" />\r\n }\r\n\r\n @if (!loading() && !loadFailed() && filtered().length === 0) {\r\n <div class=\"fly-currency-selector__status\" role=\"presentation\">{{ noResultsText() }}</div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 One option row, shared by the pinned and full groups \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<ng-template #row let-c>\r\n <div\r\n class=\"fly-currency-selector__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"optionId(navIndexOf(c.code))\"\r\n [attr.aria-selected]=\"isSelected(c.code)\"\r\n [class.fly-currency-selector__option--selected]=\"isSelected(c.code)\"\r\n [class.fly-currency-selector__option--active]=\"navIndexOf(c.code) === activeIndex()\"\r\n (click)=\"pick(c)\"\r\n (keydown.enter)=\"pick(c)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(c.code))\"\r\n >\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n\r\n <span class=\"fly-currency-selector__option-text\">\r\n <span class=\"fly-currency-selector__option-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__option-name\">{{ c.name }}</span>\r\n </span>\r\n\r\n <span class=\"fly-currency-selector__option-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n\r\n <span class=\"fly-currency-selector__check\" aria-hidden=\"true\">\r\n @if (isSelected(c.code)) { \u2713 }\r\n </span>\r\n </div>\r\n</ng-template>\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-panel: var(--glass-bg-elevated, var(--surface-card, #fff));--_panel-blur: var(--glass-blur, 40px);--_surface-hover: var(--surface-hover, #f1f5f9);--_surface-active: var(--surface-active, #eef2ff);--_border: var(--surface-border, #e2e8f0);--_text: var(--text-color, #0f172a);--_text-subtle: var(--text-color-secondary, #64748b);--_fill: var(--fill-tertiary, #f3f4f6);--_primary: var(--primary-color);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:inline-block;inline-size:100%;min-inline-size:11rem;font-size:13px;color:var(--_text)}.fly-currency-selector__wrap{position:relative;inline-size:100%}.fly-currency-selector__trigger{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:2.25rem;padding-block:4px;padding-inline:8px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;text-align:start;cursor:pointer}.fly-currency-selector__trigger:focus-visible{outline:2px solid var(--_primary);outline-offset:2px}.fly-currency-selector__trigger:disabled{opacity:.55;cursor:not-allowed}.fly-currency-selector__placeholder{flex:1 1 auto;padding-inline-start:4px;color:var(--_text-subtle);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-currency-selector__chips{display:flex;flex:1 1 auto;flex-wrap:wrap;gap:4px;min-inline-size:0}.fly-currency-selector__chip{display:inline-flex;align-items:center;gap:5px;padding-block:2px;padding-inline:3px 7px;border-radius:999px;background:var(--_fill);font-size:12px}.fly-currency-selector__chip-code{font-weight:700;letter-spacing:.02em}.fly-currency-selector__chip-symbol{color:var(--_text-subtle)}.fly-currency-selector__chip-remove{padding:1px 3px;border-radius:50%;color:var(--_text-subtle);font-size:10px;line-height:1;cursor:pointer}.fly-currency-selector__chip-remove:hover{background:color-mix(in srgb,var(--_danger) 18%,transparent);color:var(--_danger)}.fly-currency-selector__clear,.fly-currency-selector__chevron{flex:none;color:var(--_text-subtle);font-size:11px;line-height:1}.fly-currency-selector__clear{padding:3px;border-radius:50%;cursor:pointer}.fly-currency-selector__clear:hover{background:var(--_surface-hover);color:var(--_text)}.fly-currency-selector__tile{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:26px;block-size:19px;border-radius:4px;background:var(--_fill);overflow:hidden}.fly-currency-selector__tile-flag{font-size:15px;line-height:1}.fly-currency-selector__tile-code{font-size:9px;font-weight:800;letter-spacing:.04em;color:var(--_text-subtle);direction:ltr;unicode-bidi:isolate}.fly-currency-selector__locked{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:2.25rem;padding-block:4px;padding-inline:8px;border:1px dashed var(--_border);border-radius:var(--_radius);background:var(--_fill);color:var(--_text);cursor:default}.fly-currency-selector__lock-icon{flex:none;margin-inline-start:auto;font-size:12px;opacity:.7}.fly-currency-selector__locked-reason{margin:4px 0 0;color:var(--_text-subtle);font-size:11px;line-height:1.4}.fly-currency-selector__panel{position:absolute;z-index:60;inset-inline:0;inset-block-start:calc(100% + 4px);display:flex;flex-direction:column;max-block-size:19rem;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-panel);-webkit-backdrop-filter:blur(var(--_panel-blur));backdrop-filter:blur(var(--_panel-blur));box-shadow:0 12px 32px #0000002e;overflow:hidden}.fly-currency-selector__search{padding:6px;border-block-end:1px solid var(--_border)}.fly-currency-selector__search-input{inline-size:100%;padding-block:5px;padding-inline:8px;border:1px solid var(--_border);border-radius:6px;background:var(--_surface);color:var(--_text);font:inherit}.fly-currency-selector__search-input:focus-visible{outline:2px solid var(--_primary);outline-offset:-1px}.fly-currency-selector__listbox{flex:1 1 auto;overflow-y:auto;padding-block:4px}.fly-currency-selector__group{padding-block:6px 3px;padding-inline:10px;color:var(--_text-subtle);font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}.fly-currency-selector__option{display:flex;align-items:center;gap:9px;padding-block:5px;padding-inline:10px;cursor:pointer}.fly-currency-selector__option--active{background:var(--_surface-hover)}.fly-currency-selector__option--selected{background:var(--_surface-active)}.fly-currency-selector__option-text{display:flex;flex:1 1 auto;align-items:baseline;gap:8px;min-inline-size:0}.fly-currency-selector__option-code{flex:none;font-weight:700;letter-spacing:.02em;direction:ltr;unicode-bidi:isolate}.fly-currency-selector__option-name{flex:1 1 auto;min-inline-size:0;color:var(--_text-subtle);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-currency-selector__option-symbol{flex:none;min-inline-size:2.2em;color:var(--_text);text-align:end}.fly-currency-selector__check{flex:none;inline-size:1em;color:var(--_primary)}.fly-currency-selector__status{display:flex;align-items:center;gap:8px;padding-block:10px;padding-inline:10px;color:var(--_text-subtle)}.fly-currency-selector__status--error{color:var(--_danger)}.fly-currency-selector__retry{border:1px solid var(--_border);border-radius:6px;background:var(--_surface);padding-block:2px;padding-inline:8px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}\n"] }]
20753
+ }, template: "<div\r\n class=\"fly-currency-selector__wrap\"\r\n [flyClickOutsideEnabled]=\"isOpen()\"\r\n (flyClickOutside)=\"close()\"\r\n>\r\n @if (locked()) {\r\n <!-- \u2500\u2500 Locked readout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n NOT a dimmed `disabled` trigger: there is no dropdown affordance here at all \u2014 the\r\n value is frozen on purpose, not merely unavailable right now. `role=\"group\"` +\r\n `aria-label` name the field the way the combobox trigger's `aria-label` does; the\r\n reason is REAL, always-rendered text (not a `title` attribute, which many screen\r\n readers never announce and which no sighted user sees without hovering) and is\r\n additionally wired via `aria-describedby` for AT that reads by relationship rather\r\n than document order. -->\r\n <div\r\n class=\"fly-currency-selector__locked\"\r\n role=\"group\"\r\n [attr.aria-label]=\"ariaLabel() || placeholderText()\"\r\n [attr.aria-describedby]=\"lockedReasonId\"\r\n >\r\n @if (selected().length === 0) {\r\n <span class=\"fly-currency-selector__placeholder\">{{ placeholderText() }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__chips\">\r\n @for (c of selected(); track c.code) {\r\n <span class=\"fly-currency-selector__chip\">\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n <span class=\"fly-currency-selector__chip-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__chip-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n </span>\r\n }\r\n </span>\r\n }\r\n <span class=\"fly-currency-selector__lock-icon\" aria-hidden=\"true\">&#128274;</span>\r\n </div>\r\n <p class=\"fly-currency-selector__locked-reason\" [id]=\"lockedReasonId\">{{ lockedReasonText() }}</p>\r\n } @else {\r\n\r\n <!-- \u2500\u2500 Trigger \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n `aria-label` is never null: a `combobox` does NOT take its accessible name from its\r\n contents the way a plain button does, so the chips/placeholder painted inside it name\r\n nothing. Absent a consumer label the localized placeholder supplies the control's\r\n purpose; its VALUE is still announced from the contents. -->\r\n <button\r\n #triggerRef\r\n type=\"button\"\r\n [id]=\"triggerId\"\r\n class=\"fly-currency-selector__trigger\"\r\n role=\"combobox\"\r\n aria-haspopup=\"listbox\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-label]=\"ariaLabel() || placeholderText()\"\r\n [class.fly-currency-selector__trigger--empty]=\"!hasSelection()\"\r\n [disabled]=\"effectiveDisabled()\"\r\n (click)=\"toggleOpen()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n >\r\n @if (selected().length === 0) {\r\n <span class=\"fly-currency-selector__placeholder\">{{ placeholderText() }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__chips\">\r\n @for (c of selected(); track c.code) {\r\n <span class=\"fly-currency-selector__chip\">\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n <span class=\"fly-currency-selector__chip-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__chip-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n @if (isMulti() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-currency-selector__chip-remove\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"'\u2715 ' + c.code\"\r\n (click)=\"remove(c.code, $event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n </span>\r\n }\r\n </span>\r\n }\r\n\r\n @if (clearable() && hasSelection() && !effectiveDisabled()) {\r\n <span\r\n class=\"fly-currency-selector__clear\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n [attr.aria-label]=\"clearText()\"\r\n [title]=\"clearText()\"\r\n (click)=\"clear($event)\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n >\u2715</span>\r\n }\r\n\r\n <span class=\"fly-currency-selector__chevron\" aria-hidden=\"true\">\u25BE</span>\r\n </button>\r\n\r\n <!-- \u2500\u2500 Panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n @if (isOpen()) {\r\n <div class=\"fly-currency-selector__panel\" tabindex=\"-1\" (keydown)=\"onPanelKeydown($event)\">\r\n <div class=\"fly-currency-selector__search\">\r\n <input\r\n #searchRef\r\n type=\"text\"\r\n class=\"fly-currency-selector__search-input\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n [attr.aria-expanded]=\"true\"\r\n [attr.aria-controls]=\"listboxId\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"searchPlaceholderText()\"\r\n [placeholder]=\"searchPlaceholderText()\"\r\n [value]=\"searchTerm()\"\r\n (input)=\"onSearchInput($any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n @if (loading()) {\r\n <div class=\"fly-currency-selector__status\" role=\"status\">{{ loadingText() }}</div>\r\n } @else if (loadFailed()) {\r\n <div class=\"fly-currency-selector__status fly-currency-selector__status--error\" role=\"alert\">\r\n <span>{{ errorText() }}</span>\r\n <button type=\"button\" class=\"fly-currency-selector__retry\" (click)=\"retry()\">\r\n {{ retryText() }}\r\n </button>\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"fly-currency-selector__listbox\"\r\n role=\"listbox\"\r\n [id]=\"listboxId\"\r\n [attr.aria-multiselectable]=\"isMulti() ? true : null\"\r\n [attr.aria-activedescendant]=\"activeDescendant() || null\"\r\n [attr.aria-label]=\"ariaLabel() || null\"\r\n >\r\n @if (pinned().length > 0) {\r\n <div class=\"fly-currency-selector__group\" role=\"presentation\">{{ pinnedGroupText() }}</div>\r\n @for (c of pinned(); track c.code) {\r\n <ng-container *ngTemplateOutlet=\"row; context: { $implicit: c }\" />\r\n }\r\n @if (rest().length > 0) {\r\n <div class=\"fly-currency-selector__group\" role=\"presentation\">{{ allGroupText() }}</div>\r\n }\r\n }\r\n @for (c of rest(); track c.code) {\r\n <ng-container *ngTemplateOutlet=\"row; context: { $implicit: c }\" />\r\n }\r\n\r\n @if (!loading() && !loadFailed() && filtered().length === 0) {\r\n <div class=\"fly-currency-selector__status\" role=\"presentation\">{{ noResultsText() }}</div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n }\r\n</div>\r\n\r\n<!-- \u2500\u2500 One option row, shared by the pinned and full groups \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<ng-template #row let-c>\r\n <div\r\n class=\"fly-currency-selector__option\"\r\n role=\"option\"\r\n tabindex=\"-1\"\r\n [id]=\"optionId(navIndexOf(c.code))\"\r\n [attr.aria-selected]=\"isSelected(c.code)\"\r\n [class.fly-currency-selector__option--selected]=\"isSelected(c.code)\"\r\n [class.fly-currency-selector__option--active]=\"navIndexOf(c.code) === activeIndex()\"\r\n (click)=\"pick(c)\"\r\n (keydown.enter)=\"pick(c)\"\r\n (mouseenter)=\"onOptionHover(navIndexOf(c.code))\"\r\n >\r\n <span class=\"fly-currency-selector__tile\" aria-hidden=\"true\">\r\n @if (flagsRenderable() && c.flag) {\r\n <span class=\"fly-currency-selector__tile-flag\">{{ c.flag }}</span>\r\n } @else {\r\n <span class=\"fly-currency-selector__tile-code\">{{ tileCode(c) }}</span>\r\n }\r\n </span>\r\n\r\n <span class=\"fly-currency-selector__option-text\">\r\n <span class=\"fly-currency-selector__option-code\">{{ c.code }}</span>\r\n <span class=\"fly-currency-selector__option-name\">{{ c.name }}</span>\r\n </span>\r\n\r\n <span class=\"fly-currency-selector__option-symbol\" aria-hidden=\"true\">{{ c.symbol }}</span>\r\n\r\n <span class=\"fly-currency-selector__check\" aria-hidden=\"true\">\r\n @if (isSelected(c.code)) { \u2713 }\r\n </span>\r\n </div>\r\n</ng-template>\r\n", styles: [":host,:host *,:host *:before,:host *:after{box-sizing:border-box}:host{--_surface: var(--surface-card, #fff);--_surface-panel: var(--glass-bg-elevated, var(--surface-card, #fff));--_panel-blur: var(--glass-blur, 40px);--_surface-hover: var(--surface-hover, #f1f5f9);--_surface-active: var(--surface-active, #eef2ff);--_border: var(--surface-border, #e2e8f0);--_text: var(--text-color, #0f172a);--_text-subtle: var(--text-color-secondary, #64748b);--_fill: var(--fill-tertiary, #f3f4f6);--_primary: var(--primary-color);--_danger: var(--system-red, #ef4444);--_radius: 8px;display:inline-block;inline-size:100%;min-inline-size:11rem;font-size:13px;color:var(--_text)}.fly-currency-selector__wrap{position:relative;inline-size:100%}.fly-currency-selector__trigger{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:2.25rem;padding-block:4px;padding-inline:8px;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface);color:var(--_text);font:inherit;text-align:start;cursor:pointer}.fly-currency-selector__trigger:focus-visible{outline:2px solid;outline-color:var(--_primary);outline-offset:2px}.fly-currency-selector__trigger:disabled{opacity:.55;cursor:not-allowed}.fly-currency-selector__placeholder{flex:1 1 auto;padding-inline-start:4px;color:var(--_text-subtle);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-currency-selector__chips{display:flex;flex:1 1 auto;flex-wrap:wrap;gap:4px;min-inline-size:0}.fly-currency-selector__chip{display:inline-flex;align-items:center;gap:5px;padding-block:2px;padding-inline:3px 7px;border-radius:999px;background:var(--_fill);font-size:12px}.fly-currency-selector__chip-code{font-weight:700;letter-spacing:.02em}.fly-currency-selector__chip-symbol{color:var(--_text-subtle)}.fly-currency-selector__chip-remove{padding:1px 3px;border-radius:50%;color:var(--_text-subtle);font-size:10px;line-height:1;cursor:pointer}.fly-currency-selector__chip-remove:hover{background:color-mix(in srgb,var(--_danger) 18%,transparent);color:var(--_danger)}.fly-currency-selector__clear,.fly-currency-selector__chevron{flex:none;color:var(--_text-subtle);font-size:11px;line-height:1}.fly-currency-selector__clear{padding:3px;border-radius:50%;cursor:pointer}.fly-currency-selector__clear:hover{background:var(--_surface-hover);color:var(--_text)}.fly-currency-selector__tile{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:26px;block-size:19px;border-radius:4px;background:var(--_fill);overflow:hidden}.fly-currency-selector__tile-flag{font-size:15px;line-height:1}.fly-currency-selector__tile-code{font-size:9px;font-weight:800;letter-spacing:.04em;color:var(--_text-subtle);direction:ltr;unicode-bidi:isolate}.fly-currency-selector__locked{display:flex;align-items:center;gap:8px;inline-size:100%;min-block-size:2.25rem;padding-block:4px;padding-inline:8px;border:1px dashed var(--_border);border-radius:var(--_radius);background:var(--_fill);color:var(--_text);cursor:default}.fly-currency-selector__lock-icon{flex:none;margin-inline-start:auto;font-size:12px;opacity:.7}.fly-currency-selector__locked-reason{margin:4px 0 0;color:var(--_text-subtle);font-size:11px;line-height:1.4}.fly-currency-selector__panel{position:absolute;z-index:60;inset-inline:0;inset-block-start:calc(100% + 4px);display:flex;flex-direction:column;max-block-size:19rem;border:1px solid var(--_border);border-radius:var(--_radius);background:var(--_surface-panel);-webkit-backdrop-filter:blur(var(--_panel-blur));backdrop-filter:blur(var(--_panel-blur));box-shadow:0 12px 32px #0000002e;overflow:hidden}.fly-currency-selector__search{padding:6px;border-block-end:1px solid var(--_border)}.fly-currency-selector__search-input{inline-size:100%;padding-block:5px;padding-inline:8px;border:1px solid var(--_border);border-radius:6px;background:var(--_surface);color:var(--_text);font:inherit}.fly-currency-selector__search-input:focus-visible{outline:2px solid;outline-color:var(--_primary);outline-offset:-1px}.fly-currency-selector__listbox{flex:1 1 auto;overflow-y:auto;padding-block:4px}.fly-currency-selector__group{padding-block:6px 3px;padding-inline:10px;color:var(--_text-subtle);font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}.fly-currency-selector__option{display:flex;align-items:center;gap:9px;padding-block:5px;padding-inline:10px;cursor:pointer}.fly-currency-selector__option--active{background:var(--_surface-hover)}.fly-currency-selector__option--selected{background:var(--_surface-active)}.fly-currency-selector__option-text{display:flex;flex:1 1 auto;align-items:baseline;gap:8px;min-inline-size:0}.fly-currency-selector__option-code{flex:none;font-weight:700;letter-spacing:.02em;direction:ltr;unicode-bidi:isolate}.fly-currency-selector__option-name{flex:1 1 auto;min-inline-size:0;color:var(--_text-subtle);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fly-currency-selector__option-symbol{flex:none;min-inline-size:2.2em;color:var(--_text);text-align:end}.fly-currency-selector__check{flex:none;inline-size:1em;color:var(--_primary)}.fly-currency-selector__status{display:flex;align-items:center;gap:8px;padding-block:10px;padding-inline:10px;color:var(--_text-subtle)}.fly-currency-selector__status--error{color:var(--_danger)}.fly-currency-selector__retry{border:1px solid var(--_border);border-radius:6px;background:var(--_surface);padding-block:2px;padding-inline:8px;color:var(--_text);font:inherit;font-weight:600;cursor:pointer}\n"] }]
20729
20754
  }], ctorParameters: () => [], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], currencies: [{ type: i0.Input, args: [{ isSignal: true, alias: "currencies", required: false }] }], fetchFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "fetchFn", required: false }] }], applyTenantDefault: [{ type: i0.Input, args: [{ isSignal: true, alias: "applyTenantDefault", required: false }] }], tenantDefaultFetchFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenantDefaultFetchFn", required: false }] }], allowedCodes: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowedCodes", required: false }] }], pinnedCodes: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedCodes", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], locked: [{ type: i0.Input, args: [{ isSignal: true, alias: "locked", required: false }] }], lockedReasonKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockedReasonKey", required: false }] }], lockedReasonParams: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockedReasonParams", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], selectionDetailChange: [{ type: i0.Output, args: ["selectionDetailChange"] }], openedChange: [{ type: i0.Output, args: ["openedChange"] }], searchEl: [{
20730
20755
  type: ViewChild,
20731
20756
  args: ['searchRef']
@@ -21738,7 +21763,7 @@ class FlySearchInputComponent {
21738
21763
  this.inputEl().nativeElement.focus();
21739
21764
  }
21740
21765
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlySearchInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21741
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlySearchInputComponent, isStandalone: true, selector: "fly-search-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, placeholderKey: { classPropertyName: "placeholderKey", publicName: "placeholderKey", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelKey: { classPropertyName: "ariaLabelKey", publicName: "ariaLabelKey", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, expandTrigger: { classPropertyName: "expandTrigger", publicName: "expandTrigger", isSignal: true, isRequired: false, transformFunction: null }, stayExpandedWithValue: { classPropertyName: "stayExpandedWithValue", publicName: "stayExpandedWithValue", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showFilterToggle: { classPropertyName: "showFilterToggle", publicName: "showFilterToggle", isSignal: true, isRequired: false, transformFunction: null }, filterPanelOpen: { classPropertyName: "filterPanelOpen", publicName: "filterPanelOpen", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", queryChange: "queryChange", searched: "searched", submitted: "submitted", cleared: "cleared", expandedChange: "expandedChange", filterToggled: "filterToggled" }, host: { properties: { "class.fly-search-input-host--collapsible": "collapsible()" }, classAttribute: "fly-search-input-host" }, viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["input"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n Collapsible mode: the wrapper doubles as the \"open search\" button when collapsed\r\n behind a pointer trigger (role/tabindex/aria-label applied only then). The field\r\n stays mounted throughout (never unmounted) so focus and typed text survive the\r\n collapse animation; it's clipped to width 0 while collapsed. Logical CSS only \u2014\r\n RTL needs no overrides.\r\n-->\r\n<div\r\n class=\"fly-search-input\"\r\n [class.fly-search-input--disabled]=\"disabled()\"\r\n [class.fly-search-input--collapsible]=\"collapsible()\"\r\n [class.fly-search-input--collapsed]=\"collapsible() && !isExpanded()\"\r\n [class.fly-search-input--expanded]=\"collapsible() && isExpanded()\"\r\n [class.fly-search-input--sm]=\"size() === 'sm'\"\r\n [class.fly-search-input--lg]=\"size() === 'lg'\"\r\n [attr.role]=\"showCollapsedButton() ? 'button' : null\"\r\n [attr.tabindex]=\"showCollapsedButton() ? 0 : null\"\r\n [attr.aria-label]=\"showCollapsedButton() ? collapsedLabel() : null\"\r\n [attr.aria-expanded]=\"showCollapsedButton() ? false : null\"\r\n (mouseenter)=\"onHoverEnter()\"\r\n (mouseleave)=\"onHoverLeave()\"\r\n (click)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\"\r\n (keydown.enter)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\"\r\n (keydown.space)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\">\r\n <i class=\"pi pi-search fly-search-input__icon\" aria-hidden=\"true\"></i>\r\n\r\n <input\r\n #input\r\n class=\"fly-search-input__field\"\r\n type=\"search\"\r\n autocomplete=\"off\"\r\n [attr.tabindex]=\"fieldTabIndex()\"\r\n [attr.aria-label]=\"resolvedAriaLabel()\"\r\n [placeholder]=\"resolvedPlaceholder()\"\r\n [value]=\"value()\"\r\n [disabled]=\"disabled()\"\r\n (input)=\"onInput($event)\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"onBlur()\"\r\n (keydown.enter)=\"onEnter()\"\r\n (keydown.escape)=\"onEscape($event)\" />\r\n\r\n @if (hasValue() && !disabled() && (!collapsible() || isExpanded())) {\r\n <!-- mousedown.preventDefault keeps focus in the input: without it, the\r\n mousedown blurs the field, a collapse (stayExpandedWithValue=false)\r\n removes this button mid-gesture, and the click never lands. -->\r\n <button\r\n class=\"fly-search-input__clear\"\r\n type=\"button\"\r\n [attr.aria-label]=\"clearLabel()\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n (click)=\"$event.stopPropagation(); clear()\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n\r\n @if (showFilterToggle() && !disabled()) {\r\n <!-- Advanced-filter affordance. Same mousedown.preventDefault as the clear\r\n button: without it the mousedown blurs the field, which can collapse a\r\n `collapsible` box and unmount this button before the click lands. -->\r\n <button\r\n class=\"fly-search-input__filter\"\r\n type=\"button\"\r\n [class.fly-search-input__filter--open]=\"filterPanelOpen()\"\r\n [attr.aria-expanded]=\"filterPanelOpen()\"\r\n [attr.aria-label]=\"filterToggleLabel()\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n (click)=\"$event.stopPropagation(); filterToggled.emit()\">\r\n <i class=\"pi pi-chevron-down\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n\r\n @if ((!collapsible() || isExpanded()) && !disabled()) {\r\n <!-- Composable trailing affordance (e.g. a \"Filters\" button) \u2014 see the\r\n component doc's \"Nova morph\" section. Gated the same as the buttons\r\n above: never rendered in the closed circle, so a caller's content\r\n can never visibly break the collapsed geometry. -->\r\n <span class=\"fly-search-input__trailing\">\r\n <ng-content select=\"[flySearchTrailing]\" />\r\n </span>\r\n }\r\n</div>\r\n", styles: [":host{--fly-search-size: 36px;--fly-search-radius: 8px;--fly-search-font: 13px;--fly-search-expanded-width: 230px;--fly-search-max-width: 320px;--fly-search-anim-duration: var(--nova-duration-settle);--fly-search-anim-ease: var(--nova-ease-structural);--fly-search-open-bg: var(--w09);display:block}:host(.fly-search-input-host--collapsible){display:inline-flex;justify-content:var(--fly-search-anchor, flex-end)}.fly-search-input{box-sizing:border-box;display:flex;align-items:center;gap:8px;inline-size:100%;max-inline-size:var(--fly-search-max-width);block-size:var(--fly-search-size);padding-block:0;padding-inline:10px;border-radius:var(--fly-search-radius);background:var(--surface-hover, rgba(0, 0, 0, .04));border:1px solid var(--surface-border, rgba(0, 0, 0, .12));transition:border-color .15s ease}.fly-search-input:focus-within{border-color:var(--primary-color)}.fly-search-input--disabled{opacity:.6;cursor:not-allowed}.fly-search-input--sm{--fly-search-size: 28px;--fly-search-font: 12px}.fly-search-input--lg{--fly-search-size: 44px;--fly-search-font: 14px}.fly-search-input__icon{flex-shrink:0;font-size:var(--fly-search-font);color:var(--text-color-secondary, rgba(17, 24, 39, .55))}.fly-search-input__field{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-family:inherit;font-size:var(--fly-search-font)}.fly-search-input__field::placeholder{color:var(--text-color-secondary, rgba(17, 24, 39, .55));opacity:.8}.fly-search-input__field::-webkit-search-cancel-button,.fly-search-input__field::-webkit-search-decoration{appearance:none}.fly-search-input__clear{position:relative;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;padding:0;border:none;border-radius:50%;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:11px;transition:background-color .15s ease}.fly-search-input__clear:before{content:\"\";position:absolute;inset:-4px;border-radius:50%}.fly-search-input__clear:hover{background:var(--surface-border, rgba(0, 0, 0, .12))}.fly-search-input__clear:focus-visible{outline:2px solid var(--primary-color);outline-offset:1px}.fly-search-input__filter{position:relative;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;padding:0;border:none;border-radius:50%;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:11px;transition:background-color .15s ease}.fly-search-input__filter:before{content:\"\";position:absolute;inset:-4px;border-radius:50%}.fly-search-input__filter i{transition:transform .15s ease}.fly-search-input__filter--open i{transform:rotate(180deg)}.fly-search-input__filter:hover{background:var(--surface-border, rgba(0, 0, 0, .12))}.fly-search-input__filter:focus-visible{outline:2px solid var(--primary-color);outline-offset:1px}.fly-search-input__trailing{display:inline-flex;flex-shrink:0;align-items:center}.fly-search-input__trailing:empty{display:none}.fly-search-input--collapsible{inline-size:var(--fly-search-size);max-inline-size:var(--fly-search-size);padding-inline:0;justify-content:center;overflow:hidden;cursor:text;background:transparent;border-color:transparent;transition:inline-size var(--fly-search-anim-duration) var(--fly-search-anim-ease),max-inline-size var(--fly-search-anim-duration) var(--fly-search-anim-ease),border-radius var(--fly-search-anim-duration) var(--fly-search-anim-ease),padding-inline var(--fly-search-anim-duration) var(--fly-search-anim-ease),box-shadow .2s ease,border-color .16s ease,background-color .16s ease}.fly-search-input--collapsible:hover,.fly-search-input--collapsible:focus-within,.fly-search-input--collapsible.fly-search-input--expanded{will-change:inline-size}.fly-search-input--collapsible:focus-within{border-color:transparent}.fly-search-input--collapsible .fly-search-input__icon{color:var(--chrome-ink)}.fly-search-input--collapsible .fly-search-input__field{transition:opacity .12s ease}.fly-search-input--collapsible.fly-search-input--collapsed{border-radius:999px;gap:0}.fly-search-input--collapsible.fly-search-input--collapsed .fly-search-input__field{flex:0 0 0;inline-size:0;min-inline-size:0;padding:0;opacity:0}.fly-search-input--collapsible.fly-search-input--collapsed .fly-search-input__icon{pointer-events:none}.fly-search-input--collapsible.fly-search-input--expanded{inline-size:var(--fly-search-expanded-width);max-inline-size:var(--fly-search-expanded-width);padding-inline:5px;justify-content:flex-start;border-radius:var(--fly-search-radius);background:var(--fly-search-open-bg);box-shadow:var(--fly-search-focus-ring, none)}.fly-search-input--collapsible.fly-search-input--expanded .fly-search-input__field{transition:opacity .22s ease calc(var(--fly-search-anim-duration) * .4)}.fly-search-input--collapsible.fly-search-input--expanded:focus-within{box-shadow:var(--fly-search-focus-ring, 0 0 0 2px var(--primary-color))}.fly-search-input--collapsible[role=button]{cursor:pointer}.fly-search-input--collapsible[role=button]:focus-visible{outline:2px solid var(--primary-color);outline-offset:2px}@media(prefers-reduced-motion:reduce){.fly-search-input,.fly-search-input--collapsible,.fly-search-input--collapsible .fly-search-input__field,.fly-search-input__clear,.fly-search-input__filter,.fly-search-input__filter i{transition:none}}@media(forced-colors:active){.fly-search-input,.fly-search-input--collapsible.fly-search-input--collapsed{border-color:CanvasText}.fly-search-input__clear:hover{background:Highlight}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
21766
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlySearchInputComponent, isStandalone: true, selector: "fly-search-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, placeholderKey: { classPropertyName: "placeholderKey", publicName: "placeholderKey", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelKey: { classPropertyName: "ariaLabelKey", publicName: "ariaLabelKey", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, expandTrigger: { classPropertyName: "expandTrigger", publicName: "expandTrigger", isSignal: true, isRequired: false, transformFunction: null }, stayExpandedWithValue: { classPropertyName: "stayExpandedWithValue", publicName: "stayExpandedWithValue", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showFilterToggle: { classPropertyName: "showFilterToggle", publicName: "showFilterToggle", isSignal: true, isRequired: false, transformFunction: null }, filterPanelOpen: { classPropertyName: "filterPanelOpen", publicName: "filterPanelOpen", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", queryChange: "queryChange", searched: "searched", submitted: "submitted", cleared: "cleared", expandedChange: "expandedChange", filterToggled: "filterToggled" }, host: { properties: { "class.fly-search-input-host--collapsible": "collapsible()" }, classAttribute: "fly-search-input-host" }, viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["input"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n Collapsible mode: the wrapper doubles as the \"open search\" button when collapsed\r\n behind a pointer trigger (role/tabindex/aria-label applied only then). The field\r\n stays mounted throughout (never unmounted) so focus and typed text survive the\r\n collapse animation; it's clipped to width 0 while collapsed. Logical CSS only \u2014\r\n RTL needs no overrides.\r\n-->\r\n<div\r\n class=\"fly-search-input\"\r\n [class.fly-search-input--disabled]=\"disabled()\"\r\n [class.fly-search-input--collapsible]=\"collapsible()\"\r\n [class.fly-search-input--collapsed]=\"collapsible() && !isExpanded()\"\r\n [class.fly-search-input--expanded]=\"collapsible() && isExpanded()\"\r\n [class.fly-search-input--sm]=\"size() === 'sm'\"\r\n [class.fly-search-input--lg]=\"size() === 'lg'\"\r\n [attr.role]=\"showCollapsedButton() ? 'button' : null\"\r\n [attr.tabindex]=\"showCollapsedButton() ? 0 : null\"\r\n [attr.aria-label]=\"showCollapsedButton() ? collapsedLabel() : null\"\r\n [attr.aria-expanded]=\"showCollapsedButton() ? false : null\"\r\n (mouseenter)=\"onHoverEnter()\"\r\n (mouseleave)=\"onHoverLeave()\"\r\n (click)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\"\r\n (keydown.enter)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\"\r\n (keydown.space)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\">\r\n <i class=\"pi pi-search fly-search-input__icon\" aria-hidden=\"true\"></i>\r\n\r\n <input\r\n #input\r\n class=\"fly-search-input__field\"\r\n type=\"search\"\r\n autocomplete=\"off\"\r\n [attr.tabindex]=\"fieldTabIndex()\"\r\n [attr.aria-label]=\"resolvedAriaLabel()\"\r\n [placeholder]=\"resolvedPlaceholder()\"\r\n [value]=\"value()\"\r\n [disabled]=\"disabled()\"\r\n (input)=\"onInput($event)\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"onBlur()\"\r\n (keydown.enter)=\"onEnter()\"\r\n (keydown.escape)=\"onEscape($event)\" />\r\n\r\n @if (hasValue() && !disabled() && (!collapsible() || isExpanded())) {\r\n <!-- mousedown.preventDefault keeps focus in the input: without it, the\r\n mousedown blurs the field, a collapse (stayExpandedWithValue=false)\r\n removes this button mid-gesture, and the click never lands. -->\r\n <button\r\n class=\"fly-search-input__clear\"\r\n type=\"button\"\r\n [attr.aria-label]=\"clearLabel()\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n (click)=\"$event.stopPropagation(); clear()\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n\r\n @if (showFilterToggle() && !disabled()) {\r\n <!-- Advanced-filter affordance. Same mousedown.preventDefault as the clear\r\n button: without it the mousedown blurs the field, which can collapse a\r\n `collapsible` box and unmount this button before the click lands. -->\r\n <button\r\n class=\"fly-search-input__filter\"\r\n type=\"button\"\r\n [class.fly-search-input__filter--open]=\"filterPanelOpen()\"\r\n [attr.aria-expanded]=\"filterPanelOpen()\"\r\n [attr.aria-label]=\"filterToggleLabel()\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n (click)=\"$event.stopPropagation(); filterToggled.emit()\">\r\n <i class=\"pi pi-chevron-down\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n\r\n @if ((!collapsible() || isExpanded()) && !disabled()) {\r\n <!-- Composable trailing affordance (e.g. a \"Filters\" button) \u2014 see the\r\n component doc's \"Nova morph\" section. Gated the same as the buttons\r\n above: never rendered in the closed circle, so a caller's content\r\n can never visibly break the collapsed geometry. -->\r\n <span class=\"fly-search-input__trailing\">\r\n <ng-content select=\"[flySearchTrailing]\" />\r\n </span>\r\n }\r\n</div>\r\n", styles: [":host{--fly-search-size: 36px;--fly-search-radius: 8px;--fly-search-font: 13px;--fly-search-expanded-width: 230px;--fly-search-max-width: 320px;--fly-search-anim-duration: var(--nova-duration-settle);--fly-search-anim-ease: var(--nova-ease-structural);--fly-search-open-bg: var(--w09);display:block}:host(.fly-search-input-host--collapsible){display:inline-flex;justify-content:var(--fly-search-anchor, flex-end)}.fly-search-input{box-sizing:border-box;display:flex;align-items:center;gap:8px;inline-size:100%;max-inline-size:var(--fly-search-max-width);block-size:var(--fly-search-size);padding-block:0;padding-inline:10px;border-radius:var(--fly-search-radius);background:var(--surface-hover, rgba(0, 0, 0, .04));border:1px solid var(--surface-border, rgba(0, 0, 0, .12));transition:border-color .15s ease}.fly-search-input:focus-within{border-color:var(--primary-color)}.fly-search-input--disabled{opacity:.6;cursor:not-allowed}.fly-search-input--sm{--fly-search-size: 28px;--fly-search-font: 12px}.fly-search-input--lg{--fly-search-size: 44px;--fly-search-font: 14px}.fly-search-input__icon{flex-shrink:0;font-size:var(--fly-search-font);color:var(--text-color-secondary, rgba(17, 24, 39, .55))}.fly-search-input__field{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-family:inherit;font-size:var(--fly-search-font)}.fly-search-input__field::placeholder{color:var(--text-color-secondary, rgba(17, 24, 39, .55));opacity:.8}.fly-search-input__field::-webkit-search-cancel-button,.fly-search-input__field::-webkit-search-decoration{appearance:none}.fly-search-input__clear{position:relative;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;padding:0;border:none;border-radius:50%;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:11px;transition:background-color .15s ease}.fly-search-input__clear:before{content:\"\";position:absolute;inset:-4px;border-radius:50%}.fly-search-input__clear:hover{background:var(--surface-border, rgba(0, 0, 0, .12))}.fly-search-input__clear:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:1px}.fly-search-input__filter{position:relative;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;padding:0;border:none;border-radius:50%;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:11px;transition:background-color .15s ease}.fly-search-input__filter:before{content:\"\";position:absolute;inset:-4px;border-radius:50%}.fly-search-input__filter i{transition:transform .15s ease}.fly-search-input__filter--open i{transform:rotate(180deg)}.fly-search-input__filter:hover{background:var(--surface-border, rgba(0, 0, 0, .12))}.fly-search-input__filter:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:1px}.fly-search-input__trailing{display:inline-flex;flex-shrink:0;align-items:center}.fly-search-input__trailing:empty{display:none}.fly-search-input--collapsible{inline-size:var(--fly-search-size);max-inline-size:var(--fly-search-size);padding-inline:0;justify-content:center;overflow:hidden;cursor:text;background:transparent;border-color:transparent;transition:inline-size var(--fly-search-anim-duration) var(--fly-search-anim-ease),max-inline-size var(--fly-search-anim-duration) var(--fly-search-anim-ease),border-radius var(--fly-search-anim-duration) var(--fly-search-anim-ease),padding-inline var(--fly-search-anim-duration) var(--fly-search-anim-ease),box-shadow .2s ease,border-color .16s ease,background-color .16s ease}.fly-search-input--collapsible:hover,.fly-search-input--collapsible:focus-within,.fly-search-input--collapsible.fly-search-input--expanded{will-change:inline-size}.fly-search-input--collapsible:focus-within{border-color:transparent}.fly-search-input--collapsible .fly-search-input__icon{color:var(--chrome-ink)}.fly-search-input--collapsible .fly-search-input__field{transition:opacity .12s ease}.fly-search-input--collapsible.fly-search-input--collapsed{border-radius:999px;gap:0}.fly-search-input--collapsible.fly-search-input--collapsed .fly-search-input__field{flex:0 0 0;inline-size:0;min-inline-size:0;padding:0;opacity:0}.fly-search-input--collapsible.fly-search-input--collapsed .fly-search-input__icon{pointer-events:none}.fly-search-input--collapsible.fly-search-input--expanded{inline-size:var(--fly-search-expanded-width);max-inline-size:var(--fly-search-expanded-width);padding-inline:5px;justify-content:flex-start;border-radius:var(--fly-search-radius);background:var(--fly-search-open-bg);box-shadow:var(--fly-search-focus-ring, none)}.fly-search-input--collapsible.fly-search-input--expanded .fly-search-input__field{transition:opacity .22s ease calc(var(--fly-search-anim-duration) * .4)}.fly-search-input--collapsible.fly-search-input--expanded:focus-within{box-shadow:var(--fly-search-focus-ring, 0 0 0 2px var(--primary-color))}.fly-search-input--collapsible[role=button]{cursor:pointer}.fly-search-input--collapsible[role=button]:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:2px}@media(prefers-reduced-motion:reduce){.fly-search-input,.fly-search-input--collapsible,.fly-search-input--collapsible .fly-search-input__field,.fly-search-input__clear,.fly-search-input__filter,.fly-search-input__filter i{transition:none}}@media(forced-colors:active){.fly-search-input,.fly-search-input--collapsible.fly-search-input--collapsed{border-color:CanvasText}.fly-search-input__clear:hover{background:Highlight}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
21742
21767
  }
21743
21768
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlySearchInputComponent, decorators: [{
21744
21769
  type: Component,
@@ -21748,7 +21773,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
21748
21773
  // the pill pins to the host's inline-END so the magnifier stays put while the
21749
21774
  // host's flex-grow snap only moves the START edge.
21750
21775
  '[class.fly-search-input-host--collapsible]': 'collapsible()',
21751
- }, template: "<!--\r\n Collapsible mode: the wrapper doubles as the \"open search\" button when collapsed\r\n behind a pointer trigger (role/tabindex/aria-label applied only then). The field\r\n stays mounted throughout (never unmounted) so focus and typed text survive the\r\n collapse animation; it's clipped to width 0 while collapsed. Logical CSS only \u2014\r\n RTL needs no overrides.\r\n-->\r\n<div\r\n class=\"fly-search-input\"\r\n [class.fly-search-input--disabled]=\"disabled()\"\r\n [class.fly-search-input--collapsible]=\"collapsible()\"\r\n [class.fly-search-input--collapsed]=\"collapsible() && !isExpanded()\"\r\n [class.fly-search-input--expanded]=\"collapsible() && isExpanded()\"\r\n [class.fly-search-input--sm]=\"size() === 'sm'\"\r\n [class.fly-search-input--lg]=\"size() === 'lg'\"\r\n [attr.role]=\"showCollapsedButton() ? 'button' : null\"\r\n [attr.tabindex]=\"showCollapsedButton() ? 0 : null\"\r\n [attr.aria-label]=\"showCollapsedButton() ? collapsedLabel() : null\"\r\n [attr.aria-expanded]=\"showCollapsedButton() ? false : null\"\r\n (mouseenter)=\"onHoverEnter()\"\r\n (mouseleave)=\"onHoverLeave()\"\r\n (click)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\"\r\n (keydown.enter)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\"\r\n (keydown.space)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\">\r\n <i class=\"pi pi-search fly-search-input__icon\" aria-hidden=\"true\"></i>\r\n\r\n <input\r\n #input\r\n class=\"fly-search-input__field\"\r\n type=\"search\"\r\n autocomplete=\"off\"\r\n [attr.tabindex]=\"fieldTabIndex()\"\r\n [attr.aria-label]=\"resolvedAriaLabel()\"\r\n [placeholder]=\"resolvedPlaceholder()\"\r\n [value]=\"value()\"\r\n [disabled]=\"disabled()\"\r\n (input)=\"onInput($event)\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"onBlur()\"\r\n (keydown.enter)=\"onEnter()\"\r\n (keydown.escape)=\"onEscape($event)\" />\r\n\r\n @if (hasValue() && !disabled() && (!collapsible() || isExpanded())) {\r\n <!-- mousedown.preventDefault keeps focus in the input: without it, the\r\n mousedown blurs the field, a collapse (stayExpandedWithValue=false)\r\n removes this button mid-gesture, and the click never lands. -->\r\n <button\r\n class=\"fly-search-input__clear\"\r\n type=\"button\"\r\n [attr.aria-label]=\"clearLabel()\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n (click)=\"$event.stopPropagation(); clear()\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n\r\n @if (showFilterToggle() && !disabled()) {\r\n <!-- Advanced-filter affordance. Same mousedown.preventDefault as the clear\r\n button: without it the mousedown blurs the field, which can collapse a\r\n `collapsible` box and unmount this button before the click lands. -->\r\n <button\r\n class=\"fly-search-input__filter\"\r\n type=\"button\"\r\n [class.fly-search-input__filter--open]=\"filterPanelOpen()\"\r\n [attr.aria-expanded]=\"filterPanelOpen()\"\r\n [attr.aria-label]=\"filterToggleLabel()\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n (click)=\"$event.stopPropagation(); filterToggled.emit()\">\r\n <i class=\"pi pi-chevron-down\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n\r\n @if ((!collapsible() || isExpanded()) && !disabled()) {\r\n <!-- Composable trailing affordance (e.g. a \"Filters\" button) \u2014 see the\r\n component doc's \"Nova morph\" section. Gated the same as the buttons\r\n above: never rendered in the closed circle, so a caller's content\r\n can never visibly break the collapsed geometry. -->\r\n <span class=\"fly-search-input__trailing\">\r\n <ng-content select=\"[flySearchTrailing]\" />\r\n </span>\r\n }\r\n</div>\r\n", styles: [":host{--fly-search-size: 36px;--fly-search-radius: 8px;--fly-search-font: 13px;--fly-search-expanded-width: 230px;--fly-search-max-width: 320px;--fly-search-anim-duration: var(--nova-duration-settle);--fly-search-anim-ease: var(--nova-ease-structural);--fly-search-open-bg: var(--w09);display:block}:host(.fly-search-input-host--collapsible){display:inline-flex;justify-content:var(--fly-search-anchor, flex-end)}.fly-search-input{box-sizing:border-box;display:flex;align-items:center;gap:8px;inline-size:100%;max-inline-size:var(--fly-search-max-width);block-size:var(--fly-search-size);padding-block:0;padding-inline:10px;border-radius:var(--fly-search-radius);background:var(--surface-hover, rgba(0, 0, 0, .04));border:1px solid var(--surface-border, rgba(0, 0, 0, .12));transition:border-color .15s ease}.fly-search-input:focus-within{border-color:var(--primary-color)}.fly-search-input--disabled{opacity:.6;cursor:not-allowed}.fly-search-input--sm{--fly-search-size: 28px;--fly-search-font: 12px}.fly-search-input--lg{--fly-search-size: 44px;--fly-search-font: 14px}.fly-search-input__icon{flex-shrink:0;font-size:var(--fly-search-font);color:var(--text-color-secondary, rgba(17, 24, 39, .55))}.fly-search-input__field{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-family:inherit;font-size:var(--fly-search-font)}.fly-search-input__field::placeholder{color:var(--text-color-secondary, rgba(17, 24, 39, .55));opacity:.8}.fly-search-input__field::-webkit-search-cancel-button,.fly-search-input__field::-webkit-search-decoration{appearance:none}.fly-search-input__clear{position:relative;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;padding:0;border:none;border-radius:50%;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:11px;transition:background-color .15s ease}.fly-search-input__clear:before{content:\"\";position:absolute;inset:-4px;border-radius:50%}.fly-search-input__clear:hover{background:var(--surface-border, rgba(0, 0, 0, .12))}.fly-search-input__clear:focus-visible{outline:2px solid var(--primary-color);outline-offset:1px}.fly-search-input__filter{position:relative;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;padding:0;border:none;border-radius:50%;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:11px;transition:background-color .15s ease}.fly-search-input__filter:before{content:\"\";position:absolute;inset:-4px;border-radius:50%}.fly-search-input__filter i{transition:transform .15s ease}.fly-search-input__filter--open i{transform:rotate(180deg)}.fly-search-input__filter:hover{background:var(--surface-border, rgba(0, 0, 0, .12))}.fly-search-input__filter:focus-visible{outline:2px solid var(--primary-color);outline-offset:1px}.fly-search-input__trailing{display:inline-flex;flex-shrink:0;align-items:center}.fly-search-input__trailing:empty{display:none}.fly-search-input--collapsible{inline-size:var(--fly-search-size);max-inline-size:var(--fly-search-size);padding-inline:0;justify-content:center;overflow:hidden;cursor:text;background:transparent;border-color:transparent;transition:inline-size var(--fly-search-anim-duration) var(--fly-search-anim-ease),max-inline-size var(--fly-search-anim-duration) var(--fly-search-anim-ease),border-radius var(--fly-search-anim-duration) var(--fly-search-anim-ease),padding-inline var(--fly-search-anim-duration) var(--fly-search-anim-ease),box-shadow .2s ease,border-color .16s ease,background-color .16s ease}.fly-search-input--collapsible:hover,.fly-search-input--collapsible:focus-within,.fly-search-input--collapsible.fly-search-input--expanded{will-change:inline-size}.fly-search-input--collapsible:focus-within{border-color:transparent}.fly-search-input--collapsible .fly-search-input__icon{color:var(--chrome-ink)}.fly-search-input--collapsible .fly-search-input__field{transition:opacity .12s ease}.fly-search-input--collapsible.fly-search-input--collapsed{border-radius:999px;gap:0}.fly-search-input--collapsible.fly-search-input--collapsed .fly-search-input__field{flex:0 0 0;inline-size:0;min-inline-size:0;padding:0;opacity:0}.fly-search-input--collapsible.fly-search-input--collapsed .fly-search-input__icon{pointer-events:none}.fly-search-input--collapsible.fly-search-input--expanded{inline-size:var(--fly-search-expanded-width);max-inline-size:var(--fly-search-expanded-width);padding-inline:5px;justify-content:flex-start;border-radius:var(--fly-search-radius);background:var(--fly-search-open-bg);box-shadow:var(--fly-search-focus-ring, none)}.fly-search-input--collapsible.fly-search-input--expanded .fly-search-input__field{transition:opacity .22s ease calc(var(--fly-search-anim-duration) * .4)}.fly-search-input--collapsible.fly-search-input--expanded:focus-within{box-shadow:var(--fly-search-focus-ring, 0 0 0 2px var(--primary-color))}.fly-search-input--collapsible[role=button]{cursor:pointer}.fly-search-input--collapsible[role=button]:focus-visible{outline:2px solid var(--primary-color);outline-offset:2px}@media(prefers-reduced-motion:reduce){.fly-search-input,.fly-search-input--collapsible,.fly-search-input--collapsible .fly-search-input__field,.fly-search-input__clear,.fly-search-input__filter,.fly-search-input__filter i{transition:none}}@media(forced-colors:active){.fly-search-input,.fly-search-input--collapsible.fly-search-input--collapsed{border-color:CanvasText}.fly-search-input__clear:hover{background:Highlight}}\n"] }]
21776
+ }, template: "<!--\r\n Collapsible mode: the wrapper doubles as the \"open search\" button when collapsed\r\n behind a pointer trigger (role/tabindex/aria-label applied only then). The field\r\n stays mounted throughout (never unmounted) so focus and typed text survive the\r\n collapse animation; it's clipped to width 0 while collapsed. Logical CSS only \u2014\r\n RTL needs no overrides.\r\n-->\r\n<div\r\n class=\"fly-search-input\"\r\n [class.fly-search-input--disabled]=\"disabled()\"\r\n [class.fly-search-input--collapsible]=\"collapsible()\"\r\n [class.fly-search-input--collapsed]=\"collapsible() && !isExpanded()\"\r\n [class.fly-search-input--expanded]=\"collapsible() && isExpanded()\"\r\n [class.fly-search-input--sm]=\"size() === 'sm'\"\r\n [class.fly-search-input--lg]=\"size() === 'lg'\"\r\n [attr.role]=\"showCollapsedButton() ? 'button' : null\"\r\n [attr.tabindex]=\"showCollapsedButton() ? 0 : null\"\r\n [attr.aria-label]=\"showCollapsedButton() ? collapsedLabel() : null\"\r\n [attr.aria-expanded]=\"showCollapsedButton() ? false : null\"\r\n (mouseenter)=\"onHoverEnter()\"\r\n (mouseleave)=\"onHoverLeave()\"\r\n (click)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\"\r\n (keydown.enter)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\"\r\n (keydown.space)=\"showCollapsedButton() ? onCollapsedActivate($event) : null\">\r\n <i class=\"pi pi-search fly-search-input__icon\" aria-hidden=\"true\"></i>\r\n\r\n <input\r\n #input\r\n class=\"fly-search-input__field\"\r\n type=\"search\"\r\n autocomplete=\"off\"\r\n [attr.tabindex]=\"fieldTabIndex()\"\r\n [attr.aria-label]=\"resolvedAriaLabel()\"\r\n [placeholder]=\"resolvedPlaceholder()\"\r\n [value]=\"value()\"\r\n [disabled]=\"disabled()\"\r\n (input)=\"onInput($event)\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"onBlur()\"\r\n (keydown.enter)=\"onEnter()\"\r\n (keydown.escape)=\"onEscape($event)\" />\r\n\r\n @if (hasValue() && !disabled() && (!collapsible() || isExpanded())) {\r\n <!-- mousedown.preventDefault keeps focus in the input: without it, the\r\n mousedown blurs the field, a collapse (stayExpandedWithValue=false)\r\n removes this button mid-gesture, and the click never lands. -->\r\n <button\r\n class=\"fly-search-input__clear\"\r\n type=\"button\"\r\n [attr.aria-label]=\"clearLabel()\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n (click)=\"$event.stopPropagation(); clear()\">\r\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n\r\n @if (showFilterToggle() && !disabled()) {\r\n <!-- Advanced-filter affordance. Same mousedown.preventDefault as the clear\r\n button: without it the mousedown blurs the field, which can collapse a\r\n `collapsible` box and unmount this button before the click lands. -->\r\n <button\r\n class=\"fly-search-input__filter\"\r\n type=\"button\"\r\n [class.fly-search-input__filter--open]=\"filterPanelOpen()\"\r\n [attr.aria-expanded]=\"filterPanelOpen()\"\r\n [attr.aria-label]=\"filterToggleLabel()\"\r\n (mousedown)=\"$event.preventDefault()\"\r\n (click)=\"$event.stopPropagation(); filterToggled.emit()\">\r\n <i class=\"pi pi-chevron-down\" aria-hidden=\"true\"></i>\r\n </button>\r\n }\r\n\r\n @if ((!collapsible() || isExpanded()) && !disabled()) {\r\n <!-- Composable trailing affordance (e.g. a \"Filters\" button) \u2014 see the\r\n component doc's \"Nova morph\" section. Gated the same as the buttons\r\n above: never rendered in the closed circle, so a caller's content\r\n can never visibly break the collapsed geometry. -->\r\n <span class=\"fly-search-input__trailing\">\r\n <ng-content select=\"[flySearchTrailing]\" />\r\n </span>\r\n }\r\n</div>\r\n", styles: [":host{--fly-search-size: 36px;--fly-search-radius: 8px;--fly-search-font: 13px;--fly-search-expanded-width: 230px;--fly-search-max-width: 320px;--fly-search-anim-duration: var(--nova-duration-settle);--fly-search-anim-ease: var(--nova-ease-structural);--fly-search-open-bg: var(--w09);display:block}:host(.fly-search-input-host--collapsible){display:inline-flex;justify-content:var(--fly-search-anchor, flex-end)}.fly-search-input{box-sizing:border-box;display:flex;align-items:center;gap:8px;inline-size:100%;max-inline-size:var(--fly-search-max-width);block-size:var(--fly-search-size);padding-block:0;padding-inline:10px;border-radius:var(--fly-search-radius);background:var(--surface-hover, rgba(0, 0, 0, .04));border:1px solid var(--surface-border, rgba(0, 0, 0, .12));transition:border-color .15s ease}.fly-search-input:focus-within{border-color:var(--primary-color)}.fly-search-input--disabled{opacity:.6;cursor:not-allowed}.fly-search-input--sm{--fly-search-size: 28px;--fly-search-font: 12px}.fly-search-input--lg{--fly-search-size: 44px;--fly-search-font: 14px}.fly-search-input__icon{flex-shrink:0;font-size:var(--fly-search-font);color:var(--text-color-secondary, rgba(17, 24, 39, .55))}.fly-search-input__field{flex:1 1 auto;min-inline-size:0;background:transparent;border:none;outline:none;color:inherit;font-family:inherit;font-size:var(--fly-search-font)}.fly-search-input__field::placeholder{color:var(--text-color-secondary, rgba(17, 24, 39, .55));opacity:.8}.fly-search-input__field::-webkit-search-cancel-button,.fly-search-input__field::-webkit-search-decoration{appearance:none}.fly-search-input__clear{position:relative;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;padding:0;border:none;border-radius:50%;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:11px;transition:background-color .15s ease}.fly-search-input__clear:before{content:\"\";position:absolute;inset:-4px;border-radius:50%}.fly-search-input__clear:hover{background:var(--surface-border, rgba(0, 0, 0, .12))}.fly-search-input__clear:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:1px}.fly-search-input__filter{position:relative;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;inline-size:18px;block-size:18px;padding:0;border:none;border-radius:50%;background:transparent;color:var(--text-color-secondary, rgba(17, 24, 39, .55));cursor:pointer;font-size:11px;transition:background-color .15s ease}.fly-search-input__filter:before{content:\"\";position:absolute;inset:-4px;border-radius:50%}.fly-search-input__filter i{transition:transform .15s ease}.fly-search-input__filter--open i{transform:rotate(180deg)}.fly-search-input__filter:hover{background:var(--surface-border, rgba(0, 0, 0, .12))}.fly-search-input__filter:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:1px}.fly-search-input__trailing{display:inline-flex;flex-shrink:0;align-items:center}.fly-search-input__trailing:empty{display:none}.fly-search-input--collapsible{inline-size:var(--fly-search-size);max-inline-size:var(--fly-search-size);padding-inline:0;justify-content:center;overflow:hidden;cursor:text;background:transparent;border-color:transparent;transition:inline-size var(--fly-search-anim-duration) var(--fly-search-anim-ease),max-inline-size var(--fly-search-anim-duration) var(--fly-search-anim-ease),border-radius var(--fly-search-anim-duration) var(--fly-search-anim-ease),padding-inline var(--fly-search-anim-duration) var(--fly-search-anim-ease),box-shadow .2s ease,border-color .16s ease,background-color .16s ease}.fly-search-input--collapsible:hover,.fly-search-input--collapsible:focus-within,.fly-search-input--collapsible.fly-search-input--expanded{will-change:inline-size}.fly-search-input--collapsible:focus-within{border-color:transparent}.fly-search-input--collapsible .fly-search-input__icon{color:var(--chrome-ink)}.fly-search-input--collapsible .fly-search-input__field{transition:opacity .12s ease}.fly-search-input--collapsible.fly-search-input--collapsed{border-radius:999px;gap:0}.fly-search-input--collapsible.fly-search-input--collapsed .fly-search-input__field{flex:0 0 0;inline-size:0;min-inline-size:0;padding:0;opacity:0}.fly-search-input--collapsible.fly-search-input--collapsed .fly-search-input__icon{pointer-events:none}.fly-search-input--collapsible.fly-search-input--expanded{inline-size:var(--fly-search-expanded-width);max-inline-size:var(--fly-search-expanded-width);padding-inline:5px;justify-content:flex-start;border-radius:var(--fly-search-radius);background:var(--fly-search-open-bg);box-shadow:var(--fly-search-focus-ring, none)}.fly-search-input--collapsible.fly-search-input--expanded .fly-search-input__field{transition:opacity .22s ease calc(var(--fly-search-anim-duration) * .4)}.fly-search-input--collapsible.fly-search-input--expanded:focus-within{box-shadow:var(--fly-search-focus-ring, 0 0 0 2px var(--primary-color))}.fly-search-input--collapsible[role=button]{cursor:pointer}.fly-search-input--collapsible[role=button]:focus-visible{outline:2px solid;outline-color:var(--primary-color);outline-offset:2px}@media(prefers-reduced-motion:reduce){.fly-search-input,.fly-search-input--collapsible,.fly-search-input--collapsible .fly-search-input__field,.fly-search-input__clear,.fly-search-input__filter,.fly-search-input__filter i{transition:none}}@media(forced-colors:active){.fly-search-input,.fly-search-input--collapsible.fly-search-input--collapsed{border-color:CanvasText}.fly-search-input__clear:hover{background:Highlight}}\n"] }]
21752
21777
  }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], placeholderKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholderKey", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelKey", required: false }] }], debounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceMs", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], expandTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandTrigger", required: false }] }], stayExpandedWithValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "stayExpandedWithValue", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showFilterToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFilterToggle", required: false }] }], filterPanelOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPanelOpen", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], queryChange: [{ type: i0.Output, args: ["queryChange"] }], searched: [{ type: i0.Output, args: ["searched"] }], submitted: [{ type: i0.Output, args: ["submitted"] }], cleared: [{ type: i0.Output, args: ["cleared"] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }], filterToggled: [{ type: i0.Output, args: ["filterToggled"] }], inputEl: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }] } });
21753
21778
 
21754
21779
  /**
@@ -22175,7 +22200,7 @@ class FlyButtonComponent {
22175
22200
  <i class="pi pi-spin pi-spinner" aria-hidden="true"></i>
22176
22201
  }
22177
22202
  <ng-content />
22178
- `, isInline: true, styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);font-family:inherit;font-size:var(--text-base);font-weight:var(--fw-medium);border-radius:var(--r-md);border:1px solid transparent;cursor:pointer;transition:background var(--t-state),border-color var(--t-state),color var(--t-state),box-shadow var(--t-state),filter var(--t-state)}:host:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host:disabled,:host[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}:host{gap:6px;padding-block:0;text-decoration:none}:host[aria-busy=true]{pointer-events:none}:host ::ng-deep svg{width:15px;height:15px;flex-shrink:0}:host .pi,:host ::ng-deep .pi{font-size:15px}:host([data-size=xs]){height:24px;padding-inline:var(--sp-2);font-size:var(--text-xs)}:host([data-size=sm]){height:28px;padding-inline:10px;font-size:var(--text-sm)}:host([data-size=md]){height:34px;padding-inline:var(--sp-3);font-size:var(--text-sm)}:host([data-variant=primary]){background:var(--ink);border-color:var(--ink);color:var(--on-ink)}:host([data-variant=primary]):hover{background:var(--ink-hover)}:host([data-variant=secondary]){background:var(--bg-2);border-color:var(--line);color:var(--ink-2)}:host([data-variant=secondary]):hover{background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}:host([data-variant=ghost]){background:transparent;color:var(--ink-2)}:host([data-variant=ghost]):hover{background:var(--bg-3);color:var(--ink)}:host([data-variant=danger]){background:transparent;border-color:var(--danger-line);color:var(--danger)}:host([data-variant=danger]):hover{background:var(--danger-bg)}:host([data-variant=danger-fill]){background:var(--danger);border-color:transparent;color:var(--ink-inverse)}:host([data-variant=danger-fill]):hover{filter:brightness(1.05)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22203
+ `, isInline: true, styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);font-family:inherit;font-size:var(--text-base);font-weight:var(--fw-medium);border-radius:var(--r-md);border:1px solid transparent;cursor:pointer;transition:background var(--t-state),border-color var(--t-state),color var(--t-state),box-shadow var(--t-state),filter var(--t-state)}:host:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}:host:disabled,:host[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}:host{gap:6px;padding-block:0;text-decoration:none}:host[aria-busy=true]{pointer-events:none}:host ::ng-deep svg{width:15px;height:15px;flex-shrink:0}:host .pi,:host ::ng-deep .pi{font-size:15px}:host([data-size=xs]){height:24px;padding-inline:var(--sp-2);font-size:var(--text-xs)}:host([data-size=sm]){height:28px;padding-inline:10px;font-size:var(--text-sm)}:host([data-size=md]){height:34px;padding-inline:var(--sp-3);font-size:var(--text-sm)}:host([data-variant=primary]){background:var(--ink);border-color:var(--ink);color:var(--on-ink)}:host([data-variant=primary]):hover{background:var(--ink-hover)}:host([data-variant=secondary]){background:var(--bg-2);border-color:var(--line);color:var(--ink-2)}:host([data-variant=secondary]):hover{background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}:host([data-variant=ghost]){background:transparent;color:var(--ink-2)}:host([data-variant=ghost]):hover{background:var(--bg-3);color:var(--ink)}:host([data-variant=danger]){background:transparent;border-color:var(--danger-line);color:var(--danger)}:host([data-variant=danger]):hover{background:var(--danger-bg)}:host([data-variant=danger-fill]){background:var(--danger);border-color:transparent;color:var(--ink-inverse)}:host([data-variant=danger-fill]):hover{filter:brightness(1.05)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22179
22204
  }
22180
22205
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyButtonComponent, decorators: [{
22181
22206
  type: Component,
@@ -22189,7 +22214,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
22189
22214
  <i class="pi pi-spin pi-spinner" aria-hidden="true"></i>
22190
22215
  }
22191
22216
  <ng-content />
22192
- `, styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);font-family:inherit;font-size:var(--text-base);font-weight:var(--fw-medium);border-radius:var(--r-md);border:1px solid transparent;cursor:pointer;transition:background var(--t-state),border-color var(--t-state),color var(--t-state),box-shadow var(--t-state),filter var(--t-state)}:host:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host:disabled,:host[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}:host{gap:6px;padding-block:0;text-decoration:none}:host[aria-busy=true]{pointer-events:none}:host ::ng-deep svg{width:15px;height:15px;flex-shrink:0}:host .pi,:host ::ng-deep .pi{font-size:15px}:host([data-size=xs]){height:24px;padding-inline:var(--sp-2);font-size:var(--text-xs)}:host([data-size=sm]){height:28px;padding-inline:10px;font-size:var(--text-sm)}:host([data-size=md]){height:34px;padding-inline:var(--sp-3);font-size:var(--text-sm)}:host([data-variant=primary]){background:var(--ink);border-color:var(--ink);color:var(--on-ink)}:host([data-variant=primary]):hover{background:var(--ink-hover)}:host([data-variant=secondary]){background:var(--bg-2);border-color:var(--line);color:var(--ink-2)}:host([data-variant=secondary]):hover{background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}:host([data-variant=ghost]){background:transparent;color:var(--ink-2)}:host([data-variant=ghost]):hover{background:var(--bg-3);color:var(--ink)}:host([data-variant=danger]){background:transparent;border-color:var(--danger-line);color:var(--danger)}:host([data-variant=danger]):hover{background:var(--danger-bg)}:host([data-variant=danger-fill]){background:var(--danger);border-color:transparent;color:var(--ink-inverse)}:host([data-variant=danger-fill]):hover{filter:brightness(1.05)}\n"] }]
22217
+ `, styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);font-family:inherit;font-size:var(--text-base);font-weight:var(--fw-medium);border-radius:var(--r-md);border:1px solid transparent;cursor:pointer;transition:background var(--t-state),border-color var(--t-state),color var(--t-state),box-shadow var(--t-state),filter var(--t-state)}:host:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}:host:disabled,:host[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}:host{gap:6px;padding-block:0;text-decoration:none}:host[aria-busy=true]{pointer-events:none}:host ::ng-deep svg{width:15px;height:15px;flex-shrink:0}:host .pi,:host ::ng-deep .pi{font-size:15px}:host([data-size=xs]){height:24px;padding-inline:var(--sp-2);font-size:var(--text-xs)}:host([data-size=sm]){height:28px;padding-inline:10px;font-size:var(--text-sm)}:host([data-size=md]){height:34px;padding-inline:var(--sp-3);font-size:var(--text-sm)}:host([data-variant=primary]){background:var(--ink);border-color:var(--ink);color:var(--on-ink)}:host([data-variant=primary]):hover{background:var(--ink-hover)}:host([data-variant=secondary]){background:var(--bg-2);border-color:var(--line);color:var(--ink-2)}:host([data-variant=secondary]):hover{background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}:host([data-variant=ghost]){background:transparent;color:var(--ink-2)}:host([data-variant=ghost]):hover{background:var(--bg-3);color:var(--ink)}:host([data-variant=danger]){background:transparent;border-color:var(--danger-line);color:var(--danger)}:host([data-variant=danger]):hover{background:var(--danger-bg)}:host([data-variant=danger-fill]){background:var(--danger);border-color:transparent;color:var(--ink-inverse)}:host([data-variant=danger-fill]):hover{filter:brightness(1.05)}\n"] }]
22193
22218
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
22194
22219
  /**
22195
22220
  * Circular 34px icon-only button (ported from the legacy global
@@ -22235,14 +22260,14 @@ class FlyIconButtonComponent {
22235
22260
  });
22236
22261
  }
22237
22262
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyIconButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
22238
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.19", type: FlyIconButtonComponent, isStandalone: true, selector: "button[fly-icon-button]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, tooltipKey: { classPropertyName: "tooltipKey", publicName: "tooltipKey", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variant": "variant()", "class.on": "active()" } }, hostDirectives: [{ directive: FlyTooltipDirective }], ngImport: i0, template: '<ng-content />', isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;flex-shrink:0;padding:0;border-radius:50%;background:var(--bg-2);border:1px solid var(--line);color:var(--ink-2);cursor:pointer;font-family:inherit;transition:background var(--t-state),border-color var(--t-state),color var(--t-state)}:host:hover{background:var(--bg-3);color:var(--ink);border-color:var(--line-2)}:host:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host:disabled{opacity:.5;cursor:not-allowed}:host ::ng-deep svg{width:16px;height:16px}:host .pi,:host ::ng-deep .pi{font-size:16px}:host(.on){background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}:host([data-variant=primary]){background:var(--grad);border:0;color:var(--ink-inverse);box-shadow:var(--shadow-raised)}:host([data-variant=primary]):hover{background:var(--grad);border:0;color:var(--ink-inverse);filter:brightness(1.05);box-shadow:var(--shadow-accent)}:host([data-variant=danger]){color:var(--danger)}:host([data-variant=danger]):hover{background:var(--danger-bg);border-color:var(--danger-line);color:var(--danger)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22263
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.19", type: FlyIconButtonComponent, isStandalone: true, selector: "button[fly-icon-button]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, tooltipKey: { classPropertyName: "tooltipKey", publicName: "tooltipKey", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variant": "variant()", "class.on": "active()" } }, hostDirectives: [{ directive: FlyTooltipDirective }], ngImport: i0, template: '<ng-content />', isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;flex-shrink:0;padding:0;border-radius:50%;background:var(--bg-2);border:1px solid var(--line);color:var(--ink-2);cursor:pointer;font-family:inherit;transition:background var(--t-state),border-color var(--t-state),color var(--t-state)}:host:hover{background:var(--bg-3);color:var(--ink);border-color:var(--line-2)}:host:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}:host:disabled{opacity:.5;cursor:not-allowed}:host ::ng-deep svg{width:16px;height:16px}:host .pi,:host ::ng-deep .pi{font-size:16px}:host(.on){background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}:host([data-variant=primary]){background:var(--grad);border:0;color:var(--ink-inverse);box-shadow:var(--shadow-raised)}:host([data-variant=primary]):hover{background:var(--grad);border:0;color:var(--ink-inverse);filter:brightness(1.05);box-shadow:var(--shadow-accent)}:host([data-variant=danger]){color:var(--danger)}:host([data-variant=danger]):hover{background:var(--danger-bg);border-color:var(--danger-line);color:var(--danger)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22239
22264
  }
22240
22265
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyIconButtonComponent, decorators: [{
22241
22266
  type: Component,
22242
22267
  args: [{ selector: 'button[fly-icon-button]', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [FlyTooltipDirective], host: {
22243
22268
  '[attr.data-variant]': 'variant()',
22244
22269
  '[class.on]': 'active()',
22245
- }, template: '<ng-content />', styles: [":host{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;flex-shrink:0;padding:0;border-radius:50%;background:var(--bg-2);border:1px solid var(--line);color:var(--ink-2);cursor:pointer;font-family:inherit;transition:background var(--t-state),border-color var(--t-state),color var(--t-state)}:host:hover{background:var(--bg-3);color:var(--ink);border-color:var(--line-2)}:host:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host:disabled{opacity:.5;cursor:not-allowed}:host ::ng-deep svg{width:16px;height:16px}:host .pi,:host ::ng-deep .pi{font-size:16px}:host(.on){background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}:host([data-variant=primary]){background:var(--grad);border:0;color:var(--ink-inverse);box-shadow:var(--shadow-raised)}:host([data-variant=primary]):hover{background:var(--grad);border:0;color:var(--ink-inverse);filter:brightness(1.05);box-shadow:var(--shadow-accent)}:host([data-variant=danger]){color:var(--danger)}:host([data-variant=danger]):hover{background:var(--danger-bg);border-color:var(--danger-line);color:var(--danger)}\n"] }]
22270
+ }, template: '<ng-content />', styles: [":host{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;flex-shrink:0;padding:0;border-radius:50%;background:var(--bg-2);border:1px solid var(--line);color:var(--ink-2);cursor:pointer;font-family:inherit;transition:background var(--t-state),border-color var(--t-state),color var(--t-state)}:host:hover{background:var(--bg-3);color:var(--ink);border-color:var(--line-2)}:host:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}:host:disabled{opacity:.5;cursor:not-allowed}:host ::ng-deep svg{width:16px;height:16px}:host .pi,:host ::ng-deep .pi{font-size:16px}:host(.on){background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}:host([data-variant=primary]){background:var(--grad);border:0;color:var(--ink-inverse);box-shadow:var(--shadow-raised)}:host([data-variant=primary]):hover{background:var(--grad);border:0;color:var(--ink-inverse);filter:brightness(1.05);box-shadow:var(--shadow-accent)}:host([data-variant=danger]){color:var(--danger)}:host([data-variant=danger]):hover{background:var(--danger-bg);border-color:var(--danger-line);color:var(--danger)}\n"] }]
22246
22271
  }], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], tooltipKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipKey", required: false }] }] } });
22247
22272
 
22248
22273
  /**
@@ -22325,7 +22350,7 @@ class FlyStateMessageComponent {
22325
22350
  </button>
22326
22351
  }
22327
22352
  <ng-content />
22328
- `, isInline: true, styles: [":host{display:flex;flex-direction:column;align-items:center;gap:var(--sp-3);padding:48px;color:var(--ink-3);font-size:var(--text-lg)}.msg__icon{font-size:var(--text-lg)}.msg__text{margin:0}:host([data-kind=empty]){padding:56px 24px;gap:11px}:host([data-kind=empty]) .msg__icon{display:grid;place-items:center;inline-size:46px;block-size:46px;border-radius:16px;background:var(--fill-tertiary);border:1px solid var(--surface-border);color:var(--label-secondary);font-size:21px}:host([data-kind=empty]) .msg__text{font:600 14px/1.3 var(--font-sans);color:var(--label-primary)}.msg__note{margin:0;max-inline-size:320px;font:400 12.5px/1.5 var(--font-sans);color:var(--label-secondary);text-wrap:pretty}:host([data-kind=success]) .msg__icon{color:var(--success)}:host([data-kind=warning]) .msg__icon{color:var(--warning)}:host([data-kind=error]){flex-flow:row wrap;justify-content:flex-start;padding:var(--sp-3) var(--sp-4);margin-block-start:var(--sp-3);border-radius:var(--r-lg);background:var(--danger-bg);border:1px solid var(--danger-line);color:var(--ink);font-size:var(--text-base)}:host([data-kind=error]) .msg__icon{color:var(--danger)}.msg__retry{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);font-family:inherit;font-size:var(--text-base);font-weight:var(--fw-medium);border-radius:var(--r-md);border:1px solid transparent;cursor:pointer;transition:background var(--t-state),border-color var(--t-state),color var(--t-state),box-shadow var(--t-state),filter var(--t-state)}.msg__retry:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.msg__retry:disabled,.msg__retry[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}.msg__retry{height:28px;padding-inline:var(--sp-3);font-size:var(--text-sm);background:var(--bg-2);border-color:var(--line);color:var(--ink-2)}.msg__retry:hover{background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22353
+ `, isInline: true, styles: [":host{display:flex;flex-direction:column;align-items:center;gap:var(--sp-3);padding:48px;color:var(--ink-3);font-size:var(--text-lg)}.msg__icon{font-size:var(--text-lg)}.msg__text{margin:0}:host([data-kind=empty]){padding:56px 24px;gap:11px}:host([data-kind=empty]) .msg__icon{display:grid;place-items:center;inline-size:46px;block-size:46px;border-radius:16px;background:var(--fill-tertiary);border:1px solid var(--surface-border);color:var(--label-secondary);font-size:21px}:host([data-kind=empty]) .msg__text{font:600 14px/1.3 var(--font-sans);color:var(--label-primary)}.msg__note{margin:0;max-inline-size:320px;font:400 12.5px/1.5 var(--font-sans);color:var(--label-secondary);text-wrap:pretty}:host([data-kind=success]) .msg__icon{color:var(--success)}:host([data-kind=warning]) .msg__icon{color:var(--warning)}:host([data-kind=error]){flex-flow:row wrap;justify-content:flex-start;padding:var(--sp-3) var(--sp-4);margin-block-start:var(--sp-3);border-radius:var(--r-lg);background:var(--danger-bg);border:1px solid var(--danger-line);color:var(--ink);font-size:var(--text-base)}:host([data-kind=error]) .msg__icon{color:var(--danger)}.msg__retry{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);font-family:inherit;font-size:var(--text-base);font-weight:var(--fw-medium);border-radius:var(--r-md);border:1px solid transparent;cursor:pointer;transition:background var(--t-state),border-color var(--t-state),color var(--t-state),box-shadow var(--t-state),filter var(--t-state)}.msg__retry:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.msg__retry:disabled,.msg__retry[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}.msg__retry{height:28px;padding-inline:var(--sp-3);font-size:var(--text-sm);background:var(--bg-2);border-color:var(--line);color:var(--ink-2)}.msg__retry:hover{background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22329
22354
  }
22330
22355
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyStateMessageComponent, decorators: [{
22331
22356
  type: Component,
@@ -22347,7 +22372,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
22347
22372
  </button>
22348
22373
  }
22349
22374
  <ng-content />
22350
- `, styles: [":host{display:flex;flex-direction:column;align-items:center;gap:var(--sp-3);padding:48px;color:var(--ink-3);font-size:var(--text-lg)}.msg__icon{font-size:var(--text-lg)}.msg__text{margin:0}:host([data-kind=empty]){padding:56px 24px;gap:11px}:host([data-kind=empty]) .msg__icon{display:grid;place-items:center;inline-size:46px;block-size:46px;border-radius:16px;background:var(--fill-tertiary);border:1px solid var(--surface-border);color:var(--label-secondary);font-size:21px}:host([data-kind=empty]) .msg__text{font:600 14px/1.3 var(--font-sans);color:var(--label-primary)}.msg__note{margin:0;max-inline-size:320px;font:400 12.5px/1.5 var(--font-sans);color:var(--label-secondary);text-wrap:pretty}:host([data-kind=success]) .msg__icon{color:var(--success)}:host([data-kind=warning]) .msg__icon{color:var(--warning)}:host([data-kind=error]){flex-flow:row wrap;justify-content:flex-start;padding:var(--sp-3) var(--sp-4);margin-block-start:var(--sp-3);border-radius:var(--r-lg);background:var(--danger-bg);border:1px solid var(--danger-line);color:var(--ink);font-size:var(--text-base)}:host([data-kind=error]) .msg__icon{color:var(--danger)}.msg__retry{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);font-family:inherit;font-size:var(--text-base);font-weight:var(--fw-medium);border-radius:var(--r-md);border:1px solid transparent;cursor:pointer;transition:background var(--t-state),border-color var(--t-state),color var(--t-state),box-shadow var(--t-state),filter var(--t-state)}.msg__retry:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.msg__retry:disabled,.msg__retry[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}.msg__retry{height:28px;padding-inline:var(--sp-3);font-size:var(--text-sm);background:var(--bg-2);border-color:var(--line);color:var(--ink-2)}.msg__retry:hover{background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}\n"] }]
22375
+ `, styles: [":host{display:flex;flex-direction:column;align-items:center;gap:var(--sp-3);padding:48px;color:var(--ink-3);font-size:var(--text-lg)}.msg__icon{font-size:var(--text-lg)}.msg__text{margin:0}:host([data-kind=empty]){padding:56px 24px;gap:11px}:host([data-kind=empty]) .msg__icon{display:grid;place-items:center;inline-size:46px;block-size:46px;border-radius:16px;background:var(--fill-tertiary);border:1px solid var(--surface-border);color:var(--label-secondary);font-size:21px}:host([data-kind=empty]) .msg__text{font:600 14px/1.3 var(--font-sans);color:var(--label-primary)}.msg__note{margin:0;max-inline-size:320px;font:400 12.5px/1.5 var(--font-sans);color:var(--label-secondary);text-wrap:pretty}:host([data-kind=success]) .msg__icon{color:var(--success)}:host([data-kind=warning]) .msg__icon{color:var(--warning)}:host([data-kind=error]){flex-flow:row wrap;justify-content:flex-start;padding:var(--sp-3) var(--sp-4);margin-block-start:var(--sp-3);border-radius:var(--r-lg);background:var(--danger-bg);border:1px solid var(--danger-line);color:var(--ink);font-size:var(--text-base)}:host([data-kind=error]) .msg__icon{color:var(--danger)}.msg__retry{display:inline-flex;align-items:center;justify-content:center;gap:var(--sp-2);font-family:inherit;font-size:var(--text-base);font-weight:var(--fw-medium);border-radius:var(--r-md);border:1px solid transparent;cursor:pointer;transition:background var(--t-state),border-color var(--t-state),color var(--t-state),box-shadow var(--t-state),filter var(--t-state)}.msg__retry:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.msg__retry:disabled,.msg__retry[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}.msg__retry{height:28px;padding-inline:var(--sp-3);font-size:var(--text-sm);background:var(--bg-2);border-color:var(--line);color:var(--ink-2)}.msg__retry:hover{background:var(--bg-3);border-color:var(--line-2);color:var(--ink)}\n"] }]
22351
22376
  }], propDecorators: { kind: [{ type: i0.Input, args: [{ isSignal: true, alias: "kind", required: false }] }], messageKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageKey", required: false }] }], iconClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconClass", required: false }] }], noteKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "noteKey", required: false }] }], retryLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "retryLabelKey", required: false }] }], showRetry: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRetry", required: false }] }], retried: [{ type: i0.Output, args: ["retried"] }] } });
22352
22377
 
22353
22378
  /** Inline busy indicator — spinner glyph plus optional label. */
@@ -22634,11 +22659,11 @@ class FlyPaginationComponent {
22634
22659
  this.pageChange.emit(next);
22635
22660
  }
22636
22661
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyPaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
22637
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyPaginationComponent, isStandalone: true, selector: "fly-pagination", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: true, transformFunction: null }, totalPages: { classPropertyName: "totalPages", publicName: "totalPages", isSignal: true, isRequired: true, transformFunction: null }, rangeText: { classPropertyName: "rangeText", publicName: "rangeText", isSignal: true, isRequired: false, transformFunction: null }, showEdges: { classPropertyName: "showEdges", publicName: "showEdges", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange" }, ngImport: i0, template: "<nav class=\"pg\" [attr.aria-label]=\"'ui.pagination.label' | translate\">\r\n @if (rangeText(); as range) {\r\n <span class=\"pg__range\">{{ range }}</span>\r\n }\r\n <div class=\"pg__controls\">\r\n @if (showEdges()) {\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(1)\"\r\n [attr.aria-label]=\"'ui.pagination.first' | translate\"\r\n ><span class=\"pg__chev\" aria-hidden=\"true\">\u00AB</span></button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(page() - 1)\"\r\n [attr.aria-label]=\"'ui.pagination.previous' | translate\"\r\n >\r\n <svg class=\"pg__arrow\" data-arrow=\"prev\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"15 6 9 12 15 18\" />\r\n </svg>\r\n </button>\r\n <span class=\"pg__current\" aria-live=\"polite\">\r\n {{ 'ui.pagination.pageOf' | translate: { page: page(), total: totalPages() } }}\r\n </span>\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(page() + 1)\"\r\n [attr.aria-label]=\"'ui.pagination.next' | translate\"\r\n >\r\n <svg class=\"pg__arrow\" data-arrow=\"next\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n </button>\r\n @if (showEdges()) {\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(totalPages())\"\r\n [attr.aria-label]=\"'ui.pagination.last' | translate\"\r\n ><span class=\"pg__chev\" aria-hidden=\"true\">\u00BB</span></button>\r\n }\r\n </div>\r\n</nav>\r\n", styles: [".pg{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-block-start:var(--sp-4);font-size:var(--text-sm);color:var(--ink-3)}.pg__range{font-size:var(--text-sm);color:var(--ink-3);direction:ltr;unicode-bidi:isolate}.pg__range b{color:var(--ink);font-weight:var(--fw-medium)}.pg__controls{display:flex;align-items:center;gap:2px;margin-inline-start:auto;font-size:var(--text-sm)}.pg__btn{inline-size:26px;block-size:26px;padding:0;border:1px solid transparent;background:transparent;color:var(--ink-3);border-radius:50%;font-size:var(--text-sm);cursor:pointer;display:inline-grid;place-items:center;transition:background var(--t-state),color var(--t-state)}.pg__btn:hover:not(:disabled){background:var(--w06);color:var(--ink)}.pg__btn:disabled{color:var(--w2);cursor:default}.pg__btn:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.pg__arrow{inline-size:14px;block-size:14px}:host-context([dir=rtl]) .pg__arrow{transform:scaleX(-1)}.pg__current{font-size:var(--text-sm);font-weight:var(--fw-semibold);font-variant-numeric:tabular-nums;padding:0 var(--sp-3);background:var(--accent);border:1px solid transparent;border-radius:999px;color:var(--on-accent-fill);height:24px;display:inline-grid;place-items:center;direction:ltr;unicode-bidi:isolate}:host-context(.rtl) .pg__chev,:host-context([dir=rtl]) .pg__chev{display:inline-block;transform:scaleX(-1)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22662
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyPaginationComponent, isStandalone: true, selector: "fly-pagination", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: true, transformFunction: null }, totalPages: { classPropertyName: "totalPages", publicName: "totalPages", isSignal: true, isRequired: true, transformFunction: null }, rangeText: { classPropertyName: "rangeText", publicName: "rangeText", isSignal: true, isRequired: false, transformFunction: null }, showEdges: { classPropertyName: "showEdges", publicName: "showEdges", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange" }, ngImport: i0, template: "<nav class=\"pg\" [attr.aria-label]=\"'ui.pagination.label' | translate\">\r\n @if (rangeText(); as range) {\r\n <span class=\"pg__range\">{{ range }}</span>\r\n }\r\n <div class=\"pg__controls\">\r\n @if (showEdges()) {\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(1)\"\r\n [attr.aria-label]=\"'ui.pagination.first' | translate\"\r\n ><span class=\"pg__chev\" aria-hidden=\"true\">\u00AB</span></button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(page() - 1)\"\r\n [attr.aria-label]=\"'ui.pagination.previous' | translate\"\r\n >\r\n <svg class=\"pg__arrow\" data-arrow=\"prev\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"15 6 9 12 15 18\" />\r\n </svg>\r\n </button>\r\n <span class=\"pg__current\" aria-live=\"polite\">\r\n {{ 'ui.pagination.pageOf' | translate: { page: page(), total: totalPages() } }}\r\n </span>\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(page() + 1)\"\r\n [attr.aria-label]=\"'ui.pagination.next' | translate\"\r\n >\r\n <svg class=\"pg__arrow\" data-arrow=\"next\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n </button>\r\n @if (showEdges()) {\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(totalPages())\"\r\n [attr.aria-label]=\"'ui.pagination.last' | translate\"\r\n ><span class=\"pg__chev\" aria-hidden=\"true\">\u00BB</span></button>\r\n }\r\n </div>\r\n</nav>\r\n", styles: [".pg{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-block-start:var(--sp-4);font-size:var(--text-sm);color:var(--ink-3)}.pg__range{font-size:var(--text-sm);color:var(--ink-3);direction:ltr;unicode-bidi:isolate}.pg__range b{color:var(--ink);font-weight:var(--fw-medium)}.pg__controls{display:flex;align-items:center;gap:2px;margin-inline-start:auto;font-size:var(--text-sm)}.pg__btn{inline-size:26px;block-size:26px;padding:0;border:1px solid transparent;background:transparent;color:var(--ink-3);border-radius:50%;font-size:var(--text-sm);cursor:pointer;display:inline-grid;place-items:center;transition:background var(--t-state),color var(--t-state)}.pg__btn:hover:not(:disabled){background:var(--w06);color:var(--ink)}.pg__btn:disabled{color:var(--w2);cursor:default}.pg__btn:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.pg__arrow{inline-size:14px;block-size:14px}:host-context([dir=rtl]) .pg__arrow{transform:scaleX(-1)}.pg__current{font-size:var(--text-sm);font-weight:var(--fw-semibold);font-variant-numeric:tabular-nums;padding:0 var(--sp-3);background:var(--accent);border:1px solid transparent;border-radius:999px;color:var(--on-accent-fill);height:24px;display:inline-grid;place-items:center;direction:ltr;unicode-bidi:isolate}:host-context(.rtl) .pg__chev,:host-context([dir=rtl]) .pg__chev{display:inline-block;transform:scaleX(-1)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22638
22663
  }
22639
22664
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyPaginationComponent, decorators: [{
22640
22665
  type: Component,
22641
- args: [{ selector: 'fly-pagination', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav class=\"pg\" [attr.aria-label]=\"'ui.pagination.label' | translate\">\r\n @if (rangeText(); as range) {\r\n <span class=\"pg__range\">{{ range }}</span>\r\n }\r\n <div class=\"pg__controls\">\r\n @if (showEdges()) {\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(1)\"\r\n [attr.aria-label]=\"'ui.pagination.first' | translate\"\r\n ><span class=\"pg__chev\" aria-hidden=\"true\">\u00AB</span></button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(page() - 1)\"\r\n [attr.aria-label]=\"'ui.pagination.previous' | translate\"\r\n >\r\n <svg class=\"pg__arrow\" data-arrow=\"prev\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"15 6 9 12 15 18\" />\r\n </svg>\r\n </button>\r\n <span class=\"pg__current\" aria-live=\"polite\">\r\n {{ 'ui.pagination.pageOf' | translate: { page: page(), total: totalPages() } }}\r\n </span>\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(page() + 1)\"\r\n [attr.aria-label]=\"'ui.pagination.next' | translate\"\r\n >\r\n <svg class=\"pg__arrow\" data-arrow=\"next\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n </button>\r\n @if (showEdges()) {\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(totalPages())\"\r\n [attr.aria-label]=\"'ui.pagination.last' | translate\"\r\n ><span class=\"pg__chev\" aria-hidden=\"true\">\u00BB</span></button>\r\n }\r\n </div>\r\n</nav>\r\n", styles: [".pg{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-block-start:var(--sp-4);font-size:var(--text-sm);color:var(--ink-3)}.pg__range{font-size:var(--text-sm);color:var(--ink-3);direction:ltr;unicode-bidi:isolate}.pg__range b{color:var(--ink);font-weight:var(--fw-medium)}.pg__controls{display:flex;align-items:center;gap:2px;margin-inline-start:auto;font-size:var(--text-sm)}.pg__btn{inline-size:26px;block-size:26px;padding:0;border:1px solid transparent;background:transparent;color:var(--ink-3);border-radius:50%;font-size:var(--text-sm);cursor:pointer;display:inline-grid;place-items:center;transition:background var(--t-state),color var(--t-state)}.pg__btn:hover:not(:disabled){background:var(--w06);color:var(--ink)}.pg__btn:disabled{color:var(--w2);cursor:default}.pg__btn:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.pg__arrow{inline-size:14px;block-size:14px}:host-context([dir=rtl]) .pg__arrow{transform:scaleX(-1)}.pg__current{font-size:var(--text-sm);font-weight:var(--fw-semibold);font-variant-numeric:tabular-nums;padding:0 var(--sp-3);background:var(--accent);border:1px solid transparent;border-radius:999px;color:var(--on-accent-fill);height:24px;display:inline-grid;place-items:center;direction:ltr;unicode-bidi:isolate}:host-context(.rtl) .pg__chev,:host-context([dir=rtl]) .pg__chev{display:inline-block;transform:scaleX(-1)}\n"] }]
22666
+ args: [{ selector: 'fly-pagination', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav class=\"pg\" [attr.aria-label]=\"'ui.pagination.label' | translate\">\r\n @if (rangeText(); as range) {\r\n <span class=\"pg__range\">{{ range }}</span>\r\n }\r\n <div class=\"pg__controls\">\r\n @if (showEdges()) {\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(1)\"\r\n [attr.aria-label]=\"'ui.pagination.first' | translate\"\r\n ><span class=\"pg__chev\" aria-hidden=\"true\">\u00AB</span></button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(page() - 1)\"\r\n [attr.aria-label]=\"'ui.pagination.previous' | translate\"\r\n >\r\n <svg class=\"pg__arrow\" data-arrow=\"prev\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"15 6 9 12 15 18\" />\r\n </svg>\r\n </button>\r\n <span class=\"pg__current\" aria-live=\"polite\">\r\n {{ 'ui.pagination.pageOf' | translate: { page: page(), total: totalPages() } }}\r\n </span>\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(page() + 1)\"\r\n [attr.aria-label]=\"'ui.pagination.next' | translate\"\r\n >\r\n <svg class=\"pg__arrow\" data-arrow=\"next\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n </button>\r\n @if (showEdges()) {\r\n <button\r\n type=\"button\"\r\n class=\"pg__btn\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(totalPages())\"\r\n [attr.aria-label]=\"'ui.pagination.last' | translate\"\r\n ><span class=\"pg__chev\" aria-hidden=\"true\">\u00BB</span></button>\r\n }\r\n </div>\r\n</nav>\r\n", styles: [".pg{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-block-start:var(--sp-4);font-size:var(--text-sm);color:var(--ink-3)}.pg__range{font-size:var(--text-sm);color:var(--ink-3);direction:ltr;unicode-bidi:isolate}.pg__range b{color:var(--ink);font-weight:var(--fw-medium)}.pg__controls{display:flex;align-items:center;gap:2px;margin-inline-start:auto;font-size:var(--text-sm)}.pg__btn{inline-size:26px;block-size:26px;padding:0;border:1px solid transparent;background:transparent;color:var(--ink-3);border-radius:50%;font-size:var(--text-sm);cursor:pointer;display:inline-grid;place-items:center;transition:background var(--t-state),color var(--t-state)}.pg__btn:hover:not(:disabled){background:var(--w06);color:var(--ink)}.pg__btn:disabled{color:var(--w2);cursor:default}.pg__btn:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.pg__arrow{inline-size:14px;block-size:14px}:host-context([dir=rtl]) .pg__arrow{transform:scaleX(-1)}.pg__current{font-size:var(--text-sm);font-weight:var(--fw-semibold);font-variant-numeric:tabular-nums;padding:0 var(--sp-3);background:var(--accent);border:1px solid transparent;border-radius:999px;color:var(--on-accent-fill);height:24px;display:inline-grid;place-items:center;direction:ltr;unicode-bidi:isolate}:host-context(.rtl) .pg__chev,:host-context([dir=rtl]) .pg__chev{display:inline-block;transform:scaleX(-1)}\n"] }]
22642
22667
  }], propDecorators: { page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: true }] }], totalPages: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalPages", required: true }] }], rangeText: [{ type: i0.Input, args: [{ isSignal: true, alias: "rangeText", required: false }] }], showEdges: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEdges", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }] } });
22643
22668
 
22644
22669
  /** 0-indexed sibling of `pagination.logic.ts` — see `pager.component.ts` for why. */
@@ -22682,11 +22707,11 @@ class FlyPagerComponent {
22682
22707
  this.goToPage.emit(next);
22683
22708
  }
22684
22709
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyPagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
22685
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyPagerComponent, isStandalone: true, selector: "fly-pager", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: true, transformFunction: null }, totalPages: { classPropertyName: "totalPages", publicName: "totalPages", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { goToPage: "goToPage" }, ngImport: i0, template: "@if (totalPages() > 1) {\r\n <nav class=\"pgr\" [attr.aria-label]=\"'ui.pagination.label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"pgr__arrow\"\r\n data-arrow=\"back\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(page() - 1)\"\r\n [attr.aria-label]=\"'ui.pager.previous' | translate\"\r\n >\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path d=\"M14.8 5.2L8 12l6.8 6.8\" />\r\n </svg>\r\n </button>\r\n @for (p of pages(); track p) {\r\n <button\r\n type=\"button\"\r\n class=\"pgr__page\"\r\n [class.pgr__page--current]=\"p === page()\"\r\n [attr.aria-current]=\"p === page() ? 'page' : null\"\r\n (click)=\"goTo(p)\"\r\n [attr.aria-label]=\"'ui.pager.page' | translate: { page: p + 1 }\"\r\n >{{ p + 1 }}</button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"pgr__arrow\"\r\n data-arrow=\"forward\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(page() + 1)\"\r\n [attr.aria-label]=\"'ui.pager.next' | translate\"\r\n >\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path d=\"M9.2 5.2L16 12l-6.8 6.8\" />\r\n </svg>\r\n </button>\r\n </nav>\r\n}\r\n", styles: [".pgr{flex:none;display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:4px;padding:14px 8px;background:var(--w03);border:1px solid var(--w08);border-top:0}.pgr__arrow{flex:none;inline-size:26px;block-size:26px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--w6);cursor:pointer;display:grid;place-items:center;transition:background var(--t-state),color var(--t-state)}.pgr__arrow svg{inline-size:14px;block-size:14px}.pgr__arrow:hover:not(:disabled){background:var(--w06)}.pgr__arrow:disabled{color:var(--w2);cursor:default}.pgr__arrow:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host-context([dir=rtl]) .pgr__arrow[data-arrow] svg{transform:scaleX(-1)}.pgr__page{flex:none;min-inline-size:24px;block-size:24px;padding:0 3px;border:0;border-radius:50%;background:transparent;color:var(--w45);cursor:pointer;font-family:inherit;font-size:12px;font-weight:600;line-height:1;font-variant-numeric:tabular-nums;transition:background var(--t-state),color var(--t-state)}.pgr__page:hover{background:var(--w08)}.pgr__page--current{background:var(--accent);color:var(--on-accent-fill)}.pgr__page--current:hover{background:var(--accent)}.pgr__page:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22710
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyPagerComponent, isStandalone: true, selector: "fly-pager", inputs: { page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: true, transformFunction: null }, totalPages: { classPropertyName: "totalPages", publicName: "totalPages", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { goToPage: "goToPage" }, ngImport: i0, template: "@if (totalPages() > 1) {\r\n <nav class=\"pgr\" [attr.aria-label]=\"'ui.pagination.label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"pgr__arrow\"\r\n data-arrow=\"back\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(page() - 1)\"\r\n [attr.aria-label]=\"'ui.pager.previous' | translate\"\r\n >\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path d=\"M14.8 5.2L8 12l6.8 6.8\" />\r\n </svg>\r\n </button>\r\n @for (p of pages(); track p) {\r\n <button\r\n type=\"button\"\r\n class=\"pgr__page\"\r\n [class.pgr__page--current]=\"p === page()\"\r\n [attr.aria-current]=\"p === page() ? 'page' : null\"\r\n (click)=\"goTo(p)\"\r\n [attr.aria-label]=\"'ui.pager.page' | translate: { page: p + 1 }\"\r\n >{{ p + 1 }}</button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"pgr__arrow\"\r\n data-arrow=\"forward\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(page() + 1)\"\r\n [attr.aria-label]=\"'ui.pager.next' | translate\"\r\n >\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path d=\"M9.2 5.2L16 12l-6.8 6.8\" />\r\n </svg>\r\n </button>\r\n </nav>\r\n}\r\n", styles: [".pgr{flex:none;display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:4px;padding:14px 8px;background:var(--w03);border:1px solid var(--w08);border-top:0}.pgr__arrow{flex:none;inline-size:26px;block-size:26px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--w6);cursor:pointer;display:grid;place-items:center;transition:background var(--t-state),color var(--t-state)}.pgr__arrow svg{inline-size:14px;block-size:14px}.pgr__arrow:hover:not(:disabled){background:var(--w06)}.pgr__arrow:disabled{color:var(--w2);cursor:default}.pgr__arrow:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}:host-context([dir=rtl]) .pgr__arrow[data-arrow] svg{transform:scaleX(-1)}.pgr__page{flex:none;min-inline-size:24px;block-size:24px;padding:0 3px;border:0;border-radius:50%;background:transparent;color:var(--w45);cursor:pointer;font-family:inherit;font-size:12px;font-weight:600;line-height:1;font-variant-numeric:tabular-nums;transition:background var(--t-state),color var(--t-state)}.pgr__page:hover{background:var(--w08)}.pgr__page--current{background:var(--accent);color:var(--on-accent-fill)}.pgr__page--current:hover{background:var(--accent)}.pgr__page:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22686
22711
  }
22687
22712
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyPagerComponent, decorators: [{
22688
22713
  type: Component,
22689
- args: [{ selector: 'fly-pager', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (totalPages() > 1) {\r\n <nav class=\"pgr\" [attr.aria-label]=\"'ui.pagination.label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"pgr__arrow\"\r\n data-arrow=\"back\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(page() - 1)\"\r\n [attr.aria-label]=\"'ui.pager.previous' | translate\"\r\n >\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path d=\"M14.8 5.2L8 12l6.8 6.8\" />\r\n </svg>\r\n </button>\r\n @for (p of pages(); track p) {\r\n <button\r\n type=\"button\"\r\n class=\"pgr__page\"\r\n [class.pgr__page--current]=\"p === page()\"\r\n [attr.aria-current]=\"p === page() ? 'page' : null\"\r\n (click)=\"goTo(p)\"\r\n [attr.aria-label]=\"'ui.pager.page' | translate: { page: p + 1 }\"\r\n >{{ p + 1 }}</button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"pgr__arrow\"\r\n data-arrow=\"forward\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(page() + 1)\"\r\n [attr.aria-label]=\"'ui.pager.next' | translate\"\r\n >\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path d=\"M9.2 5.2L16 12l-6.8 6.8\" />\r\n </svg>\r\n </button>\r\n </nav>\r\n}\r\n", styles: [".pgr{flex:none;display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:4px;padding:14px 8px;background:var(--w03);border:1px solid var(--w08);border-top:0}.pgr__arrow{flex:none;inline-size:26px;block-size:26px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--w6);cursor:pointer;display:grid;place-items:center;transition:background var(--t-state),color var(--t-state)}.pgr__arrow svg{inline-size:14px;block-size:14px}.pgr__arrow:hover:not(:disabled){background:var(--w06)}.pgr__arrow:disabled{color:var(--w2);cursor:default}.pgr__arrow:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host-context([dir=rtl]) .pgr__arrow[data-arrow] svg{transform:scaleX(-1)}.pgr__page{flex:none;min-inline-size:24px;block-size:24px;padding:0 3px;border:0;border-radius:50%;background:transparent;color:var(--w45);cursor:pointer;font-family:inherit;font-size:12px;font-weight:600;line-height:1;font-variant-numeric:tabular-nums;transition:background var(--t-state),color var(--t-state)}.pgr__page:hover{background:var(--w08)}.pgr__page--current{background:var(--accent);color:var(--on-accent-fill)}.pgr__page--current:hover{background:var(--accent)}.pgr__page:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}\n"] }]
22714
+ args: [{ selector: 'fly-pager', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (totalPages() > 1) {\r\n <nav class=\"pgr\" [attr.aria-label]=\"'ui.pagination.label' | translate\">\r\n <button\r\n type=\"button\"\r\n class=\"pgr__arrow\"\r\n data-arrow=\"back\"\r\n [disabled]=\"!prevEnabled()\"\r\n (click)=\"goTo(page() - 1)\"\r\n [attr.aria-label]=\"'ui.pager.previous' | translate\"\r\n >\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path d=\"M14.8 5.2L8 12l6.8 6.8\" />\r\n </svg>\r\n </button>\r\n @for (p of pages(); track p) {\r\n <button\r\n type=\"button\"\r\n class=\"pgr__page\"\r\n [class.pgr__page--current]=\"p === page()\"\r\n [attr.aria-current]=\"p === page() ? 'page' : null\"\r\n (click)=\"goTo(p)\"\r\n [attr.aria-label]=\"'ui.pager.page' | translate: { page: p + 1 }\"\r\n >{{ p + 1 }}</button>\r\n }\r\n <button\r\n type=\"button\"\r\n class=\"pgr__arrow\"\r\n data-arrow=\"forward\"\r\n [disabled]=\"!nextEnabled()\"\r\n (click)=\"goTo(page() + 1)\"\r\n [attr.aria-label]=\"'ui.pager.next' | translate\"\r\n >\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path d=\"M9.2 5.2L16 12l-6.8 6.8\" />\r\n </svg>\r\n </button>\r\n </nav>\r\n}\r\n", styles: [".pgr{flex:none;display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:4px;padding:14px 8px;background:var(--w03);border:1px solid var(--w08);border-top:0}.pgr__arrow{flex:none;inline-size:26px;block-size:26px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--w6);cursor:pointer;display:grid;place-items:center;transition:background var(--t-state),color var(--t-state)}.pgr__arrow svg{inline-size:14px;block-size:14px}.pgr__arrow:hover:not(:disabled){background:var(--w06)}.pgr__arrow:disabled{color:var(--w2);cursor:default}.pgr__arrow:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}:host-context([dir=rtl]) .pgr__arrow[data-arrow] svg{transform:scaleX(-1)}.pgr__page{flex:none;min-inline-size:24px;block-size:24px;padding:0 3px;border:0;border-radius:50%;background:transparent;color:var(--w45);cursor:pointer;font-family:inherit;font-size:12px;font-weight:600;line-height:1;font-variant-numeric:tabular-nums;transition:background var(--t-state),color var(--t-state)}.pgr__page:hover{background:var(--w08)}.pgr__page--current{background:var(--accent);color:var(--on-accent-fill)}.pgr__page--current:hover{background:var(--accent)}.pgr__page:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}\n"] }]
22690
22715
  }], propDecorators: { page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: true }] }], totalPages: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalPages", required: true }] }], goToPage: [{ type: i0.Output, args: ["goToPage"] }] } });
22691
22716
 
22692
22717
  /**
@@ -22791,7 +22816,7 @@ class FlyCardComponent {
22791
22816
  <ng-content select="fly-card-status" />
22792
22817
  <ng-content select="fly-card-footer" />
22793
22818
  <ng-content select="fly-card-actions" />
22794
- `, isInline: true, styles: ["@charset \"UTF-8\";:host{background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);box-shadow:var(--shadow-card);padding:var(--sp-4);position:relative;min-width:0}:host(.is-interactive){cursor:pointer;transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive):hover{border-color:var(--line-2);box-shadow:var(--shadow-card)}:host(.is-interactive):focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host(.is-interactive.is-lift){transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive.is-lift):hover{transform:translateY(-2px);box-shadow:var(--shadow-filter)}:host([aria-disabled=true]){opacity:.5;cursor:default}:host([data-layout=column]){display:grid;grid-template:\"status actions\" auto \"media media\" auto \"main main\" 1fr \"footer footer\" auto/1fr auto;align-items:start;column-gap:var(--sp-2);animation:riseIn .34s var(--nova-ease-micro) both}:host([data-layout=column]):nth-child(1){animation-delay:0ms}:host([data-layout=column]):nth-child(2){animation-delay:55ms}:host([data-layout=column]):nth-child(3){animation-delay:.11s}:host([data-layout=column]):nth-child(4){animation-delay:165ms}:host([data-layout=column]):nth-child(5){animation-delay:.22s}:host([data-layout=column]):nth-child(6){animation-delay:275ms}:host([data-layout=column]):nth-child(7){animation-delay:.33s}:host([data-layout=column]):nth-child(8){animation-delay:385ms}:host([data-layout=column]):nth-child(9){animation-delay:.44s}:host([data-layout=column]):nth-child(10){animation-delay:495ms}:host([data-layout=column]):nth-child(11){animation-delay:.55s}:host([data-layout=column]):nth-child(12){animation-delay:605ms}:host([data-layout=column]):nth-child(n+13){animation-delay:605ms}:host([data-layout=row]){display:flex;align-items:flex-start;gap:12px;padding:14px 12px;border-color:transparent;background:transparent;box-shadow:none;animation:itemIn .4s var(--nova-ease-micro) both}:host([data-layout=row]):nth-child(1){animation-delay:0ms}:host([data-layout=row]):nth-child(2){animation-delay:40ms}:host([data-layout=row]):nth-child(3){animation-delay:80ms}:host([data-layout=row]):nth-child(4){animation-delay:.12s}:host([data-layout=row]):nth-child(5){animation-delay:.16s}:host([data-layout=row]):nth-child(6){animation-delay:.2s}:host([data-layout=row]):nth-child(7){animation-delay:.24s}:host([data-layout=row]):nth-child(8){animation-delay:.28s}:host([data-layout=row]):nth-child(9){animation-delay:.32s}:host([data-layout=row]):nth-child(10){animation-delay:.36s}:host([data-layout=row]):nth-child(11){animation-delay:.4s}:host([data-layout=row]):nth-child(12){animation-delay:.44s}:host([data-layout=row]):nth-child(n+13){animation-delay:.44s}:host([data-layout=row]){transition:padding-inline-start var(--t-overlay),background var(--t-state),border-color var(--t-state),box-shadow var(--t-state)}:host([data-layout=row]):hover{background:var(--w04)}:host([data-layout=row]):not(.is-selectable,:first-child):before{content:\"\";position:absolute;inset-block-start:0;inset-inline:12px;block-size:1px;background:var(--w07)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:48px}:host([data-layout=row].is-selectable){padding:13px 14px;border:1px solid var(--w07);background:var(--w04)}:host([data-layout=row].is-selectable):hover{background:var(--w06);border-color:var(--w14)}:host([data-layout=row].is-selected){background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=row].is-selected):hover{background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=column].is-selected){background:color-mix(in srgb,var(--accent-soft) 65%,var(--bg-2));border-color:color-mix(in srgb,var(--accent) 45%,transparent)}.card__check{position:absolute;inset-inline-start:14px;inset-block-start:15px;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity var(--t-state)}.card__check input{position:absolute;opacity:0;width:14px;height:14px;margin:0;cursor:pointer}:host(:hover) .card__check,:host(:focus-visible) .card__check,:host(:has(:focus-visible)) .card__check,:host(.is-selected) .card__check{opacity:1;pointer-events:auto}.card__check-box{position:relative;display:inline-block;width:14px;height:14px;border:1.5px solid var(--ink-4);border-radius:4px;background:var(--bg-2);transition:background var(--t-state),border-color var(--t-state);flex-shrink:0}.card__check-box:after{content:\"\";position:absolute;inset:0;margin:auto;width:4px;height:7px;border:solid var(--ink-inverse);border-width:0 1.6px 1.6px 0;transform:translateY(-1px) rotate(45deg);opacity:0;transition:opacity var(--t-state)}input:checked+.card__check-box{background:var(--accent);border-color:var(--accent)}input:checked+.card__check-box:after{opacity:1}.card__main{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0;flex:1}:host([data-layout=column]) .card__main{grid-area:main;gap:var(--sp-3);height:100%}:host([data-layout=row]) .card__main{font-size:13px;line-height:1.5;color:var(--w55);text-wrap:pretty}:host([data-layout=column]) .card__main ::ng-deep fly-card-body{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-meta{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-body~fly-card-meta{margin-block-start:0}:host ::ng-deep fly-card-media{display:block;flex-shrink:0}:host([data-layout=column]) ::ng-deep fly-card-media{grid-area:media;margin-block-end:var(--sp-3)}:host ::ng-deep fly-card-title{display:block;font-size:15px;color:var(--ink);letter-spacing:-.01em;overflow:hidden;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-title{font-weight:var(--fw-medium);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}:host([data-layout=row]) ::ng-deep fly-card-title{font-weight:var(--fw-semibold);font-size:14px;line-height:1.35;text-wrap:pretty;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:normal;transition:font-size var(--t-state)}:host([data-density=compact]) ::ng-deep fly-card-title{font-size:12.5px}:host([data-density=compact]) ::ng-deep fly-card-status{display:none}:host ::ng-deep fly-card-meta{display:flex;flex-wrap:wrap;gap:var(--sp-1);min-width:0}:host([data-layout=row]) ::ng-deep fly-card-meta{align-items:center;gap:8px;font-size:11.5px;color:var(--w55)}:host([data-layout=row]) ::ng-deep fly-card-meta>span{display:inline-flex;align-items:center}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child){position:relative;padding-inline-start:8px}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child):before{content:\"\";position:absolute;inset-inline-start:0;inset-block:2px;inline-size:1px;background:var(--w12)}:host ::ng-deep fly-card-meta dl{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:var(--sp-2);width:100%;margin:0}:host ::ng-deep fly-card-meta dl>div{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}:host ::ng-deep fly-card-meta dl dt{margin:0;font-size:10px;font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-4)}:host ::ng-deep fly-card-meta dl dd{margin:0;font-size:var(--text-sm);color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep fly-card-status{display:inline-flex;align-items:center;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-status{grid-area:status;place-self:center start;min-height:24px;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-status{flex-shrink:0;align-self:center}:host ::ng-deep fly-card-body{display:block;min-width:0}:host ::ng-deep fly-card-footer{display:flex;align-items:center;gap:6px}:host([data-layout=column]) ::ng-deep fly-card-footer{grid-area:footer;justify-content:space-between;margin-block-start:var(--sp-3);padding-block-start:10px;border-block-start:1px solid var(--line-3);font-size:10.5px;font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4)}:host([data-layout=row]) ::ng-deep fly-card-footer{flex-shrink:0;align-self:center;font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink-3);font-variant-numeric:tabular-nums}:host ::ng-deep fly-card-actions{display:inline-flex;align-items:center;gap:2px}:host([data-layout=column]) ::ng-deep fly-card-actions{grid-area:actions;place-self:center end;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-actions{flex-shrink:0;align-self:center}@media(width<=640px){:host([data-layout=row]){padding:14px var(--sp-4);gap:var(--sp-3)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:44px}.card__check{inset-inline-start:14px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22819
+ `, isInline: true, styles: ["@charset \"UTF-8\";:host{background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);box-shadow:var(--shadow-card);padding:var(--sp-4);position:relative;min-width:0}:host(.is-interactive){cursor:pointer;transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive):hover{border-color:var(--line-2);box-shadow:var(--shadow-card)}:host(.is-interactive):focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}:host(.is-interactive.is-lift){transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive.is-lift):hover{transform:translateY(-2px);box-shadow:var(--shadow-filter)}:host([aria-disabled=true]){opacity:.5;cursor:default}:host([data-layout=column]){display:grid;grid-template:\"status actions\" auto \"media media\" auto \"main main\" 1fr \"footer footer\" auto/1fr auto;align-items:start;column-gap:var(--sp-2);animation:riseIn .34s var(--nova-ease-micro) both}:host([data-layout=column]):nth-child(1){animation-delay:0ms}:host([data-layout=column]):nth-child(2){animation-delay:55ms}:host([data-layout=column]):nth-child(3){animation-delay:.11s}:host([data-layout=column]):nth-child(4){animation-delay:165ms}:host([data-layout=column]):nth-child(5){animation-delay:.22s}:host([data-layout=column]):nth-child(6){animation-delay:275ms}:host([data-layout=column]):nth-child(7){animation-delay:.33s}:host([data-layout=column]):nth-child(8){animation-delay:385ms}:host([data-layout=column]):nth-child(9){animation-delay:.44s}:host([data-layout=column]):nth-child(10){animation-delay:495ms}:host([data-layout=column]):nth-child(11){animation-delay:.55s}:host([data-layout=column]):nth-child(12){animation-delay:605ms}:host([data-layout=column]):nth-child(n+13){animation-delay:605ms}:host([data-layout=row]){display:flex;align-items:flex-start;gap:12px;padding:14px 12px;border-color:transparent;background:transparent;box-shadow:none;animation:itemIn .4s var(--nova-ease-micro) both}:host([data-layout=row]):nth-child(1){animation-delay:0ms}:host([data-layout=row]):nth-child(2){animation-delay:40ms}:host([data-layout=row]):nth-child(3){animation-delay:80ms}:host([data-layout=row]):nth-child(4){animation-delay:.12s}:host([data-layout=row]):nth-child(5){animation-delay:.16s}:host([data-layout=row]):nth-child(6){animation-delay:.2s}:host([data-layout=row]):nth-child(7){animation-delay:.24s}:host([data-layout=row]):nth-child(8){animation-delay:.28s}:host([data-layout=row]):nth-child(9){animation-delay:.32s}:host([data-layout=row]):nth-child(10){animation-delay:.36s}:host([data-layout=row]):nth-child(11){animation-delay:.4s}:host([data-layout=row]):nth-child(12){animation-delay:.44s}:host([data-layout=row]):nth-child(n+13){animation-delay:.44s}:host([data-layout=row]){transition:padding-inline-start var(--t-overlay),background var(--t-state),border-color var(--t-state),box-shadow var(--t-state)}:host([data-layout=row]):hover{background:var(--w04)}:host([data-layout=row]):not(.is-selectable,:first-child):before{content:\"\";position:absolute;inset-block-start:0;inset-inline:12px;block-size:1px;background:var(--w07)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:48px}:host([data-layout=row].is-selectable){padding:13px 14px;border:1px solid var(--w07);background:var(--w04)}:host([data-layout=row].is-selectable):hover{background:var(--w06);border-color:var(--w14)}:host([data-layout=row].is-selected){background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=row].is-selected):hover{background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=column].is-selected){background:color-mix(in srgb,var(--accent-soft) 65%,var(--bg-2));border-color:color-mix(in srgb,var(--accent) 45%,transparent)}.card__check{position:absolute;inset-inline-start:14px;inset-block-start:15px;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity var(--t-state)}.card__check input{position:absolute;opacity:0;width:14px;height:14px;margin:0;cursor:pointer}:host(:hover) .card__check,:host(:focus-visible) .card__check,:host(:has(:focus-visible)) .card__check,:host(.is-selected) .card__check{opacity:1;pointer-events:auto}.card__check-box{position:relative;display:inline-block;width:14px;height:14px;border:1.5px solid var(--ink-4);border-radius:4px;background:var(--bg-2);transition:background var(--t-state),border-color var(--t-state);flex-shrink:0}.card__check-box:after{content:\"\";position:absolute;inset:0;margin:auto;width:4px;height:7px;border:solid var(--ink-inverse);border-width:0 1.6px 1.6px 0;transform:translateY(-1px) rotate(45deg);opacity:0;transition:opacity var(--t-state)}input:checked+.card__check-box{background:var(--accent);border-color:var(--accent)}input:checked+.card__check-box:after{opacity:1}.card__main{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0;flex:1}:host([data-layout=column]) .card__main{grid-area:main;gap:var(--sp-3);height:100%}:host([data-layout=row]) .card__main{font-size:13px;line-height:1.5;color:var(--w55);text-wrap:pretty}:host([data-layout=column]) .card__main ::ng-deep fly-card-body{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-meta{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-body~fly-card-meta{margin-block-start:0}:host ::ng-deep fly-card-media{display:block;flex-shrink:0}:host([data-layout=column]) ::ng-deep fly-card-media{grid-area:media;margin-block-end:var(--sp-3)}:host ::ng-deep fly-card-title{display:block;font-size:15px;color:var(--ink);letter-spacing:-.01em;overflow:hidden;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-title{font-weight:var(--fw-medium);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}:host([data-layout=row]) ::ng-deep fly-card-title{font-weight:var(--fw-semibold);font-size:14px;line-height:1.35;text-wrap:pretty;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:normal;transition:font-size var(--t-state)}:host([data-density=compact]) ::ng-deep fly-card-title{font-size:12.5px}:host([data-density=compact]) ::ng-deep fly-card-status{display:none}:host ::ng-deep fly-card-meta{display:flex;flex-wrap:wrap;gap:var(--sp-1);min-width:0}:host([data-layout=row]) ::ng-deep fly-card-meta{align-items:center;gap:8px;font-size:11.5px;color:var(--w55)}:host([data-layout=row]) ::ng-deep fly-card-meta>span{display:inline-flex;align-items:center}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child){position:relative;padding-inline-start:8px}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child):before{content:\"\";position:absolute;inset-inline-start:0;inset-block:2px;inline-size:1px;background:var(--w12)}:host ::ng-deep fly-card-meta dl{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:var(--sp-2);width:100%;margin:0}:host ::ng-deep fly-card-meta dl>div{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}:host ::ng-deep fly-card-meta dl dt{margin:0;font-size:10px;font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-4)}:host ::ng-deep fly-card-meta dl dd{margin:0;font-size:var(--text-sm);color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep fly-card-status{display:inline-flex;align-items:center;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-status{grid-area:status;place-self:center start;min-height:24px;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-status{flex-shrink:0;align-self:center}:host ::ng-deep fly-card-body{display:block;min-width:0}:host ::ng-deep fly-card-footer{display:flex;align-items:center;gap:6px}:host([data-layout=column]) ::ng-deep fly-card-footer{grid-area:footer;justify-content:space-between;margin-block-start:var(--sp-3);padding-block-start:10px;border-block-start:1px solid var(--line-3);font-size:10.5px;font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4)}:host([data-layout=row]) ::ng-deep fly-card-footer{flex-shrink:0;align-self:center;font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink-3);font-variant-numeric:tabular-nums}:host ::ng-deep fly-card-actions{display:inline-flex;align-items:center;gap:2px}:host([data-layout=column]) ::ng-deep fly-card-actions{grid-area:actions;place-self:center end;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-actions{flex-shrink:0;align-self:center}@media(width<=640px){:host([data-layout=row]){padding:14px var(--sp-4);gap:var(--sp-3)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:44px}.card__check{inset-inline-start:14px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22795
22820
  }
22796
22821
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyCardComponent, decorators: [{
22797
22822
  type: Component,
@@ -22831,7 +22856,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
22831
22856
  <ng-content select="fly-card-status" />
22832
22857
  <ng-content select="fly-card-footer" />
22833
22858
  <ng-content select="fly-card-actions" />
22834
- `, styles: ["@charset \"UTF-8\";:host{background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);box-shadow:var(--shadow-card);padding:var(--sp-4);position:relative;min-width:0}:host(.is-interactive){cursor:pointer;transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive):hover{border-color:var(--line-2);box-shadow:var(--shadow-card)}:host(.is-interactive):focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}:host(.is-interactive.is-lift){transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive.is-lift):hover{transform:translateY(-2px);box-shadow:var(--shadow-filter)}:host([aria-disabled=true]){opacity:.5;cursor:default}:host([data-layout=column]){display:grid;grid-template:\"status actions\" auto \"media media\" auto \"main main\" 1fr \"footer footer\" auto/1fr auto;align-items:start;column-gap:var(--sp-2);animation:riseIn .34s var(--nova-ease-micro) both}:host([data-layout=column]):nth-child(1){animation-delay:0ms}:host([data-layout=column]):nth-child(2){animation-delay:55ms}:host([data-layout=column]):nth-child(3){animation-delay:.11s}:host([data-layout=column]):nth-child(4){animation-delay:165ms}:host([data-layout=column]):nth-child(5){animation-delay:.22s}:host([data-layout=column]):nth-child(6){animation-delay:275ms}:host([data-layout=column]):nth-child(7){animation-delay:.33s}:host([data-layout=column]):nth-child(8){animation-delay:385ms}:host([data-layout=column]):nth-child(9){animation-delay:.44s}:host([data-layout=column]):nth-child(10){animation-delay:495ms}:host([data-layout=column]):nth-child(11){animation-delay:.55s}:host([data-layout=column]):nth-child(12){animation-delay:605ms}:host([data-layout=column]):nth-child(n+13){animation-delay:605ms}:host([data-layout=row]){display:flex;align-items:flex-start;gap:12px;padding:14px 12px;border-color:transparent;background:transparent;box-shadow:none;animation:itemIn .4s var(--nova-ease-micro) both}:host([data-layout=row]):nth-child(1){animation-delay:0ms}:host([data-layout=row]):nth-child(2){animation-delay:40ms}:host([data-layout=row]):nth-child(3){animation-delay:80ms}:host([data-layout=row]):nth-child(4){animation-delay:.12s}:host([data-layout=row]):nth-child(5){animation-delay:.16s}:host([data-layout=row]):nth-child(6){animation-delay:.2s}:host([data-layout=row]):nth-child(7){animation-delay:.24s}:host([data-layout=row]):nth-child(8){animation-delay:.28s}:host([data-layout=row]):nth-child(9){animation-delay:.32s}:host([data-layout=row]):nth-child(10){animation-delay:.36s}:host([data-layout=row]):nth-child(11){animation-delay:.4s}:host([data-layout=row]):nth-child(12){animation-delay:.44s}:host([data-layout=row]):nth-child(n+13){animation-delay:.44s}:host([data-layout=row]){transition:padding-inline-start var(--t-overlay),background var(--t-state),border-color var(--t-state),box-shadow var(--t-state)}:host([data-layout=row]):hover{background:var(--w04)}:host([data-layout=row]):not(.is-selectable,:first-child):before{content:\"\";position:absolute;inset-block-start:0;inset-inline:12px;block-size:1px;background:var(--w07)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:48px}:host([data-layout=row].is-selectable){padding:13px 14px;border:1px solid var(--w07);background:var(--w04)}:host([data-layout=row].is-selectable):hover{background:var(--w06);border-color:var(--w14)}:host([data-layout=row].is-selected){background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=row].is-selected):hover{background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=column].is-selected){background:color-mix(in srgb,var(--accent-soft) 65%,var(--bg-2));border-color:color-mix(in srgb,var(--accent) 45%,transparent)}.card__check{position:absolute;inset-inline-start:14px;inset-block-start:15px;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity var(--t-state)}.card__check input{position:absolute;opacity:0;width:14px;height:14px;margin:0;cursor:pointer}:host(:hover) .card__check,:host(:focus-visible) .card__check,:host(:has(:focus-visible)) .card__check,:host(.is-selected) .card__check{opacity:1;pointer-events:auto}.card__check-box{position:relative;display:inline-block;width:14px;height:14px;border:1.5px solid var(--ink-4);border-radius:4px;background:var(--bg-2);transition:background var(--t-state),border-color var(--t-state);flex-shrink:0}.card__check-box:after{content:\"\";position:absolute;inset:0;margin:auto;width:4px;height:7px;border:solid var(--ink-inverse);border-width:0 1.6px 1.6px 0;transform:translateY(-1px) rotate(45deg);opacity:0;transition:opacity var(--t-state)}input:checked+.card__check-box{background:var(--accent);border-color:var(--accent)}input:checked+.card__check-box:after{opacity:1}.card__main{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0;flex:1}:host([data-layout=column]) .card__main{grid-area:main;gap:var(--sp-3);height:100%}:host([data-layout=row]) .card__main{font-size:13px;line-height:1.5;color:var(--w55);text-wrap:pretty}:host([data-layout=column]) .card__main ::ng-deep fly-card-body{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-meta{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-body~fly-card-meta{margin-block-start:0}:host ::ng-deep fly-card-media{display:block;flex-shrink:0}:host([data-layout=column]) ::ng-deep fly-card-media{grid-area:media;margin-block-end:var(--sp-3)}:host ::ng-deep fly-card-title{display:block;font-size:15px;color:var(--ink);letter-spacing:-.01em;overflow:hidden;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-title{font-weight:var(--fw-medium);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}:host([data-layout=row]) ::ng-deep fly-card-title{font-weight:var(--fw-semibold);font-size:14px;line-height:1.35;text-wrap:pretty;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:normal;transition:font-size var(--t-state)}:host([data-density=compact]) ::ng-deep fly-card-title{font-size:12.5px}:host([data-density=compact]) ::ng-deep fly-card-status{display:none}:host ::ng-deep fly-card-meta{display:flex;flex-wrap:wrap;gap:var(--sp-1);min-width:0}:host([data-layout=row]) ::ng-deep fly-card-meta{align-items:center;gap:8px;font-size:11.5px;color:var(--w55)}:host([data-layout=row]) ::ng-deep fly-card-meta>span{display:inline-flex;align-items:center}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child){position:relative;padding-inline-start:8px}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child):before{content:\"\";position:absolute;inset-inline-start:0;inset-block:2px;inline-size:1px;background:var(--w12)}:host ::ng-deep fly-card-meta dl{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:var(--sp-2);width:100%;margin:0}:host ::ng-deep fly-card-meta dl>div{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}:host ::ng-deep fly-card-meta dl dt{margin:0;font-size:10px;font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-4)}:host ::ng-deep fly-card-meta dl dd{margin:0;font-size:var(--text-sm);color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep fly-card-status{display:inline-flex;align-items:center;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-status{grid-area:status;place-self:center start;min-height:24px;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-status{flex-shrink:0;align-self:center}:host ::ng-deep fly-card-body{display:block;min-width:0}:host ::ng-deep fly-card-footer{display:flex;align-items:center;gap:6px}:host([data-layout=column]) ::ng-deep fly-card-footer{grid-area:footer;justify-content:space-between;margin-block-start:var(--sp-3);padding-block-start:10px;border-block-start:1px solid var(--line-3);font-size:10.5px;font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4)}:host([data-layout=row]) ::ng-deep fly-card-footer{flex-shrink:0;align-self:center;font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink-3);font-variant-numeric:tabular-nums}:host ::ng-deep fly-card-actions{display:inline-flex;align-items:center;gap:2px}:host([data-layout=column]) ::ng-deep fly-card-actions{grid-area:actions;place-self:center end;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-actions{flex-shrink:0;align-self:center}@media(width<=640px){:host([data-layout=row]){padding:14px var(--sp-4);gap:var(--sp-3)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:44px}.card__check{inset-inline-start:14px}}\n"] }]
22859
+ `, styles: ["@charset \"UTF-8\";:host{background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);box-shadow:var(--shadow-card);padding:var(--sp-4);position:relative;min-width:0}:host(.is-interactive){cursor:pointer;transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive):hover{border-color:var(--line-2);box-shadow:var(--shadow-card)}:host(.is-interactive):focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}:host(.is-interactive.is-lift){transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-overlay)}:host(.is-interactive.is-lift):hover{transform:translateY(-2px);box-shadow:var(--shadow-filter)}:host([aria-disabled=true]){opacity:.5;cursor:default}:host([data-layout=column]){display:grid;grid-template:\"status actions\" auto \"media media\" auto \"main main\" 1fr \"footer footer\" auto/1fr auto;align-items:start;column-gap:var(--sp-2);animation:riseIn .34s var(--nova-ease-micro) both}:host([data-layout=column]):nth-child(1){animation-delay:0ms}:host([data-layout=column]):nth-child(2){animation-delay:55ms}:host([data-layout=column]):nth-child(3){animation-delay:.11s}:host([data-layout=column]):nth-child(4){animation-delay:165ms}:host([data-layout=column]):nth-child(5){animation-delay:.22s}:host([data-layout=column]):nth-child(6){animation-delay:275ms}:host([data-layout=column]):nth-child(7){animation-delay:.33s}:host([data-layout=column]):nth-child(8){animation-delay:385ms}:host([data-layout=column]):nth-child(9){animation-delay:.44s}:host([data-layout=column]):nth-child(10){animation-delay:495ms}:host([data-layout=column]):nth-child(11){animation-delay:.55s}:host([data-layout=column]):nth-child(12){animation-delay:605ms}:host([data-layout=column]):nth-child(n+13){animation-delay:605ms}:host([data-layout=row]){display:flex;align-items:flex-start;gap:12px;padding:14px 12px;border-color:transparent;background:transparent;box-shadow:none;animation:itemIn .4s var(--nova-ease-micro) both}:host([data-layout=row]):nth-child(1){animation-delay:0ms}:host([data-layout=row]):nth-child(2){animation-delay:40ms}:host([data-layout=row]):nth-child(3){animation-delay:80ms}:host([data-layout=row]):nth-child(4){animation-delay:.12s}:host([data-layout=row]):nth-child(5){animation-delay:.16s}:host([data-layout=row]):nth-child(6){animation-delay:.2s}:host([data-layout=row]):nth-child(7){animation-delay:.24s}:host([data-layout=row]):nth-child(8){animation-delay:.28s}:host([data-layout=row]):nth-child(9){animation-delay:.32s}:host([data-layout=row]):nth-child(10){animation-delay:.36s}:host([data-layout=row]):nth-child(11){animation-delay:.4s}:host([data-layout=row]):nth-child(12){animation-delay:.44s}:host([data-layout=row]):nth-child(n+13){animation-delay:.44s}:host([data-layout=row]){transition:padding-inline-start var(--t-overlay),background var(--t-state),border-color var(--t-state),box-shadow var(--t-state)}:host([data-layout=row]):hover{background:var(--w04)}:host([data-layout=row]):not(.is-selectable,:first-child):before{content:\"\";position:absolute;inset-block-start:0;inset-inline:12px;block-size:1px;background:var(--w07)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:48px}:host([data-layout=row].is-selectable){padding:13px 14px;border:1px solid var(--w07);background:var(--w04)}:host([data-layout=row].is-selectable):hover{background:var(--w06);border-color:var(--w14)}:host([data-layout=row].is-selected){background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=row].is-selected):hover{background:var(--tint-sel);border-color:var(--accent)}:host([data-layout=column].is-selected){background:color-mix(in srgb,var(--accent-soft) 65%,var(--bg-2));border-color:color-mix(in srgb,var(--accent) 45%,transparent)}.card__check{position:absolute;inset-inline-start:14px;inset-block-start:15px;display:inline-flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity var(--t-state)}.card__check input{position:absolute;opacity:0;width:14px;height:14px;margin:0;cursor:pointer}:host(:hover) .card__check,:host(:focus-visible) .card__check,:host(:has(:focus-visible)) .card__check,:host(.is-selected) .card__check{opacity:1;pointer-events:auto}.card__check-box{position:relative;display:inline-block;width:14px;height:14px;border:1.5px solid var(--ink-4);border-radius:4px;background:var(--bg-2);transition:background var(--t-state),border-color var(--t-state);flex-shrink:0}.card__check-box:after{content:\"\";position:absolute;inset:0;margin:auto;width:4px;height:7px;border:solid var(--ink-inverse);border-width:0 1.6px 1.6px 0;transform:translateY(-1px) rotate(45deg);opacity:0;transition:opacity var(--t-state)}input:checked+.card__check-box{background:var(--accent);border-color:var(--accent)}input:checked+.card__check-box:after{opacity:1}.card__main{display:flex;flex-direction:column;gap:var(--sp-2);min-width:0;flex:1}:host([data-layout=column]) .card__main{grid-area:main;gap:var(--sp-3);height:100%}:host([data-layout=row]) .card__main{font-size:13px;line-height:1.5;color:var(--w55);text-wrap:pretty}:host([data-layout=column]) .card__main ::ng-deep fly-card-body{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-meta{margin-block-start:auto}:host([data-layout=column]) .card__main ::ng-deep fly-card-body~fly-card-meta{margin-block-start:0}:host ::ng-deep fly-card-media{display:block;flex-shrink:0}:host([data-layout=column]) ::ng-deep fly-card-media{grid-area:media;margin-block-end:var(--sp-3)}:host ::ng-deep fly-card-title{display:block;font-size:15px;color:var(--ink);letter-spacing:-.01em;overflow:hidden;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-title{font-weight:var(--fw-medium);line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}:host([data-layout=row]) ::ng-deep fly-card-title{font-weight:var(--fw-semibold);font-size:14px;line-height:1.35;text-wrap:pretty;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;white-space:normal;transition:font-size var(--t-state)}:host([data-density=compact]) ::ng-deep fly-card-title{font-size:12.5px}:host([data-density=compact]) ::ng-deep fly-card-status{display:none}:host ::ng-deep fly-card-meta{display:flex;flex-wrap:wrap;gap:var(--sp-1);min-width:0}:host([data-layout=row]) ::ng-deep fly-card-meta{align-items:center;gap:8px;font-size:11.5px;color:var(--w55)}:host([data-layout=row]) ::ng-deep fly-card-meta>span{display:inline-flex;align-items:center}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child){position:relative;padding-inline-start:8px}:host([data-layout=row]) ::ng-deep fly-card-meta>span:not(:first-child):before{content:\"\";position:absolute;inset-inline-start:0;inset-block:2px;inline-size:1px;background:var(--w12)}:host ::ng-deep fly-card-meta dl{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:var(--sp-2);width:100%;margin:0}:host ::ng-deep fly-card-meta dl>div{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}:host ::ng-deep fly-card-meta dl dt{margin:0;font-size:10px;font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-4)}:host ::ng-deep fly-card-meta dl dd{margin:0;font-size:var(--text-sm);color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep fly-card-status{display:inline-flex;align-items:center;min-width:0}:host([data-layout=column]) ::ng-deep fly-card-status{grid-area:status;place-self:center start;min-height:24px;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-status{flex-shrink:0;align-self:center}:host ::ng-deep fly-card-body{display:block;min-width:0}:host ::ng-deep fly-card-footer{display:flex;align-items:center;gap:6px}:host([data-layout=column]) ::ng-deep fly-card-footer{grid-area:footer;justify-content:space-between;margin-block-start:var(--sp-3);padding-block-start:10px;border-block-start:1px solid var(--line-3);font-size:10.5px;font-weight:var(--fw-medium);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-4)}:host([data-layout=row]) ::ng-deep fly-card-footer{flex-shrink:0;align-self:center;font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink-3);font-variant-numeric:tabular-nums}:host ::ng-deep fly-card-actions{display:inline-flex;align-items:center;gap:2px}:host([data-layout=column]) ::ng-deep fly-card-actions{grid-area:actions;place-self:center end;margin-block-end:var(--sp-3)}:host([data-layout=row]) ::ng-deep fly-card-actions{flex-shrink:0;align-self:center}@media(width<=640px){:host([data-layout=row]){padding:14px var(--sp-4);gap:var(--sp-3)}:host([data-layout=row].is-selectable:hover),:host([data-layout=row].is-selectable.is-selected){padding-inline-start:44px}.card__check{inset-inline-start:14px}}\n"] }]
22835
22860
  }], propDecorators: { layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], lift: [{ type: i0.Input, args: [{ isSignal: true, alias: "lift", required: false }] }], selectLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectLabelKey", required: false }] }], selectLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectLabel", required: false }] }], activated: [{ type: i0.Output, args: ["activated"] }] } });
22836
22861
 
22837
22862
  /**
@@ -23285,14 +23310,14 @@ class FlyFilterPanelComponent {
23285
23310
  host.style.removeProperty('--fp-max-w');
23286
23311
  }
23287
23312
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyFilterPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
23288
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyFilterPanelComponent, isStandalone: true, selector: "fly-filter-panel", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: true, transformFunction: null }, titleKey: { classPropertyName: "titleKey", publicName: "titleKey", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, showSearchButton: { classPropertyName: "showSearchButton", publicName: "showSearchButton", isSignal: true, isRequired: false, transformFunction: null }, anchored: { classPropertyName: "anchored", publicName: "anchored", isSignal: true, isRequired: false, transformFunction: null }, anchorEl: { classPropertyName: "anchorEl", publicName: "anchorEl", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cleared: "cleared", closed: "closed", searched: "searched" }, host: { properties: { "class.fp--anchored": "anchored() && !floating()", "class.fp--floating": "floating()" } }, ngImport: i0, template: " @if (open()) {\r\n <!--\r\n The dismiss host is `.fp`, and the TRIGGER is listed as ignored rather than\r\n wrapped: an anchored panel's toggle can live in another component entirely (the\r\n shell's magic bar), so there is no element that contains both. See the\r\n directive's `flyClickOutsideIgnore` for what goes wrong without it.\r\n -->\r\n <div\r\n class=\"fp\"\r\n [attr.data-layout]=\"layout()\"\r\n [flyClickOutsideEnabled]=\"dismissable()\"\r\n [flyClickOutsideIgnore]=\"anchorEl()\"\r\n (flyClickOutside)=\"closed.emit()\"\r\n >\r\n <div class=\"fp__head\">\r\n <div class=\"fp__title\">{{ titleKey() | translate }}</div>\r\n <div class=\"fp__actions\">\r\n <button type=\"button\" class=\"fp__clear\" (click)=\"cleared.emit()\">\r\n {{ 'ui.action.clearFilters' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fp__close\"\r\n (click)=\"closed.emit()\"\r\n [attr.aria-label]=\"'ui.action.close' | translate\"\r\n >\u00D7</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"fp__body\">\r\n <ng-content select=\"[filter-status]\" />\r\n\r\n <div class=\"fp__grid\">\r\n <ng-content />\r\n </div>\r\n\r\n @if (hasMore()) {\r\n <div class=\"fp__more\" [hidden]=\"!showMore()\">\r\n <div class=\"fp__grid\">\r\n <ng-content select=\"[filter-more]\" />\r\n </div>\r\n </div>\r\n <div class=\"fp__morebar\">\r\n <button\r\n type=\"button\"\r\n class=\"fp__morebtn\"\r\n (click)=\"showMore.set(!showMore())\"\r\n [attr.aria-expanded]=\"showMore()\"\r\n >\r\n <svg class=\"fp__moreico\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path [attr.d]=\"showMore() ? 'M3.5 8h9' : 'M8 3.5v9M3.5 8h9'\" />\r\n </svg>\r\n {{ (showMore() ? 'ui.action.fewerOptions' : 'ui.action.addMoreOptions') | translate }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (showSearchButton()) {\r\n <div class=\"fp__footer\">\r\n <button type=\"button\" fly-button variant=\"primary\" (click)=\"searched.emit()\">\r\n {{ 'ui.action.search' | translate }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n", styles: ["@charset \"UTF-8\";:host{display:block;container-type:inline-size}.fp{margin-block-end:var(--sp-4);border-radius:var(--r-lg);overflow:hidden;animation:fly-fp-in var(--t-overlay);border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fp{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fp:before,.fp:after{display:none}}@media(prefers-contrast:more){.fp{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fp:after{animation:none}}:host(.fp--anchored){--fp-shift-x: 0px;--fp-max-w: calc(100vw - 2 * var(--sp-4));position:absolute;inset-block-start:calc(100% + var(--sp-2));inset-inline-end:0;z-index:var(--z-overlay);width:min(600px,var(--fp-max-w));transform:translate(var(--fp-shift-x))}:host(.fp--floating){--fp-max-w: calc(100vw - 2 * var(--sp-4));--fp-max-h: calc(100vh - 2 * var(--sp-4));--fp-x: 0px;--fp-y: 0px;position:fixed;inset-block-start:var(--fp-y);inset-inline-start:auto;left:var(--fp-x);z-index:var(--z-overlay);width:min(600px,var(--fp-max-w));max-height:var(--fp-max-h)}:host(.fp--floating) .fp{margin-block-end:0;max-height:var(--fp-max-h);display:flex;flex-direction:column}:host(.fp--floating) .fp__body{flex:1 1 auto;min-height:0;overflow-y:auto}:host(.fp--anchored) .fp{margin-block-end:0}:host(.fp--anchored) .fp__body{max-height:min(320px,44vh);overflow-y:auto}.fp__head{display:flex;align-items:center;justify-content:space-between;padding:var(--sp-3) var(--sp-4);border-block-end:.5px solid var(--w1)}.fp__title{font-size:var(--text-xs);font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3)}.fp__actions{display:flex;align-items:center;gap:var(--sp-1)}.fp__clear{border:0;background:transparent;font-size:12px;color:var(--ink-3);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-sm);cursor:pointer;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.fp__clear:hover{color:var(--ink);background:var(--w08)}.fp__clear:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fp__close{width:24px;height:24px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:var(--text-xl);line-height:1;display:grid;place-items:center}.fp__close:hover{color:var(--ink);background:var(--w08)}.fp__close:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fp ::ng-deep [filter-status]{display:flex;flex-direction:column;gap:var(--sp-2);padding:14px var(--sp-4);border-block-end:.5px solid var(--w08)}.fp__grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:14px var(--sp-4);padding:var(--sp-4)}@container (width <= 1180px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(4,minmax(0,1fr))}}@media(width<=1180px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(4,minmax(0,1fr))}}@container (width <= 820px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(width<=820px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}.fp[data-layout=rows] .fp__grid{grid-template-columns:1fr;gap:var(--sp-2)}.fp[data-layout=rows] ::ng-deep .fld{display:grid;grid-template-columns:minmax(110px,168px) 1fr;align-items:center;gap:var(--sp-1) var(--sp-4)}.fp[data-layout=rows] ::ng-deep .fld__l{margin:0;color:var(--ink-2)}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:2}@container (width <= 640px){.fp[data-layout=rows] ::ng-deep .fld{grid-template-columns:1fr}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:1}}@media(width<=640px){.fp[data-layout=rows] ::ng-deep .fld{grid-template-columns:1fr}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:1}}.fp__more{border-block-start:.5px solid var(--w08)}.fp__more .fp__grid{padding-block-start:var(--sp-3)}.fp__morebar{padding:0 var(--sp-4) var(--sp-3)}.fp__morebtn{display:inline-flex;align-items:center;gap:var(--sp-1);border:0;background:transparent;padding:var(--sp-1) var(--sp-2);border-radius:var(--r-sm);font-family:inherit;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--accent);cursor:pointer;transition:background var(--t-state)}.fp__morebtn:hover{background:var(--w08)}.fp__morebtn:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fp__moreico{width:14px;height:14px;flex-shrink:0}.fp__footer{display:flex;justify-content:flex-end;padding:var(--sp-3) var(--sp-4);border-block-start:.5px solid var(--w08)}.fp__footer button{background:var(--grad);border:0;color:var(--ink-inverse);box-shadow:var(--shadow-raised)}.fp__footer button:hover{background:var(--grad);border:0;filter:brightness(1.05);box-shadow:var(--shadow-accent)}@keyframes fly-fp-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"], dependencies: [{ kind: "component", type: FlyButtonComponent, selector: "button[fly-button], a[fly-button]", inputs: ["variant", "size", "loading"] }, { kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled", "flyClickOutsideIgnore"], outputs: ["flyClickOutside"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23313
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyFilterPanelComponent, isStandalone: true, selector: "fly-filter-panel", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: true, transformFunction: null }, titleKey: { classPropertyName: "titleKey", publicName: "titleKey", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, showSearchButton: { classPropertyName: "showSearchButton", publicName: "showSearchButton", isSignal: true, isRequired: false, transformFunction: null }, anchored: { classPropertyName: "anchored", publicName: "anchored", isSignal: true, isRequired: false, transformFunction: null }, anchorEl: { classPropertyName: "anchorEl", publicName: "anchorEl", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cleared: "cleared", closed: "closed", searched: "searched" }, host: { properties: { "class.fp--anchored": "anchored() && !floating()", "class.fp--floating": "floating()" } }, ngImport: i0, template: " @if (open()) {\r\n <!--\r\n The dismiss host is `.fp`, and the TRIGGER is listed as ignored rather than\r\n wrapped: an anchored panel's toggle can live in another component entirely (the\r\n shell's magic bar), so there is no element that contains both. See the\r\n directive's `flyClickOutsideIgnore` for what goes wrong without it.\r\n -->\r\n <div\r\n class=\"fp\"\r\n [attr.data-layout]=\"layout()\"\r\n [flyClickOutsideEnabled]=\"dismissable()\"\r\n [flyClickOutsideIgnore]=\"anchorEl()\"\r\n (flyClickOutside)=\"closed.emit()\"\r\n >\r\n <div class=\"fp__head\">\r\n <div class=\"fp__title\">{{ titleKey() | translate }}</div>\r\n <div class=\"fp__actions\">\r\n <button type=\"button\" class=\"fp__clear\" (click)=\"cleared.emit()\">\r\n {{ 'ui.action.clearFilters' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fp__close\"\r\n (click)=\"closed.emit()\"\r\n [attr.aria-label]=\"'ui.action.close' | translate\"\r\n >\u00D7</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"fp__body\">\r\n <ng-content select=\"[filter-status]\" />\r\n\r\n <div class=\"fp__grid\">\r\n <ng-content />\r\n </div>\r\n\r\n @if (hasMore()) {\r\n <div class=\"fp__more\" [hidden]=\"!showMore()\">\r\n <div class=\"fp__grid\">\r\n <ng-content select=\"[filter-more]\" />\r\n </div>\r\n </div>\r\n <div class=\"fp__morebar\">\r\n <button\r\n type=\"button\"\r\n class=\"fp__morebtn\"\r\n (click)=\"showMore.set(!showMore())\"\r\n [attr.aria-expanded]=\"showMore()\"\r\n >\r\n <svg class=\"fp__moreico\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path [attr.d]=\"showMore() ? 'M3.5 8h9' : 'M8 3.5v9M3.5 8h9'\" />\r\n </svg>\r\n {{ (showMore() ? 'ui.action.fewerOptions' : 'ui.action.addMoreOptions') | translate }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (showSearchButton()) {\r\n <div class=\"fp__footer\">\r\n <button type=\"button\" fly-button variant=\"primary\" (click)=\"searched.emit()\">\r\n {{ 'ui.action.search' | translate }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n", styles: ["@charset \"UTF-8\";:host{display:block;container-type:inline-size}.fp{margin-block-end:var(--sp-4);border-radius:var(--r-lg);overflow:hidden;animation:fly-fp-in var(--t-overlay);border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fp{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fp:before,.fp:after{display:none}}@media(prefers-contrast:more){.fp{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fp:after{animation:none}}:host(.fp--anchored){--fp-shift-x: 0px;--fp-max-w: calc(100vw - 2 * var(--sp-4));position:absolute;inset-block-start:calc(100% + var(--sp-2));inset-inline-end:0;z-index:var(--z-overlay);width:min(600px,var(--fp-max-w));transform:translate(var(--fp-shift-x))}:host(.fp--floating){--fp-max-w: calc(100vw - 2 * var(--sp-4));--fp-max-h: calc(100vh - 2 * var(--sp-4));--fp-x: 0px;--fp-y: 0px;position:fixed;inset-block-start:var(--fp-y);inset-inline-start:auto;left:var(--fp-x);z-index:var(--z-overlay);width:min(600px,var(--fp-max-w));max-height:var(--fp-max-h)}:host(.fp--floating) .fp{margin-block-end:0;max-height:var(--fp-max-h);display:flex;flex-direction:column}:host(.fp--floating) .fp__body{flex:1 1 auto;min-height:0;overflow-y:auto}:host(.fp--anchored) .fp{margin-block-end:0}:host(.fp--anchored) .fp__body{max-height:min(320px,44vh);overflow-y:auto}.fp__head{display:flex;align-items:center;justify-content:space-between;padding:var(--sp-3) var(--sp-4);border-block-end:.5px solid var(--w1)}.fp__title{font-size:var(--text-xs);font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3)}.fp__actions{display:flex;align-items:center;gap:var(--sp-1)}.fp__clear{border:0;background:transparent;font-size:12px;color:var(--ink-3);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-sm);cursor:pointer;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.fp__clear:hover{color:var(--ink);background:var(--w08)}.fp__clear:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.fp__close{width:24px;height:24px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:var(--text-xl);line-height:1;display:grid;place-items:center}.fp__close:hover{color:var(--ink);background:var(--w08)}.fp__close:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.fp ::ng-deep [filter-status]{display:flex;flex-direction:column;gap:var(--sp-2);padding:14px var(--sp-4);border-block-end:.5px solid var(--w08)}.fp__grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:14px var(--sp-4);padding:var(--sp-4)}@container (width <= 1180px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(4,minmax(0,1fr))}}@media(width<=1180px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(4,minmax(0,1fr))}}@container (width <= 820px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(width<=820px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}.fp[data-layout=rows] .fp__grid{grid-template-columns:1fr;gap:var(--sp-2)}.fp[data-layout=rows] ::ng-deep .fld{display:grid;grid-template-columns:minmax(110px,168px) 1fr;align-items:center;gap:var(--sp-1) var(--sp-4)}.fp[data-layout=rows] ::ng-deep .fld__l{margin:0;color:var(--ink-2)}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:2}@container (width <= 640px){.fp[data-layout=rows] ::ng-deep .fld{grid-template-columns:1fr}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:1}}@media(width<=640px){.fp[data-layout=rows] ::ng-deep .fld{grid-template-columns:1fr}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:1}}.fp__more{border-block-start:.5px solid var(--w08)}.fp__more .fp__grid{padding-block-start:var(--sp-3)}.fp__morebar{padding:0 var(--sp-4) var(--sp-3)}.fp__morebtn{display:inline-flex;align-items:center;gap:var(--sp-1);border:0;background:transparent;padding:var(--sp-1) var(--sp-2);border-radius:var(--r-sm);font-family:inherit;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--accent);cursor:pointer;transition:background var(--t-state)}.fp__morebtn:hover{background:var(--w08)}.fp__morebtn:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.fp__moreico{width:14px;height:14px;flex-shrink:0}.fp__footer{display:flex;justify-content:flex-end;padding:var(--sp-3) var(--sp-4);border-block-start:.5px solid var(--w08)}.fp__footer button{background:var(--grad);border:0;color:var(--ink-inverse);box-shadow:var(--shadow-raised)}.fp__footer button:hover{background:var(--grad);border:0;filter:brightness(1.05);box-shadow:var(--shadow-accent)}@keyframes fly-fp-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"], dependencies: [{ kind: "component", type: FlyButtonComponent, selector: "button[fly-button], a[fly-button]", inputs: ["variant", "size", "loading"] }, { kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled", "flyClickOutsideIgnore"], outputs: ["flyClickOutside"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23289
23314
  }
23290
23315
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyFilterPanelComponent, decorators: [{
23291
23316
  type: Component,
23292
23317
  args: [{ selector: 'fly-filter-panel', standalone: true, imports: [TranslatePipe, FlyButtonComponent, FlyClickOutsideDirective], changeDetection: ChangeDetectionStrategy.OnPush, host: {
23293
23318
  '[class.fp--anchored]': 'anchored() && !floating()',
23294
23319
  '[class.fp--floating]': 'floating()',
23295
- }, template: " @if (open()) {\r\n <!--\r\n The dismiss host is `.fp`, and the TRIGGER is listed as ignored rather than\r\n wrapped: an anchored panel's toggle can live in another component entirely (the\r\n shell's magic bar), so there is no element that contains both. See the\r\n directive's `flyClickOutsideIgnore` for what goes wrong without it.\r\n -->\r\n <div\r\n class=\"fp\"\r\n [attr.data-layout]=\"layout()\"\r\n [flyClickOutsideEnabled]=\"dismissable()\"\r\n [flyClickOutsideIgnore]=\"anchorEl()\"\r\n (flyClickOutside)=\"closed.emit()\"\r\n >\r\n <div class=\"fp__head\">\r\n <div class=\"fp__title\">{{ titleKey() | translate }}</div>\r\n <div class=\"fp__actions\">\r\n <button type=\"button\" class=\"fp__clear\" (click)=\"cleared.emit()\">\r\n {{ 'ui.action.clearFilters' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fp__close\"\r\n (click)=\"closed.emit()\"\r\n [attr.aria-label]=\"'ui.action.close' | translate\"\r\n >\u00D7</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"fp__body\">\r\n <ng-content select=\"[filter-status]\" />\r\n\r\n <div class=\"fp__grid\">\r\n <ng-content />\r\n </div>\r\n\r\n @if (hasMore()) {\r\n <div class=\"fp__more\" [hidden]=\"!showMore()\">\r\n <div class=\"fp__grid\">\r\n <ng-content select=\"[filter-more]\" />\r\n </div>\r\n </div>\r\n <div class=\"fp__morebar\">\r\n <button\r\n type=\"button\"\r\n class=\"fp__morebtn\"\r\n (click)=\"showMore.set(!showMore())\"\r\n [attr.aria-expanded]=\"showMore()\"\r\n >\r\n <svg class=\"fp__moreico\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path [attr.d]=\"showMore() ? 'M3.5 8h9' : 'M8 3.5v9M3.5 8h9'\" />\r\n </svg>\r\n {{ (showMore() ? 'ui.action.fewerOptions' : 'ui.action.addMoreOptions') | translate }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (showSearchButton()) {\r\n <div class=\"fp__footer\">\r\n <button type=\"button\" fly-button variant=\"primary\" (click)=\"searched.emit()\">\r\n {{ 'ui.action.search' | translate }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n", styles: ["@charset \"UTF-8\";:host{display:block;container-type:inline-size}.fp{margin-block-end:var(--sp-4);border-radius:var(--r-lg);overflow:hidden;animation:fly-fp-in var(--t-overlay);border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fp{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fp:before,.fp:after{display:none}}@media(prefers-contrast:more){.fp{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fp:after{animation:none}}:host(.fp--anchored){--fp-shift-x: 0px;--fp-max-w: calc(100vw - 2 * var(--sp-4));position:absolute;inset-block-start:calc(100% + var(--sp-2));inset-inline-end:0;z-index:var(--z-overlay);width:min(600px,var(--fp-max-w));transform:translate(var(--fp-shift-x))}:host(.fp--floating){--fp-max-w: calc(100vw - 2 * var(--sp-4));--fp-max-h: calc(100vh - 2 * var(--sp-4));--fp-x: 0px;--fp-y: 0px;position:fixed;inset-block-start:var(--fp-y);inset-inline-start:auto;left:var(--fp-x);z-index:var(--z-overlay);width:min(600px,var(--fp-max-w));max-height:var(--fp-max-h)}:host(.fp--floating) .fp{margin-block-end:0;max-height:var(--fp-max-h);display:flex;flex-direction:column}:host(.fp--floating) .fp__body{flex:1 1 auto;min-height:0;overflow-y:auto}:host(.fp--anchored) .fp{margin-block-end:0}:host(.fp--anchored) .fp__body{max-height:min(320px,44vh);overflow-y:auto}.fp__head{display:flex;align-items:center;justify-content:space-between;padding:var(--sp-3) var(--sp-4);border-block-end:.5px solid var(--w1)}.fp__title{font-size:var(--text-xs);font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3)}.fp__actions{display:flex;align-items:center;gap:var(--sp-1)}.fp__clear{border:0;background:transparent;font-size:12px;color:var(--ink-3);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-sm);cursor:pointer;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.fp__clear:hover{color:var(--ink);background:var(--w08)}.fp__clear:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fp__close{width:24px;height:24px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:var(--text-xl);line-height:1;display:grid;place-items:center}.fp__close:hover{color:var(--ink);background:var(--w08)}.fp__close:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fp ::ng-deep [filter-status]{display:flex;flex-direction:column;gap:var(--sp-2);padding:14px var(--sp-4);border-block-end:.5px solid var(--w08)}.fp__grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:14px var(--sp-4);padding:var(--sp-4)}@container (width <= 1180px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(4,minmax(0,1fr))}}@media(width<=1180px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(4,minmax(0,1fr))}}@container (width <= 820px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(width<=820px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}.fp[data-layout=rows] .fp__grid{grid-template-columns:1fr;gap:var(--sp-2)}.fp[data-layout=rows] ::ng-deep .fld{display:grid;grid-template-columns:minmax(110px,168px) 1fr;align-items:center;gap:var(--sp-1) var(--sp-4)}.fp[data-layout=rows] ::ng-deep .fld__l{margin:0;color:var(--ink-2)}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:2}@container (width <= 640px){.fp[data-layout=rows] ::ng-deep .fld{grid-template-columns:1fr}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:1}}@media(width<=640px){.fp[data-layout=rows] ::ng-deep .fld{grid-template-columns:1fr}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:1}}.fp__more{border-block-start:.5px solid var(--w08)}.fp__more .fp__grid{padding-block-start:var(--sp-3)}.fp__morebar{padding:0 var(--sp-4) var(--sp-3)}.fp__morebtn{display:inline-flex;align-items:center;gap:var(--sp-1);border:0;background:transparent;padding:var(--sp-1) var(--sp-2);border-radius:var(--r-sm);font-family:inherit;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--accent);cursor:pointer;transition:background var(--t-state)}.fp__morebtn:hover{background:var(--w08)}.fp__morebtn:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fp__moreico{width:14px;height:14px;flex-shrink:0}.fp__footer{display:flex;justify-content:flex-end;padding:var(--sp-3) var(--sp-4);border-block-start:.5px solid var(--w08)}.fp__footer button{background:var(--grad);border:0;color:var(--ink-inverse);box-shadow:var(--shadow-raised)}.fp__footer button:hover{background:var(--grad);border:0;filter:brightness(1.05);box-shadow:var(--shadow-accent)}@keyframes fly-fp-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"] }]
23320
+ }, template: " @if (open()) {\r\n <!--\r\n The dismiss host is `.fp`, and the TRIGGER is listed as ignored rather than\r\n wrapped: an anchored panel's toggle can live in another component entirely (the\r\n shell's magic bar), so there is no element that contains both. See the\r\n directive's `flyClickOutsideIgnore` for what goes wrong without it.\r\n -->\r\n <div\r\n class=\"fp\"\r\n [attr.data-layout]=\"layout()\"\r\n [flyClickOutsideEnabled]=\"dismissable()\"\r\n [flyClickOutsideIgnore]=\"anchorEl()\"\r\n (flyClickOutside)=\"closed.emit()\"\r\n >\r\n <div class=\"fp__head\">\r\n <div class=\"fp__title\">{{ titleKey() | translate }}</div>\r\n <div class=\"fp__actions\">\r\n <button type=\"button\" class=\"fp__clear\" (click)=\"cleared.emit()\">\r\n {{ 'ui.action.clearFilters' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fp__close\"\r\n (click)=\"closed.emit()\"\r\n [attr.aria-label]=\"'ui.action.close' | translate\"\r\n >\u00D7</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"fp__body\">\r\n <ng-content select=\"[filter-status]\" />\r\n\r\n <div class=\"fp__grid\">\r\n <ng-content />\r\n </div>\r\n\r\n @if (hasMore()) {\r\n <div class=\"fp__more\" [hidden]=\"!showMore()\">\r\n <div class=\"fp__grid\">\r\n <ng-content select=\"[filter-more]\" />\r\n </div>\r\n </div>\r\n <div class=\"fp__morebar\">\r\n <button\r\n type=\"button\"\r\n class=\"fp__morebtn\"\r\n (click)=\"showMore.set(!showMore())\"\r\n [attr.aria-expanded]=\"showMore()\"\r\n >\r\n <svg class=\"fp__moreico\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <path [attr.d]=\"showMore() ? 'M3.5 8h9' : 'M8 3.5v9M3.5 8h9'\" />\r\n </svg>\r\n {{ (showMore() ? 'ui.action.fewerOptions' : 'ui.action.addMoreOptions') | translate }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (showSearchButton()) {\r\n <div class=\"fp__footer\">\r\n <button type=\"button\" fly-button variant=\"primary\" (click)=\"searched.emit()\">\r\n {{ 'ui.action.search' | translate }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n", styles: ["@charset \"UTF-8\";:host{display:block;container-type:inline-size}.fp{margin-block-end:var(--sp-4);border-radius:var(--r-lg);overflow:hidden;animation:fly-fp-in var(--t-overlay);border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fp{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fp:before,.fp:after{display:none}}@media(prefers-contrast:more){.fp{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fp:after{animation:none}}:host(.fp--anchored){--fp-shift-x: 0px;--fp-max-w: calc(100vw - 2 * var(--sp-4));position:absolute;inset-block-start:calc(100% + var(--sp-2));inset-inline-end:0;z-index:var(--z-overlay);width:min(600px,var(--fp-max-w));transform:translate(var(--fp-shift-x))}:host(.fp--floating){--fp-max-w: calc(100vw - 2 * var(--sp-4));--fp-max-h: calc(100vh - 2 * var(--sp-4));--fp-x: 0px;--fp-y: 0px;position:fixed;inset-block-start:var(--fp-y);inset-inline-start:auto;left:var(--fp-x);z-index:var(--z-overlay);width:min(600px,var(--fp-max-w));max-height:var(--fp-max-h)}:host(.fp--floating) .fp{margin-block-end:0;max-height:var(--fp-max-h);display:flex;flex-direction:column}:host(.fp--floating) .fp__body{flex:1 1 auto;min-height:0;overflow-y:auto}:host(.fp--anchored) .fp{margin-block-end:0}:host(.fp--anchored) .fp__body{max-height:min(320px,44vh);overflow-y:auto}.fp__head{display:flex;align-items:center;justify-content:space-between;padding:var(--sp-3) var(--sp-4);border-block-end:.5px solid var(--w1)}.fp__title{font-size:var(--text-xs);font-weight:var(--fw-medium);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3)}.fp__actions{display:flex;align-items:center;gap:var(--sp-1)}.fp__clear{border:0;background:transparent;font-size:12px;color:var(--ink-3);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-sm);cursor:pointer;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.fp__clear:hover{color:var(--ink);background:var(--w08)}.fp__clear:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.fp__close{width:24px;height:24px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:var(--text-xl);line-height:1;display:grid;place-items:center}.fp__close:hover{color:var(--ink);background:var(--w08)}.fp__close:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.fp ::ng-deep [filter-status]{display:flex;flex-direction:column;gap:var(--sp-2);padding:14px var(--sp-4);border-block-end:.5px solid var(--w08)}.fp__grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:14px var(--sp-4);padding:var(--sp-4)}@container (width <= 1180px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(4,minmax(0,1fr))}}@media(width<=1180px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(4,minmax(0,1fr))}}@container (width <= 820px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(width<=820px){.fp[data-layout=grid] .fp__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}.fp[data-layout=rows] .fp__grid{grid-template-columns:1fr;gap:var(--sp-2)}.fp[data-layout=rows] ::ng-deep .fld{display:grid;grid-template-columns:minmax(110px,168px) 1fr;align-items:center;gap:var(--sp-1) var(--sp-4)}.fp[data-layout=rows] ::ng-deep .fld__l{margin:0;color:var(--ink-2)}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:2}@container (width <= 640px){.fp[data-layout=rows] ::ng-deep .fld{grid-template-columns:1fr}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:1}}@media(width<=640px){.fp[data-layout=rows] ::ng-deep .fld{grid-template-columns:1fr}.fp[data-layout=rows] ::ng-deep .fld__hint,.fp[data-layout=rows] ::ng-deep .fld__err{grid-column:1}}.fp__more{border-block-start:.5px solid var(--w08)}.fp__more .fp__grid{padding-block-start:var(--sp-3)}.fp__morebar{padding:0 var(--sp-4) var(--sp-3)}.fp__morebtn{display:inline-flex;align-items:center;gap:var(--sp-1);border:0;background:transparent;padding:var(--sp-1) var(--sp-2);border-radius:var(--r-sm);font-family:inherit;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--accent);cursor:pointer;transition:background var(--t-state)}.fp__morebtn:hover{background:var(--w08)}.fp__morebtn:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.fp__moreico{width:14px;height:14px;flex-shrink:0}.fp__footer{display:flex;justify-content:flex-end;padding:var(--sp-3) var(--sp-4);border-block-start:.5px solid var(--w08)}.fp__footer button{background:var(--grad);border:0;color:var(--ink-inverse);box-shadow:var(--shadow-raised)}.fp__footer button:hover{background:var(--grad);border:0;filter:brightness(1.05);box-shadow:var(--shadow-accent)}@keyframes fly-fp-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n"] }]
23296
23321
  }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: true }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], hasMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMore", required: false }] }], showSearchButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSearchButton", required: false }] }], anchored: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchored", required: false }] }], anchorEl: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchorEl", required: false }] }], cleared: [{ type: i0.Output, args: ["cleared"] }], closed: [{ type: i0.Output, args: ["closed"] }], searched: [{ type: i0.Output, args: ["searched"] }] } });
23297
23322
 
23298
23323
  /**
@@ -23432,11 +23457,11 @@ class FlyDataTableComponent {
23432
23457
  this.sortChange.emit(nextSort(this.sort(), col.id));
23433
23458
  }
23434
23459
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyDataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
23435
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyDataTableComponent, isStandalone: true, selector: "fly-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelKey: { classPropertyName: "ariaLabelKey", publicName: "ariaLabelKey", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, emptyKey: { classPropertyName: "emptyKey", publicName: "emptyKey", isSignal: true, isRequired: false, transformFunction: null }, emptyIconClass: { classPropertyName: "emptyIconClass", publicName: "emptyIconClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortChange: "sortChange", rowActivated: "rowActivated" }, queries: [{ propertyName: "cellTemplates", predicate: FlyCellDirective, isSignal: true }], ngImport: i0, template: "<table class=\"dt\" [attr.aria-label]=\"ariaLabelKey() ? (ariaLabelKey()! | translate) : null\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.id) {\r\n <th\r\n scope=\"col\"\r\n [class.dt__th--end]=\"col.align === 'end'\"\r\n [attr.aria-sort]=\"headerAriaSort(col)\"\r\n >\r\n @if (col.sortable) {\r\n <button type=\"button\" class=\"dt__sort\" (click)=\"onHeaderClick(col)\">\r\n <span>{{ col.headerKey | translate }}</span>\r\n <span class=\"dt__sort-icon\" [attr.data-dir]=\"sortDirFor(col)\" aria-hidden=\"true\"></span>\r\n </button>\r\n } @else {\r\n {{ col.headerKey | translate }}\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @if (loading()) {\r\n @for (i of skeletonRows; track i) {\r\n <tr class=\"dt__row dt__row--skel\">\r\n <td [attr.colspan]=\"columns().length\">\r\n <!-- shape=\"lines\" is the DS skeleton's no-chrome text shimmer\r\n (the kit's former shape=\"text\"); one line per collapsed row.\r\n No backticks in here: this is an INLINE template literal. -->\r\n <fly-skeleton shape=\"lines\" [lines]=\"1\" />\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n @for (row of rows(); track $index) {\r\n <tr\r\n class=\"dt__row\"\r\n tabindex=\"0\"\r\n (click)=\"onRowActivate($event, row)\"\r\n (keydown.enter)=\"onRowActivate($event, row)\"\r\n >\r\n @for (col of columns(); track col.id) {\r\n <td\r\n [class.dt__td--end]=\"col.align === 'end'\"\r\n [class.mono]=\"col.kind === 'mono'\"\r\n [class.dt__td--date]=\"col.kind === 'date'\"\r\n [class.dt__td--num]=\"col.kind === 'number'\"\r\n [attr.data-label]=\"col.headerKey | translate\"\r\n >\r\n @if (templateFor(col.id); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: row }\" />\r\n } @else {\r\n @switch (col.kind ?? 'text') {\r\n @case ('date') {\r\n @if (cellValue(row, col); as value) {\r\n {{ $any(value) | date: 'yyyy-MM-dd' : 'UTC' }}\r\n } @else { \u2014 }\r\n }\r\n @default {\r\n {{ displayValue(row, col) }}\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n</table>\r\n@if (!loading() && rows().length === 0 && emptyKey()) {\r\n <fly-state-message kind=\"empty\" [messageKey]=\"emptyKey()\" [iconClass]=\"emptyIconClass()\" />\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:block;background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-card);container-type:inline-size}.dt{width:100%;border-collapse:collapse;font-size:var(--text-base)}.dt thead th{text-align:start;padding:var(--sp-2) var(--sp-3);font-size:12px;font-weight:var(--fw-bold);color:var(--ink-3);background:var(--bg-3);border-block-end:1px solid var(--w1)}.dt__th--end{text-align:end}.dt__sort{display:inline-flex;align-items:center;gap:var(--sp-1);padding:0;border:0;background:transparent;font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit;cursor:pointer}.dt__sort:hover{color:var(--ink)}.dt__sort:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.dt__sort-icon{inline-size:0;block-size:0;border-inline:4px solid transparent;border-block-start:5px solid var(--ink-4);opacity:.45;transition:transform var(--t-state),opacity var(--t-state)}.dt__sort-icon[data-dir=asc]{opacity:1;border-block-start-color:var(--accent);transform:rotate(180deg)}.dt__sort-icon[data-dir=desc]{opacity:1;border-block-start-color:var(--accent)}.dt tbody td{height:var(--row-h);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--line-3);color:var(--ink);transition:background var(--t-state)}.dt tbody tr:last-child td{border-block-end:0}.dt__row{cursor:pointer}.dt__row:hover td{background:var(--bg-hover)}.dt__row:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.dt__row--skel{cursor:default}.dt__row--skel:hover td{background:transparent}.dt__td--end{text-align:end}.dt__td--date,.dt__td--num{color:var(--ink-3);font-size:var(--text-sm);font-variant-numeric:tabular-nums}@container (width <= 720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}@media(width<=720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FlyStateMessageComponent, selector: "fly-state-message", inputs: ["kind", "messageKey", "iconClass", "noteKey", "retryLabelKey", "showRetry"], outputs: ["retried"] }, { kind: "component", type: FlySkeletonComponent, selector: "fly-skeleton", inputs: ["layout", "shape", "count", "lines", "animation", "fill", "messageKey", "announce"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23460
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyDataTableComponent, isStandalone: true, selector: "fly-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelKey: { classPropertyName: "ariaLabelKey", publicName: "ariaLabelKey", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, emptyKey: { classPropertyName: "emptyKey", publicName: "emptyKey", isSignal: true, isRequired: false, transformFunction: null }, emptyIconClass: { classPropertyName: "emptyIconClass", publicName: "emptyIconClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortChange: "sortChange", rowActivated: "rowActivated" }, queries: [{ propertyName: "cellTemplates", predicate: FlyCellDirective, isSignal: true }], ngImport: i0, template: "<table class=\"dt\" [attr.aria-label]=\"ariaLabelKey() ? (ariaLabelKey()! | translate) : null\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.id) {\r\n <th\r\n scope=\"col\"\r\n [class.dt__th--end]=\"col.align === 'end'\"\r\n [attr.aria-sort]=\"headerAriaSort(col)\"\r\n >\r\n @if (col.sortable) {\r\n <button type=\"button\" class=\"dt__sort\" (click)=\"onHeaderClick(col)\">\r\n <span>{{ col.headerKey | translate }}</span>\r\n <span class=\"dt__sort-icon\" [attr.data-dir]=\"sortDirFor(col)\" aria-hidden=\"true\"></span>\r\n </button>\r\n } @else {\r\n {{ col.headerKey | translate }}\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @if (loading()) {\r\n @for (i of skeletonRows; track i) {\r\n <tr class=\"dt__row dt__row--skel\">\r\n <td [attr.colspan]=\"columns().length\">\r\n <!-- shape=\"lines\" is the DS skeleton's no-chrome text shimmer\r\n (the kit's former shape=\"text\"); one line per collapsed row.\r\n No backticks in here: this is an INLINE template literal. -->\r\n <fly-skeleton shape=\"lines\" [lines]=\"1\" />\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n @for (row of rows(); track $index) {\r\n <tr\r\n class=\"dt__row\"\r\n tabindex=\"0\"\r\n (click)=\"onRowActivate($event, row)\"\r\n (keydown.enter)=\"onRowActivate($event, row)\"\r\n >\r\n @for (col of columns(); track col.id) {\r\n <td\r\n [class.dt__td--end]=\"col.align === 'end'\"\r\n [class.mono]=\"col.kind === 'mono'\"\r\n [class.dt__td--date]=\"col.kind === 'date'\"\r\n [class.dt__td--num]=\"col.kind === 'number'\"\r\n [attr.data-label]=\"col.headerKey | translate\"\r\n >\r\n @if (templateFor(col.id); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: row }\" />\r\n } @else {\r\n @switch (col.kind ?? 'text') {\r\n @case ('date') {\r\n @if (cellValue(row, col); as value) {\r\n {{ $any(value) | date: 'yyyy-MM-dd' : 'UTC' }}\r\n } @else { \u2014 }\r\n }\r\n @default {\r\n {{ displayValue(row, col) }}\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n</table>\r\n@if (!loading() && rows().length === 0 && emptyKey()) {\r\n <fly-state-message kind=\"empty\" [messageKey]=\"emptyKey()\" [iconClass]=\"emptyIconClass()\" />\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:block;background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-card);container-type:inline-size}.dt{width:100%;border-collapse:collapse;font-size:var(--text-base)}.dt thead th{text-align:start;padding:var(--sp-2) var(--sp-3);font-size:12px;font-weight:var(--fw-bold);color:var(--ink-3);background:var(--bg-3);border-block-end:1px solid var(--w1)}.dt__th--end{text-align:end}.dt__sort{display:inline-flex;align-items:center;gap:var(--sp-1);padding:0;border:0;background:transparent;font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit;cursor:pointer}.dt__sort:hover{color:var(--ink)}.dt__sort:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.dt__sort-icon{inline-size:0;block-size:0;border-inline:4px solid transparent;border-block-start:5px solid var(--ink-4);opacity:.45;transition:transform var(--t-state),opacity var(--t-state)}.dt__sort-icon[data-dir=asc]{opacity:1;border-block-start-color:var(--accent);transform:rotate(180deg)}.dt__sort-icon[data-dir=desc]{opacity:1;border-block-start-color:var(--accent)}.dt tbody td{height:var(--row-h);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--line-3);color:var(--ink);transition:background var(--t-state)}.dt tbody tr:last-child td{border-block-end:0}.dt__row{cursor:pointer}.dt__row:hover td{background:var(--bg-hover)}.dt__row:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px;outline-offset:-2px}.dt__row--skel{cursor:default}.dt__row--skel:hover td{background:transparent}.dt__td--end{text-align:end}.dt__td--date,.dt__td--num{color:var(--ink-3);font-size:var(--text-sm);font-variant-numeric:tabular-nums}@container (width <= 720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}@media(width<=720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FlyStateMessageComponent, selector: "fly-state-message", inputs: ["kind", "messageKey", "iconClass", "noteKey", "retryLabelKey", "showRetry"], outputs: ["retried"] }, { kind: "component", type: FlySkeletonComponent, selector: "fly-skeleton", inputs: ["layout", "shape", "count", "lines", "animation", "fill", "messageKey", "announce"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23436
23461
  }
23437
23462
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyDataTableComponent, decorators: [{
23438
23463
  type: Component,
23439
- args: [{ selector: 'fly-data-table', standalone: true, imports: [DatePipe, NgTemplateOutlet, TranslatePipe, FlyStateMessageComponent, FlySkeletonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<table class=\"dt\" [attr.aria-label]=\"ariaLabelKey() ? (ariaLabelKey()! | translate) : null\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.id) {\r\n <th\r\n scope=\"col\"\r\n [class.dt__th--end]=\"col.align === 'end'\"\r\n [attr.aria-sort]=\"headerAriaSort(col)\"\r\n >\r\n @if (col.sortable) {\r\n <button type=\"button\" class=\"dt__sort\" (click)=\"onHeaderClick(col)\">\r\n <span>{{ col.headerKey | translate }}</span>\r\n <span class=\"dt__sort-icon\" [attr.data-dir]=\"sortDirFor(col)\" aria-hidden=\"true\"></span>\r\n </button>\r\n } @else {\r\n {{ col.headerKey | translate }}\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @if (loading()) {\r\n @for (i of skeletonRows; track i) {\r\n <tr class=\"dt__row dt__row--skel\">\r\n <td [attr.colspan]=\"columns().length\">\r\n <!-- shape=\"lines\" is the DS skeleton's no-chrome text shimmer\r\n (the kit's former shape=\"text\"); one line per collapsed row.\r\n No backticks in here: this is an INLINE template literal. -->\r\n <fly-skeleton shape=\"lines\" [lines]=\"1\" />\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n @for (row of rows(); track $index) {\r\n <tr\r\n class=\"dt__row\"\r\n tabindex=\"0\"\r\n (click)=\"onRowActivate($event, row)\"\r\n (keydown.enter)=\"onRowActivate($event, row)\"\r\n >\r\n @for (col of columns(); track col.id) {\r\n <td\r\n [class.dt__td--end]=\"col.align === 'end'\"\r\n [class.mono]=\"col.kind === 'mono'\"\r\n [class.dt__td--date]=\"col.kind === 'date'\"\r\n [class.dt__td--num]=\"col.kind === 'number'\"\r\n [attr.data-label]=\"col.headerKey | translate\"\r\n >\r\n @if (templateFor(col.id); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: row }\" />\r\n } @else {\r\n @switch (col.kind ?? 'text') {\r\n @case ('date') {\r\n @if (cellValue(row, col); as value) {\r\n {{ $any(value) | date: 'yyyy-MM-dd' : 'UTC' }}\r\n } @else { \u2014 }\r\n }\r\n @default {\r\n {{ displayValue(row, col) }}\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n</table>\r\n@if (!loading() && rows().length === 0 && emptyKey()) {\r\n <fly-state-message kind=\"empty\" [messageKey]=\"emptyKey()\" [iconClass]=\"emptyIconClass()\" />\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:block;background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-card);container-type:inline-size}.dt{width:100%;border-collapse:collapse;font-size:var(--text-base)}.dt thead th{text-align:start;padding:var(--sp-2) var(--sp-3);font-size:12px;font-weight:var(--fw-bold);color:var(--ink-3);background:var(--bg-3);border-block-end:1px solid var(--w1)}.dt__th--end{text-align:end}.dt__sort{display:inline-flex;align-items:center;gap:var(--sp-1);padding:0;border:0;background:transparent;font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit;cursor:pointer}.dt__sort:hover{color:var(--ink)}.dt__sort:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.dt__sort-icon{inline-size:0;block-size:0;border-inline:4px solid transparent;border-block-start:5px solid var(--ink-4);opacity:.45;transition:transform var(--t-state),opacity var(--t-state)}.dt__sort-icon[data-dir=asc]{opacity:1;border-block-start-color:var(--accent);transform:rotate(180deg)}.dt__sort-icon[data-dir=desc]{opacity:1;border-block-start-color:var(--accent)}.dt tbody td{height:var(--row-h);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--line-3);color:var(--ink);transition:background var(--t-state)}.dt tbody tr:last-child td{border-block-end:0}.dt__row{cursor:pointer}.dt__row:hover td{background:var(--bg-hover)}.dt__row:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.dt__row--skel{cursor:default}.dt__row--skel:hover td{background:transparent}.dt__td--end{text-align:end}.dt__td--date,.dt__td--num{color:var(--ink-3);font-size:var(--text-sm);font-variant-numeric:tabular-nums}@container (width <= 720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}@media(width<=720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}\n"] }]
23464
+ args: [{ selector: 'fly-data-table', standalone: true, imports: [DatePipe, NgTemplateOutlet, TranslatePipe, FlyStateMessageComponent, FlySkeletonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<table class=\"dt\" [attr.aria-label]=\"ariaLabelKey() ? (ariaLabelKey()! | translate) : null\">\r\n <thead>\r\n <tr>\r\n @for (col of columns(); track col.id) {\r\n <th\r\n scope=\"col\"\r\n [class.dt__th--end]=\"col.align === 'end'\"\r\n [attr.aria-sort]=\"headerAriaSort(col)\"\r\n >\r\n @if (col.sortable) {\r\n <button type=\"button\" class=\"dt__sort\" (click)=\"onHeaderClick(col)\">\r\n <span>{{ col.headerKey | translate }}</span>\r\n <span class=\"dt__sort-icon\" [attr.data-dir]=\"sortDirFor(col)\" aria-hidden=\"true\"></span>\r\n </button>\r\n } @else {\r\n {{ col.headerKey | translate }}\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @if (loading()) {\r\n @for (i of skeletonRows; track i) {\r\n <tr class=\"dt__row dt__row--skel\">\r\n <td [attr.colspan]=\"columns().length\">\r\n <!-- shape=\"lines\" is the DS skeleton's no-chrome text shimmer\r\n (the kit's former shape=\"text\"); one line per collapsed row.\r\n No backticks in here: this is an INLINE template literal. -->\r\n <fly-skeleton shape=\"lines\" [lines]=\"1\" />\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n @for (row of rows(); track $index) {\r\n <tr\r\n class=\"dt__row\"\r\n tabindex=\"0\"\r\n (click)=\"onRowActivate($event, row)\"\r\n (keydown.enter)=\"onRowActivate($event, row)\"\r\n >\r\n @for (col of columns(); track col.id) {\r\n <td\r\n [class.dt__td--end]=\"col.align === 'end'\"\r\n [class.mono]=\"col.kind === 'mono'\"\r\n [class.dt__td--date]=\"col.kind === 'date'\"\r\n [class.dt__td--num]=\"col.kind === 'number'\"\r\n [attr.data-label]=\"col.headerKey | translate\"\r\n >\r\n @if (templateFor(col.id); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: row }\" />\r\n } @else {\r\n @switch (col.kind ?? 'text') {\r\n @case ('date') {\r\n @if (cellValue(row, col); as value) {\r\n {{ $any(value) | date: 'yyyy-MM-dd' : 'UTC' }}\r\n } @else { \u2014 }\r\n }\r\n @default {\r\n {{ displayValue(row, col) }}\r\n }\r\n }\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }\r\n </tbody>\r\n</table>\r\n@if (!loading() && rows().length === 0 && emptyKey()) {\r\n <fly-state-message kind=\"empty\" [messageKey]=\"emptyKey()\" [iconClass]=\"emptyIconClass()\" />\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:block;background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-card);container-type:inline-size}.dt{width:100%;border-collapse:collapse;font-size:var(--text-base)}.dt thead th{text-align:start;padding:var(--sp-2) var(--sp-3);font-size:12px;font-weight:var(--fw-bold);color:var(--ink-3);background:var(--bg-3);border-block-end:1px solid var(--w1)}.dt__th--end{text-align:end}.dt__sort{display:inline-flex;align-items:center;gap:var(--sp-1);padding:0;border:0;background:transparent;font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit;cursor:pointer}.dt__sort:hover{color:var(--ink)}.dt__sort:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.dt__sort-icon{inline-size:0;block-size:0;border-inline:4px solid transparent;border-block-start:5px solid var(--ink-4);opacity:.45;transition:transform var(--t-state),opacity var(--t-state)}.dt__sort-icon[data-dir=asc]{opacity:1;border-block-start-color:var(--accent);transform:rotate(180deg)}.dt__sort-icon[data-dir=desc]{opacity:1;border-block-start-color:var(--accent)}.dt tbody td{height:var(--row-h);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--line-3);color:var(--ink);transition:background var(--t-state)}.dt tbody tr:last-child td{border-block-end:0}.dt__row{cursor:pointer}.dt__row:hover td{background:var(--bg-hover)}.dt__row:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px;outline-offset:-2px}.dt__row--skel{cursor:default}.dt__row--skel:hover td{background:transparent}.dt__td--end{text-align:end}.dt__td--date,.dt__td--num{color:var(--ink-3);font-size:var(--text-sm);font-variant-numeric:tabular-nums}@container (width <= 720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}@media(width<=720px){.dt thead{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.dt,.dt tbody,.dt tbody tr,.dt tbody td{display:block}.dt__row{padding:var(--sp-2) 0;border-block-end:1px solid var(--line-3)}.dt__row:last-child{border-block-end:0}.dt tbody td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-3);height:auto;border-block-end:0;padding:var(--sp-1) var(--sp-3);text-align:end}.dt tbody td:before{content:attr(data-label);flex-shrink:0;font-size:var(--text-xs);font-weight:var(--fw-medium);color:var(--ink-4);text-align:start}}\n"] }]
23440
23465
  }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], ariaLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelKey", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], rowActivated: [{ type: i0.Output, args: ["rowActivated"] }], emptyKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyKey", required: false }] }], emptyIconClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyIconClass", required: false }] }], cellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FlyCellDirective), { isSignal: true }] }] } });
23441
23466
 
23442
23467
  /**
@@ -23713,7 +23738,7 @@ class FlySectionHeaderComponent {
23713
23738
  <ng-content select="[section-actions]" />
23714
23739
  </div>
23715
23740
  </header>
23716
- `, isInline: true, styles: [":host{display:block}.sh{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:13px 16px;border-block-end:1px solid var(--line-3)}.sh__t{margin:0;font-size:13px;font-weight:var(--fw-semibold);color:var(--ink);letter-spacing:-.005em;min-width:0}.sh__a{display:inline-flex;align-items:center;gap:var(--sp-1);flex-shrink:0}.sh__a ::ng-deep a:not([fly-button]),.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]){display:inline-flex;align-items:center;gap:5px;background:transparent;border:0;color:var(--accent);font-size:12px;font-weight:var(--fw-medium);cursor:pointer;padding:4px 6px;border-radius:var(--r-sm);font-family:inherit;text-decoration:none;transition:background var(--t-state)}.sh__a ::ng-deep a:not([fly-button]):hover,.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]):hover{background:color-mix(in srgb,var(--accent-soft) 50%,transparent)}.sh__a ::ng-deep a:not([fly-button]):focus-visible,.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]):focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23741
+ `, isInline: true, styles: [":host{display:block}.sh{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:13px 16px;border-block-end:1px solid var(--line-3)}.sh__t{margin:0;font-size:13px;font-weight:var(--fw-semibold);color:var(--ink);letter-spacing:-.005em;min-width:0}.sh__a{display:inline-flex;align-items:center;gap:var(--sp-1);flex-shrink:0}.sh__a ::ng-deep a:not([fly-button]),.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]){display:inline-flex;align-items:center;gap:5px;background:transparent;border:0;color:var(--accent);font-size:12px;font-weight:var(--fw-medium);cursor:pointer;padding:4px 6px;border-radius:var(--r-sm);font-family:inherit;text-decoration:none;transition:background var(--t-state)}.sh__a ::ng-deep a:not([fly-button]):hover,.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]):hover{background:color-mix(in srgb,var(--accent-soft) 50%,transparent)}.sh__a ::ng-deep a:not([fly-button]):focus-visible,.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]):focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23717
23742
  }
23718
23743
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlySectionHeaderComponent, decorators: [{
23719
23744
  type: Component,
@@ -23729,7 +23754,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
23729
23754
  <ng-content select="[section-actions]" />
23730
23755
  </div>
23731
23756
  </header>
23732
- `, styles: [":host{display:block}.sh{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:13px 16px;border-block-end:1px solid var(--line-3)}.sh__t{margin:0;font-size:13px;font-weight:var(--fw-semibold);color:var(--ink);letter-spacing:-.005em;min-width:0}.sh__a{display:inline-flex;align-items:center;gap:var(--sp-1);flex-shrink:0}.sh__a ::ng-deep a:not([fly-button]),.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]){display:inline-flex;align-items:center;gap:5px;background:transparent;border:0;color:var(--accent);font-size:12px;font-weight:var(--fw-medium);cursor:pointer;padding:4px 6px;border-radius:var(--r-sm);font-family:inherit;text-decoration:none;transition:background var(--t-state)}.sh__a ::ng-deep a:not([fly-button]):hover,.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]):hover{background:color-mix(in srgb,var(--accent-soft) 50%,transparent)}.sh__a ::ng-deep a:not([fly-button]):focus-visible,.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]):focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}\n"] }]
23757
+ `, styles: [":host{display:block}.sh{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:13px 16px;border-block-end:1px solid var(--line-3)}.sh__t{margin:0;font-size:13px;font-weight:var(--fw-semibold);color:var(--ink);letter-spacing:-.005em;min-width:0}.sh__a{display:inline-flex;align-items:center;gap:var(--sp-1);flex-shrink:0}.sh__a ::ng-deep a:not([fly-button]),.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]){display:inline-flex;align-items:center;gap:5px;background:transparent;border:0;color:var(--accent);font-size:12px;font-weight:var(--fw-medium);cursor:pointer;padding:4px 6px;border-radius:var(--r-sm);font-family:inherit;text-decoration:none;transition:background var(--t-state)}.sh__a ::ng-deep a:not([fly-button]):hover,.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]):hover{background:color-mix(in srgb,var(--accent-soft) 50%,transparent)}.sh__a ::ng-deep a:not([fly-button]):focus-visible,.sh__a ::ng-deep button:not([fly-button],[fly-icon-button]):focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}\n"] }]
23733
23758
  }], propDecorators: { titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }] } });
23734
23759
 
23735
23760
  /**
@@ -23972,7 +23997,7 @@ class FlyDetailShellComponent {
23972
23997
  <ng-content />
23973
23998
  </div>
23974
23999
  </div>
23975
- `, isInline: true, styles: [":host{display:block;container-type:inline-size}.ds__layout{display:grid;grid-template-columns:var(--fly-detail-aside, 300px) minmax(0,1fr);gap:var(--sp-4);align-items:start}.ds__aside{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0}.ds__aside .ds__rail{order:-1}.ds__pinned{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0}.ds__panel{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0;align-self:stretch}.ds__panel>:only-child{flex:1}.ds__rail{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-2);background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);box-shadow:var(--shadow-card)}.ds__tab{display:flex;align-items:center;gap:var(--sp-3);width:100%;padding:var(--sp-2);border:0;background:transparent;border-radius:var(--r-md);color:var(--ink-2);cursor:pointer;font-family:inherit;font-size:var(--text-sm);text-align:start;white-space:nowrap;overflow:hidden;transition:background var(--t-state),color var(--t-state)}.ds__tab:hover{background:var(--w06);color:var(--ink)}.ds__tab:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ds__tab--active{background:var(--accent-fill);color:var(--on-accent-fill);font-weight:var(--fw-semibold)}.ds__tab-ico{font-size:var(--text-md);flex-shrink:0;width:20px;text-align:center}.ds__tab-label{min-width:0;overflow:hidden;text-overflow:ellipsis}@container (width <= 980px){.ds__layout{grid-template-columns:minmax(0,1fr)}.ds__rail{flex-flow:row wrap}.ds__tab{width:auto}}@media(width<=980px){.ds__layout{grid-template-columns:minmax(0,1fr)}.ds__rail{flex-flow:row wrap}.ds__tab{width:auto}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24000
+ `, isInline: true, styles: [":host{display:block;container-type:inline-size}.ds__layout{display:grid;grid-template-columns:var(--fly-detail-aside, 300px) minmax(0,1fr);gap:var(--sp-4);align-items:start}.ds__aside{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0}.ds__aside .ds__rail{order:-1}.ds__pinned{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0}.ds__panel{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0;align-self:stretch}.ds__panel>:only-child{flex:1}.ds__rail{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-2);background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);box-shadow:var(--shadow-card)}.ds__tab{display:flex;align-items:center;gap:var(--sp-3);width:100%;padding:var(--sp-2);border:0;background:transparent;border-radius:var(--r-md);color:var(--ink-2);cursor:pointer;font-family:inherit;font-size:var(--text-sm);text-align:start;white-space:nowrap;overflow:hidden;transition:background var(--t-state),color var(--t-state)}.ds__tab:hover{background:var(--w06);color:var(--ink)}.ds__tab:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.ds__tab--active{background:var(--accent-fill);color:var(--on-accent-fill);font-weight:var(--fw-semibold)}.ds__tab-ico{font-size:var(--text-md);flex-shrink:0;width:20px;text-align:center}.ds__tab-label{min-width:0;overflow:hidden;text-overflow:ellipsis}@container (width <= 980px){.ds__layout{grid-template-columns:minmax(0,1fr)}.ds__rail{flex-flow:row wrap}.ds__tab{width:auto}}@media(width<=980px){.ds__layout{grid-template-columns:minmax(0,1fr)}.ds__rail{flex-flow:row wrap}.ds__tab{width:auto}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23976
24001
  }
23977
24002
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyDetailShellComponent, decorators: [{
23978
24003
  type: Component,
@@ -24025,7 +24050,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
24025
24050
  <ng-content />
24026
24051
  </div>
24027
24052
  </div>
24028
- `, styles: [":host{display:block;container-type:inline-size}.ds__layout{display:grid;grid-template-columns:var(--fly-detail-aside, 300px) minmax(0,1fr);gap:var(--sp-4);align-items:start}.ds__aside{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0}.ds__aside .ds__rail{order:-1}.ds__pinned{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0}.ds__panel{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0;align-self:stretch}.ds__panel>:only-child{flex:1}.ds__rail{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-2);background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);box-shadow:var(--shadow-card)}.ds__tab{display:flex;align-items:center;gap:var(--sp-3);width:100%;padding:var(--sp-2);border:0;background:transparent;border-radius:var(--r-md);color:var(--ink-2);cursor:pointer;font-family:inherit;font-size:var(--text-sm);text-align:start;white-space:nowrap;overflow:hidden;transition:background var(--t-state),color var(--t-state)}.ds__tab:hover{background:var(--w06);color:var(--ink)}.ds__tab:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ds__tab--active{background:var(--accent-fill);color:var(--on-accent-fill);font-weight:var(--fw-semibold)}.ds__tab-ico{font-size:var(--text-md);flex-shrink:0;width:20px;text-align:center}.ds__tab-label{min-width:0;overflow:hidden;text-overflow:ellipsis}@container (width <= 980px){.ds__layout{grid-template-columns:minmax(0,1fr)}.ds__rail{flex-flow:row wrap}.ds__tab{width:auto}}@media(width<=980px){.ds__layout{grid-template-columns:minmax(0,1fr)}.ds__rail{flex-flow:row wrap}.ds__tab{width:auto}}\n"] }]
24053
+ `, styles: [":host{display:block;container-type:inline-size}.ds__layout{display:grid;grid-template-columns:var(--fly-detail-aside, 300px) minmax(0,1fr);gap:var(--sp-4);align-items:start}.ds__aside{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0}.ds__aside .ds__rail{order:-1}.ds__pinned{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0}.ds__panel{display:flex;flex-direction:column;gap:var(--sp-4);min-width:0;align-self:stretch}.ds__panel>:only-child{flex:1}.ds__rail{display:flex;flex-direction:column;gap:var(--sp-1);padding:var(--sp-2);background:var(--bg-2);border:1px solid var(--w08);border-radius:var(--r-lg);box-shadow:var(--shadow-card)}.ds__tab{display:flex;align-items:center;gap:var(--sp-3);width:100%;padding:var(--sp-2);border:0;background:transparent;border-radius:var(--r-md);color:var(--ink-2);cursor:pointer;font-family:inherit;font-size:var(--text-sm);text-align:start;white-space:nowrap;overflow:hidden;transition:background var(--t-state),color var(--t-state)}.ds__tab:hover{background:var(--w06);color:var(--ink)}.ds__tab:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.ds__tab--active{background:var(--accent-fill);color:var(--on-accent-fill);font-weight:var(--fw-semibold)}.ds__tab-ico{font-size:var(--text-md);flex-shrink:0;width:20px;text-align:center}.ds__tab-label{min-width:0;overflow:hidden;text-overflow:ellipsis}@container (width <= 980px){.ds__layout{grid-template-columns:minmax(0,1fr)}.ds__rail{flex-flow:row wrap}.ds__tab{width:auto}}@media(width<=980px){.ds__layout{grid-template-columns:minmax(0,1fr)}.ds__rail{flex-flow:row wrap}.ds__tab{width:auto}}\n"] }]
24029
24054
  }], propDecorators: { rail: [{ type: i0.ViewChild, args: ['rail', { isSignal: true }] }], sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], sectionsLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "sectionsLabelKey", required: false }] }] } });
24030
24055
 
24031
24056
  /** Every module across every section, in visual order. */
@@ -24159,10 +24184,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
24159
24184
  * Standalone (no dock anywhere above), nothing happens and the bar renders as the
24160
24185
  * app's own first row, exactly as before.
24161
24186
  *
24162
- * a11y: the trigger is `aria-haspopup="menu"` + `aria-expanded`; the popover is
24163
- * `role="menu"` with `role="menuitem"` rows carrying `aria-current="page"` on
24164
- * the active one. Arrow keys rove (RTL-aware, wrapping, skipping disabled),
24165
- * Home/End jump, Escape closes and returns focus to the trigger, and a click
24187
+ * The trigger is split in two: the anchor (icon + label) is a breadcrumb —
24188
+ * click it and it re-activates the current module, the same "back to the
24189
+ * register" nav a popover row for it already performs, without opening the
24190
+ * popover. The chevron alone is the switcher's `aria-haspopup="menu"` +
24191
+ * `aria-expanded` trigger. The popover is `role="menu"` with `role="menuitem"`
24192
+ * rows carrying `aria-current="page"` on the active one.
24193
+ *
24194
+ * a11y: arrow keys rove the popover (RTL-aware, wrapping, skipping disabled),
24195
+ * Home/End jump, Escape closes and returns focus to the chevron, and a click
24166
24196
  * outside closes. Only the topmost overlay answers Escape, so a switcher opened
24167
24197
  * over a drawer closes alone.
24168
24198
  */
@@ -24204,22 +24234,19 @@ class FlyAppTopbarComponent {
24204
24234
  pendingFocus = signal(false, ...(ngDevMode ? [{ debugName: "pendingFocus" }] : /* istanbul ignore next */ []));
24205
24235
  flat = computed(() => flattenModules(this.sections()), ...(ngDevMode ? [{ debugName: "flat" }] : /* istanbul ignore next */ []));
24206
24236
  activeModule = computed(() => resolveActiveModule(this.sections(), this.activeKey()), ...(ngDevMode ? [{ debugName: "activeModule" }] : /* istanbul ignore next */ []));
24207
- // Both trigger names must START with the button's visible text ("Circles",
24237
+ // The brand name must START with the button's visible text ("Circles",
24208
24238
  // "Signals") — voice-control users activate controls by saying what they see,
24209
- // so a name that omits it fails WCAG 2.5.3 Label in Name. The action context
24210
- // is appended after the visible text; the popover menu keeps the plain
24211
- // "Switch module" name since it renders no visible text of its own.
24239
+ // so a name that omits it fails WCAG 2.5.3 Label in Name. The module anchor
24240
+ // needs no such override: its accessible name IS its visible text (icon
24241
+ // aria-hidden + label span), trivially compliant. The chevron and the popover
24242
+ // menu are icon-only / render no visible text of their own, so both keep the
24243
+ // plain "Switch module" name.
24212
24244
  brandAriaLabel = computed(() => {
24213
24245
  const home = this.i18n.t('ui.nav.home');
24214
24246
  const key = this.brandLabelKey();
24215
24247
  return key ? `${this.i18n.t(key)}, ${home}` : home;
24216
24248
  }, ...(ngDevMode ? [{ debugName: "brandAriaLabel" }] : /* istanbul ignore next */ []));
24217
24249
  switchAriaLabel = computed(() => this.i18n.t('ui.nav.switchModule'), ...(ngDevMode ? [{ debugName: "switchAriaLabel" }] : /* istanbul ignore next */ []));
24218
- triggerAriaLabel = computed(() => {
24219
- const active = this.activeModule();
24220
- const visible = active ? this.i18n.t(active.labelKey) : this.i18n.t('ui.nav.selectModule');
24221
- return `${visible}, ${this.i18n.t('ui.nav.switchModule')}`;
24222
- }, ...(ngDevMode ? [{ debugName: "triggerAriaLabel" }] : /* istanbul ignore next */ []));
24223
24250
  constructor() {
24224
24251
  inject(DestroyRef).onDestroy(() => overlayStack.remove(this.stackHandle));
24225
24252
  // After the FIRST render, not on every one: the dock is host chrome, which is
@@ -24256,6 +24283,23 @@ class FlyAppTopbarComponent {
24256
24283
  else
24257
24284
  this.openMenu();
24258
24285
  }
24286
+ /**
24287
+ * The anchor (icon + label) is a breadcrumb crumb, not the switcher's
24288
+ * trigger — that's the chevron's job now. Clicking it re-activates the
24289
+ * CURRENT module, the same "back to the register" navigation a click on its
24290
+ * own row in the popover already performs, without opening the popover to
24291
+ * get there. Only when nothing is active yet (the neutral "Select a
24292
+ * module" state, nothing to go back to) does it fall back to opening the
24293
+ * switcher, matching the old combined-trigger behaviour for that state.
24294
+ */
24295
+ onAnchorClick() {
24296
+ const active = this.activeModule();
24297
+ if (active) {
24298
+ this.select(active);
24299
+ return;
24300
+ }
24301
+ this.toggle();
24302
+ }
24259
24303
  openMenu() {
24260
24304
  // Start focus on the active row when there is one, so the keyboard lands
24261
24305
  // where the user already is rather than at the top of the list.
@@ -24339,14 +24383,14 @@ class FlyAppTopbarComponent {
24339
24383
  this.rows()[index]?.nativeElement.focus();
24340
24384
  }
24341
24385
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyAppTopbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
24342
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyAppTopbarComponent, isStandalone: true, selector: "fly-app-topbar", inputs: { brandLabelKey: { classPropertyName: "brandLabelKey", publicName: "brandLabelKey", isSignal: true, isRequired: false, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, activeKey: { classPropertyName: "activeKey", publicName: "activeKey", isSignal: true, isRequired: false, transformFunction: null }, footerLabel: { classPropertyName: "footerLabel", publicName: "footerLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { moduleSelected: "moduleSelected", brandSelected: "brandSelected" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, properties: { "class.fly-topbar--docked": "docked()" } }, queries: [{ propertyName: "icons", predicate: FlyModuleIconDirective, isSignal: true }], viewQueries: [{ propertyName: "rows", predicate: ["row"], descendants: true, isSignal: true }, { propertyName: "trigger", predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: "<header class=\"fly-topbar\">\r\n <div class=\"fly-topbar__lead\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-topbar__brand\"\r\n (click)=\"brandSelected.emit()\"\r\n [attr.aria-label]=\"brandAriaLabel()\"\r\n >\r\n <span class=\"fly-topbar__brand-mark\"><ng-content select=\"[app-topbar-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"fly-topbar__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n\r\n @if (activeModule()) {\r\n <span class=\"fly-topbar__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n\r\n <div class=\"fly-topbar__anchor\" (flyClickOutside)=\"close()\" [flyClickOutsideEnabled]=\"open()\">\r\n <button\r\n #trigger\r\n type=\"button\"\r\n class=\"fly-topbar__module\"\r\n [class.fly-topbar__module--on]=\"open()\"\r\n (click)=\"toggle()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n aria-haspopup=\"menu\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-label]=\"triggerAriaLabel()\"\r\n >\r\n @if (activeModule(); as active) {\r\n <span class=\"fly-topbar__module-icon\">\r\n @if (iconFor(active.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (active.iconClass) {\r\n <i [class]=\"active.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__module-label\">{{ active.labelKey | translate }}</span>\r\n } @else {\r\n <span class=\"fly-topbar__module-label fly-topbar__module-label--empty\">\r\n {{ 'ui.nav.selectModule' | translate }}\r\n </span>\r\n }\r\n <svg class=\"fly-topbar__chevron\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n\r\n @if (open()) {\r\n <div class=\"fly-topbar__pop\" role=\"menu\" [attr.aria-label]=\"switchAriaLabel()\">\r\n <div class=\"fly-topbar__cols\">\r\n @for (section of sections(); track $index) {\r\n <div class=\"fly-topbar__col\">\r\n @if (section.titleKey; as titleKey) {\r\n <div class=\"fly-topbar__col-title\">{{ titleKey | translate }}</div>\r\n }\r\n @for (mod of section.modules; track mod.key) {\r\n <button\r\n #row\r\n type=\"button\"\r\n class=\"fly-topbar__item\"\r\n [class.fly-topbar__item--on]=\"mod.key === activeKey()\"\r\n role=\"menuitem\"\r\n [disabled]=\"mod.disabled ?? false\"\r\n [attr.tabindex]=\"indexOf(mod) === focusIndex() ? 0 : -1\"\r\n [attr.aria-current]=\"mod.key === activeKey() ? 'page' : null\"\r\n (click)=\"select(mod)\"\r\n (keydown)=\"onRowKeydown($event)\"\r\n >\r\n <span class=\"fly-topbar__item-icon\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__item-main\">\r\n <span class=\"fly-topbar__item-label\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"fly-topbar__item-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n @if (footerLabel()) {\r\n <div class=\"fly-topbar__foot\">{{ footerLabel() }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fly-topbar__actions\"><ng-content select=\"[app-topbar-actions]\" /></div>\r\n</header>\r\n", styles: [":host{display:block;position:relative;z-index:var(--z-sticky)}.fly-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--w1);background:var(--bg-3)}.fly-topbar__lead{display:flex;align-items:center;gap:var(--sp-2);min-inline-size:0}.fly-topbar__brand,.fly-topbar__module{display:inline-flex;align-items:center;gap:var(--sp-2);appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__brand:hover,.fly-topbar__module:hover{background:var(--bg-hover)}.fly-topbar__brand:focus-visible,.fly-topbar__module:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fly-topbar__brand-name{font-weight:var(--fw-semibold);white-space:nowrap}.fly-topbar__brand-mark{display:inline-flex;align-items:center;max-block-size:var(--icon-lg)}.fly-topbar__sep{color:var(--ink-4);-webkit-user-select:none;user-select:none}.fly-topbar__module{min-inline-size:0}.fly-topbar__module--on{background:var(--bg-hover)}.fly-topbar__module-label{font-weight:var(--fw-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-topbar__module-label--empty{color:var(--ink-3)}.fly-topbar__module-icon,.fly-topbar__item-icon{display:inline-flex;align-items:center;justify-content:center;inline-size:var(--icon-md);block-size:var(--icon-md);flex:0 0 auto;color:var(--accent)}.fly-topbar__chevron{flex:0 0 auto;color:var(--ink-3);transition:transform var(--t-state)}.fly-topbar__module--on .fly-topbar__chevron{transform:rotate(180deg)}.fly-topbar__anchor{position:relative}:host(.fly-topbar--docked){flex:1 1 auto;min-inline-size:0;z-index:auto}:host(.fly-topbar--docked) .fly-topbar{padding:0;background:transparent;border-block-end:0}:host(.fly-topbar--docked) .fly-topbar__lead{gap:2px}:host(.fly-topbar--docked) .fly-topbar__brand,:host(.fly-topbar--docked) .fly-topbar__module{block-size:26px;padding-block:0;padding-inline:var(--sp-2);border-radius:var(--r-md);gap:6px;font-size:var(--text-sm);line-height:1;color:var(--w55)}:host(.fly-topbar--docked) .fly-topbar__brand:hover,:host(.fly-topbar--docked) .fly-topbar__module:hover{background:var(--w08);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module{background:var(--w06);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module--on{background:var(--w08)}:host(.fly-topbar--docked) .fly-topbar__brand-name{font-weight:var(--fw-medium)}:host(.fly-topbar--docked) .fly-topbar__module-label{font-weight:var(--fw-semibold);letter-spacing:-.006em}:host-context([dir=rtl]) :host(.fly-topbar--docked) .fly-topbar__module-label{letter-spacing:normal}:host(.fly-topbar--docked) .fly-topbar__sep{position:relative;display:inline-block;inline-size:7px;block-size:7px;color:transparent;border-block-start:1.5px solid var(--w28);border-inline-end:1.5px solid var(--w28);transform:rotate(45deg)}:host-context([dir=rtl]) :host(.fly-topbar--docked) .fly-topbar__sep{transform:rotate(-135deg)}:host(.fly-topbar--docked) .fly-topbar__actions{display:none}:host(.fly-topbar--docked) .fly-topbar__module-icon{inline-size:14px;block-size:14px}:host(.fly-topbar--docked) .fly-topbar__brand-mark{max-block-size:14px}:host(.fly-topbar--docked) .fly-topbar__brand-mark ::ng-deep *{max-inline-size:14px;max-block-size:14px}.fly-topbar__pop{position:absolute;inset-block-start:calc(100% + var(--sp-1));inset-inline-start:0;z-index:var(--z-overlay);min-inline-size:260px;max-inline-size:min(680px,92vw);padding:var(--sp-3);border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-topbar__pop{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-topbar__pop:before,.fly-topbar__pop:after{display:none}}@media(prefers-contrast:more){.fly-topbar__pop{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-topbar__pop:after{animation:none}}.fly-topbar__cols{display:flex;gap:var(--sp-4);align-items:flex-start}@media(width<=720px){.fly-topbar__cols{flex-direction:column;gap:var(--sp-3)}}.fly-topbar__col{display:flex;flex-direction:column;gap:2px;min-inline-size:220px;flex:1 1 0}.fly-topbar__col-title{font-size:var(--text-2xs);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-3);padding:var(--sp-2) var(--sp-2) var(--sp-1)}.fly-topbar__item{display:flex;align-items:flex-start;gap:var(--sp-2);inline-size:100%;text-align:start;appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__item:hover:not(:disabled){background:var(--w1)}.fly-topbar__item:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}.fly-topbar__item:disabled{opacity:.5;cursor:default}.fly-topbar__item--on{background:var(--accent-soft);color:var(--on-accent-soft);box-shadow:inset 2px 0 0 0 var(--accent)}.fly-topbar__item-main{display:flex;flex-direction:column;gap:1px;min-inline-size:0}.fly-topbar__item-label{font-weight:var(--fw-medium);line-height:1.3}.fly-topbar__item-desc{font-size:var(--text-xs);color:var(--ink-3);line-height:1.35}.fly-topbar__foot{margin-block-start:var(--sp-3);padding-block-start:var(--sp-2);border-block-start:.5px solid var(--w08);font-size:var(--text-2xs);color:var(--ink-4)}.fly-topbar__actions{display:flex;align-items:center;gap:var(--sp-2);flex:0 0 auto}@media(forced-colors:active){.fly-topbar__item--on{border-inline-start:2px solid CanvasText}}@media(prefers-reduced-motion:reduce){.fly-topbar__brand,.fly-topbar__module,.fly-topbar__item,.fly-topbar__chevron{transition:none}}\n"], dependencies: [{ kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled", "flyClickOutsideIgnore"], outputs: ["flyClickOutside"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24386
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyAppTopbarComponent, isStandalone: true, selector: "fly-app-topbar", inputs: { brandLabelKey: { classPropertyName: "brandLabelKey", publicName: "brandLabelKey", isSignal: true, isRequired: false, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, activeKey: { classPropertyName: "activeKey", publicName: "activeKey", isSignal: true, isRequired: false, transformFunction: null }, footerLabel: { classPropertyName: "footerLabel", publicName: "footerLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { moduleSelected: "moduleSelected", brandSelected: "brandSelected" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, properties: { "class.fly-topbar--docked": "docked()" } }, queries: [{ propertyName: "icons", predicate: FlyModuleIconDirective, isSignal: true }], viewQueries: [{ propertyName: "rows", predicate: ["row"], descendants: true, isSignal: true }, { propertyName: "trigger", predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: "<header class=\"fly-topbar\">\r\n <div class=\"fly-topbar__lead\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-topbar__brand\"\r\n (click)=\"brandSelected.emit()\"\r\n [attr.aria-label]=\"brandAriaLabel()\"\r\n >\r\n <span class=\"fly-topbar__brand-mark\"><ng-content select=\"[app-topbar-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"fly-topbar__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n\r\n @if (activeModule()) {\r\n <span class=\"fly-topbar__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n\r\n <div class=\"fly-topbar__anchor\" (flyClickOutside)=\"close()\" [flyClickOutsideEnabled]=\"open()\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-topbar__module\"\r\n [class.fly-topbar__module--on]=\"open()\"\r\n (click)=\"onAnchorClick()\"\r\n >\r\n @if (activeModule(); as active) {\r\n <span class=\"fly-topbar__module-icon\">\r\n @if (iconFor(active.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (active.iconClass) {\r\n <i [class]=\"active.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__module-label\">{{ active.labelKey | translate }}</span>\r\n } @else {\r\n <span class=\"fly-topbar__module-label fly-topbar__module-label--empty\">\r\n {{ 'ui.nav.selectModule' | translate }}\r\n </span>\r\n }\r\n </button>\r\n\r\n <button\r\n #trigger\r\n type=\"button\"\r\n class=\"fly-topbar__chevron-btn\"\r\n [class.fly-topbar__chevron-btn--on]=\"open()\"\r\n (click)=\"toggle()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n aria-haspopup=\"menu\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-label]=\"switchAriaLabel()\"\r\n >\r\n <svg class=\"fly-topbar__chevron\" [class.fly-topbar__chevron--on]=\"open()\" width=\"11\" height=\"11\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n\r\n @if (open()) {\r\n <div class=\"fly-topbar__pop\" role=\"menu\" [attr.aria-label]=\"switchAriaLabel()\">\r\n <div class=\"fly-topbar__cols\">\r\n @for (section of sections(); track $index) {\r\n <div class=\"fly-topbar__col\">\r\n @if (section.titleKey; as titleKey) {\r\n <div class=\"fly-topbar__col-title\">{{ titleKey | translate }}</div>\r\n }\r\n @for (mod of section.modules; track mod.key) {\r\n <button\r\n #row\r\n type=\"button\"\r\n class=\"fly-topbar__item\"\r\n [class.fly-topbar__item--on]=\"mod.key === activeKey()\"\r\n role=\"menuitem\"\r\n [disabled]=\"mod.disabled ?? false\"\r\n [attr.tabindex]=\"indexOf(mod) === focusIndex() ? 0 : -1\"\r\n [attr.aria-current]=\"mod.key === activeKey() ? 'page' : null\"\r\n (click)=\"select(mod)\"\r\n (keydown)=\"onRowKeydown($event)\"\r\n >\r\n <span class=\"fly-topbar__item-icon\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__item-main\">\r\n <span class=\"fly-topbar__item-label\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"fly-topbar__item-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n @if (footerLabel()) {\r\n <div class=\"fly-topbar__foot\">{{ footerLabel() }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fly-topbar__actions\"><ng-content select=\"[app-topbar-actions]\" /></div>\r\n</header>\r\n", styles: [":host{display:block;position:relative;z-index:var(--z-sticky)}.fly-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--w1);background:var(--bg-3)}.fly-topbar__lead{display:flex;align-items:center;gap:var(--sp-2);min-inline-size:0}.fly-topbar__brand,.fly-topbar__module{display:inline-flex;align-items:center;gap:var(--sp-2);appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__brand:hover,.fly-topbar__module:hover{background:var(--bg-hover)}.fly-topbar__brand:focus-visible,.fly-topbar__module:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.fly-topbar__brand-name{font-weight:var(--fw-semibold);white-space:nowrap}.fly-topbar__brand-mark{display:inline-flex;align-items:center;max-block-size:var(--icon-lg)}.fly-topbar__sep{color:var(--ink-4);-webkit-user-select:none;user-select:none}.fly-topbar__module{min-inline-size:0;border-start-end-radius:0;border-end-end-radius:0}.fly-topbar__module--on{background:var(--bg-hover)}.fly-topbar__module-label{font-weight:var(--fw-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-topbar__module-label--empty{color:var(--ink-3)}.fly-topbar__module-icon,.fly-topbar__item-icon{display:inline-flex;align-items:center;justify-content:center;inline-size:var(--icon-md);block-size:var(--icon-md);flex:0 0 auto;color:var(--accent)}.fly-topbar__chevron-btn{display:inline-flex;align-items:center;justify-content:center;align-self:stretch;flex:0 0 auto;appearance:none;border:0;background:transparent;cursor:pointer;color:var(--ink-3);padding:var(--sp-1);border-radius:var(--r-md);border-start-start-radius:0;border-end-start-radius:0;transition:background var(--t-state)}.fly-topbar__chevron-btn:hover,.fly-topbar__chevron-btn--on{background:var(--bg-hover)}.fly-topbar__chevron-btn:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.fly-topbar__chevron{flex:0 0 auto;color:inherit;transition:transform var(--t-state)}.fly-topbar__chevron--on{transform:rotate(180deg)}.fly-topbar__anchor{position:relative;display:inline-flex;align-items:center;gap:0;min-inline-size:0}:host(.fly-topbar--docked){flex:1 1 auto;min-inline-size:0;z-index:auto}:host(.fly-topbar--docked) .fly-topbar{padding:0;background:transparent;border-block-end:0}:host(.fly-topbar--docked) .fly-topbar__lead{gap:2px}:host(.fly-topbar--docked) .fly-topbar__brand,:host(.fly-topbar--docked) .fly-topbar__module{block-size:26px;padding-block:0;padding-inline:var(--sp-2);gap:6px;font-size:var(--text-sm);line-height:1;color:var(--w55)}:host(.fly-topbar--docked) .fly-topbar__brand:hover,:host(.fly-topbar--docked) .fly-topbar__module:hover{background:var(--w12);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__chevron-btn{block-size:26px;padding-block:0;padding-inline:var(--sp-2);background:var(--w06);color:var(--w55)}:host(.fly-topbar--docked) .fly-topbar__chevron-btn:hover{background:var(--w12);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__chevron-btn--on,:host(.fly-topbar--docked) .fly-topbar__chevron-btn--on:hover{background:var(--w18);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module{background:var(--w06);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module--on,:host(.fly-topbar--docked) .fly-topbar__module--on:hover{background:var(--w18)}:host(.fly-topbar--docked) .fly-topbar__brand-name{font-weight:var(--fw-medium)}:host(.fly-topbar--docked) .fly-topbar__module-label{font-weight:var(--fw-semibold);letter-spacing:-.006em}:host-context([dir=rtl]) :host(.fly-topbar--docked) .fly-topbar__module-label{letter-spacing:normal}:host(.fly-topbar--docked) .fly-topbar__sep{position:relative;display:inline-block;inline-size:7px;block-size:7px;color:transparent;border-block-start:1.5px solid var(--w28);border-inline-end:1.5px solid var(--w28);transform:rotate(45deg)}:host-context([dir=rtl]) :host(.fly-topbar--docked) .fly-topbar__sep{transform:rotate(-135deg)}:host(.fly-topbar--docked) .fly-topbar__actions{display:none}:host(.fly-topbar--docked) .fly-topbar__module-icon{inline-size:14px;block-size:14px}:host(.fly-topbar--docked) .fly-topbar__brand-mark{max-block-size:14px}:host(.fly-topbar--docked) .fly-topbar__brand-mark ::ng-deep *{max-inline-size:14px;max-block-size:14px}.fly-topbar__pop{position:absolute;inset-block-start:calc(100% + var(--sp-1));inset-inline-start:0;z-index:var(--z-overlay);min-inline-size:260px;max-inline-size:min(680px,92vw);padding:var(--sp-3);border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-topbar__pop{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-topbar__pop:before,.fly-topbar__pop:after{display:none}}@media(prefers-contrast:more){.fly-topbar__pop{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-topbar__pop:after{animation:none}}.fly-topbar__cols{display:flex;gap:var(--sp-4);align-items:flex-start}@media(width<=720px){.fly-topbar__cols{flex-direction:column;gap:var(--sp-3)}}.fly-topbar__col{display:flex;flex-direction:column;gap:2px;min-inline-size:220px;flex:1 1 0}.fly-topbar__col-title{font-size:var(--text-2xs);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-3);padding:var(--sp-2) var(--sp-2) var(--sp-1)}.fly-topbar__item{display:flex;align-items:flex-start;gap:var(--sp-2);inline-size:100%;text-align:start;appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__item:hover:not(:disabled){background:var(--w1)}.fly-topbar__item:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:-2px}.fly-topbar__item:disabled{opacity:.5;cursor:default}.fly-topbar__item--on{background:var(--accent-soft);color:var(--on-accent-soft);box-shadow:inset 2px 0 0 0 var(--accent)}.fly-topbar__item-main{display:flex;flex-direction:column;gap:1px;min-inline-size:0}.fly-topbar__item-label{font-weight:var(--fw-medium);line-height:1.3}.fly-topbar__item-desc{font-size:var(--text-xs);color:var(--ink-3);line-height:1.35}.fly-topbar__foot{margin-block-start:var(--sp-3);padding-block-start:var(--sp-2);border-block-start:.5px solid var(--w08);font-size:var(--text-2xs);color:var(--ink-4)}.fly-topbar__actions{display:flex;align-items:center;gap:var(--sp-2);flex:0 0 auto}@media(forced-colors:active){.fly-topbar__item--on{border-inline-start:2px solid CanvasText}}@media(prefers-reduced-motion:reduce){.fly-topbar__brand,.fly-topbar__module,.fly-topbar__chevron-btn,.fly-topbar__item,.fly-topbar__chevron{transition:none}}\n"], dependencies: [{ kind: "directive", type: FlyClickOutsideDirective, selector: "[flyClickOutside]", inputs: ["flyClickOutsideEnabled", "flyClickOutsideIgnore"], outputs: ["flyClickOutside"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24343
24387
  }
24344
24388
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyAppTopbarComponent, decorators: [{
24345
24389
  type: Component,
24346
24390
  args: [{ selector: 'fly-app-topbar', standalone: true, imports: [TranslatePipe, FlyClickOutsideDirective, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
24347
24391
  '(document:keydown.escape)': 'onEscape()',
24348
24392
  '[class.fly-topbar--docked]': 'docked()',
24349
- }, template: "<header class=\"fly-topbar\">\r\n <div class=\"fly-topbar__lead\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-topbar__brand\"\r\n (click)=\"brandSelected.emit()\"\r\n [attr.aria-label]=\"brandAriaLabel()\"\r\n >\r\n <span class=\"fly-topbar__brand-mark\"><ng-content select=\"[app-topbar-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"fly-topbar__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n\r\n @if (activeModule()) {\r\n <span class=\"fly-topbar__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n\r\n <div class=\"fly-topbar__anchor\" (flyClickOutside)=\"close()\" [flyClickOutsideEnabled]=\"open()\">\r\n <button\r\n #trigger\r\n type=\"button\"\r\n class=\"fly-topbar__module\"\r\n [class.fly-topbar__module--on]=\"open()\"\r\n (click)=\"toggle()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n aria-haspopup=\"menu\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-label]=\"triggerAriaLabel()\"\r\n >\r\n @if (activeModule(); as active) {\r\n <span class=\"fly-topbar__module-icon\">\r\n @if (iconFor(active.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (active.iconClass) {\r\n <i [class]=\"active.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__module-label\">{{ active.labelKey | translate }}</span>\r\n } @else {\r\n <span class=\"fly-topbar__module-label fly-topbar__module-label--empty\">\r\n {{ 'ui.nav.selectModule' | translate }}\r\n </span>\r\n }\r\n <svg class=\"fly-topbar__chevron\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n aria-hidden=\"true\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n\r\n @if (open()) {\r\n <div class=\"fly-topbar__pop\" role=\"menu\" [attr.aria-label]=\"switchAriaLabel()\">\r\n <div class=\"fly-topbar__cols\">\r\n @for (section of sections(); track $index) {\r\n <div class=\"fly-topbar__col\">\r\n @if (section.titleKey; as titleKey) {\r\n <div class=\"fly-topbar__col-title\">{{ titleKey | translate }}</div>\r\n }\r\n @for (mod of section.modules; track mod.key) {\r\n <button\r\n #row\r\n type=\"button\"\r\n class=\"fly-topbar__item\"\r\n [class.fly-topbar__item--on]=\"mod.key === activeKey()\"\r\n role=\"menuitem\"\r\n [disabled]=\"mod.disabled ?? false\"\r\n [attr.tabindex]=\"indexOf(mod) === focusIndex() ? 0 : -1\"\r\n [attr.aria-current]=\"mod.key === activeKey() ? 'page' : null\"\r\n (click)=\"select(mod)\"\r\n (keydown)=\"onRowKeydown($event)\"\r\n >\r\n <span class=\"fly-topbar__item-icon\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__item-main\">\r\n <span class=\"fly-topbar__item-label\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"fly-topbar__item-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n @if (footerLabel()) {\r\n <div class=\"fly-topbar__foot\">{{ footerLabel() }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fly-topbar__actions\"><ng-content select=\"[app-topbar-actions]\" /></div>\r\n</header>\r\n", styles: [":host{display:block;position:relative;z-index:var(--z-sticky)}.fly-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--w1);background:var(--bg-3)}.fly-topbar__lead{display:flex;align-items:center;gap:var(--sp-2);min-inline-size:0}.fly-topbar__brand,.fly-topbar__module{display:inline-flex;align-items:center;gap:var(--sp-2);appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__brand:hover,.fly-topbar__module:hover{background:var(--bg-hover)}.fly-topbar__brand:focus-visible,.fly-topbar__module:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.fly-topbar__brand-name{font-weight:var(--fw-semibold);white-space:nowrap}.fly-topbar__brand-mark{display:inline-flex;align-items:center;max-block-size:var(--icon-lg)}.fly-topbar__sep{color:var(--ink-4);-webkit-user-select:none;user-select:none}.fly-topbar__module{min-inline-size:0}.fly-topbar__module--on{background:var(--bg-hover)}.fly-topbar__module-label{font-weight:var(--fw-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-topbar__module-label--empty{color:var(--ink-3)}.fly-topbar__module-icon,.fly-topbar__item-icon{display:inline-flex;align-items:center;justify-content:center;inline-size:var(--icon-md);block-size:var(--icon-md);flex:0 0 auto;color:var(--accent)}.fly-topbar__chevron{flex:0 0 auto;color:var(--ink-3);transition:transform var(--t-state)}.fly-topbar__module--on .fly-topbar__chevron{transform:rotate(180deg)}.fly-topbar__anchor{position:relative}:host(.fly-topbar--docked){flex:1 1 auto;min-inline-size:0;z-index:auto}:host(.fly-topbar--docked) .fly-topbar{padding:0;background:transparent;border-block-end:0}:host(.fly-topbar--docked) .fly-topbar__lead{gap:2px}:host(.fly-topbar--docked) .fly-topbar__brand,:host(.fly-topbar--docked) .fly-topbar__module{block-size:26px;padding-block:0;padding-inline:var(--sp-2);border-radius:var(--r-md);gap:6px;font-size:var(--text-sm);line-height:1;color:var(--w55)}:host(.fly-topbar--docked) .fly-topbar__brand:hover,:host(.fly-topbar--docked) .fly-topbar__module:hover{background:var(--w08);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module{background:var(--w06);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module--on{background:var(--w08)}:host(.fly-topbar--docked) .fly-topbar__brand-name{font-weight:var(--fw-medium)}:host(.fly-topbar--docked) .fly-topbar__module-label{font-weight:var(--fw-semibold);letter-spacing:-.006em}:host-context([dir=rtl]) :host(.fly-topbar--docked) .fly-topbar__module-label{letter-spacing:normal}:host(.fly-topbar--docked) .fly-topbar__sep{position:relative;display:inline-block;inline-size:7px;block-size:7px;color:transparent;border-block-start:1.5px solid var(--w28);border-inline-end:1.5px solid var(--w28);transform:rotate(45deg)}:host-context([dir=rtl]) :host(.fly-topbar--docked) .fly-topbar__sep{transform:rotate(-135deg)}:host(.fly-topbar--docked) .fly-topbar__actions{display:none}:host(.fly-topbar--docked) .fly-topbar__module-icon{inline-size:14px;block-size:14px}:host(.fly-topbar--docked) .fly-topbar__brand-mark{max-block-size:14px}:host(.fly-topbar--docked) .fly-topbar__brand-mark ::ng-deep *{max-inline-size:14px;max-block-size:14px}.fly-topbar__pop{position:absolute;inset-block-start:calc(100% + var(--sp-1));inset-inline-start:0;z-index:var(--z-overlay);min-inline-size:260px;max-inline-size:min(680px,92vw);padding:var(--sp-3);border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-topbar__pop{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-topbar__pop:before,.fly-topbar__pop:after{display:none}}@media(prefers-contrast:more){.fly-topbar__pop{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-topbar__pop:after{animation:none}}.fly-topbar__cols{display:flex;gap:var(--sp-4);align-items:flex-start}@media(width<=720px){.fly-topbar__cols{flex-direction:column;gap:var(--sp-3)}}.fly-topbar__col{display:flex;flex-direction:column;gap:2px;min-inline-size:220px;flex:1 1 0}.fly-topbar__col-title{font-size:var(--text-2xs);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-3);padding:var(--sp-2) var(--sp-2) var(--sp-1)}.fly-topbar__item{display:flex;align-items:flex-start;gap:var(--sp-2);inline-size:100%;text-align:start;appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__item:hover:not(:disabled){background:var(--w1)}.fly-topbar__item:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}.fly-topbar__item:disabled{opacity:.5;cursor:default}.fly-topbar__item--on{background:var(--accent-soft);color:var(--on-accent-soft);box-shadow:inset 2px 0 0 0 var(--accent)}.fly-topbar__item-main{display:flex;flex-direction:column;gap:1px;min-inline-size:0}.fly-topbar__item-label{font-weight:var(--fw-medium);line-height:1.3}.fly-topbar__item-desc{font-size:var(--text-xs);color:var(--ink-3);line-height:1.35}.fly-topbar__foot{margin-block-start:var(--sp-3);padding-block-start:var(--sp-2);border-block-start:.5px solid var(--w08);font-size:var(--text-2xs);color:var(--ink-4)}.fly-topbar__actions{display:flex;align-items:center;gap:var(--sp-2);flex:0 0 auto}@media(forced-colors:active){.fly-topbar__item--on{border-inline-start:2px solid CanvasText}}@media(prefers-reduced-motion:reduce){.fly-topbar__brand,.fly-topbar__module,.fly-topbar__item,.fly-topbar__chevron{transition:none}}\n"] }]
24393
+ }, template: "<header class=\"fly-topbar\">\r\n <div class=\"fly-topbar__lead\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-topbar__brand\"\r\n (click)=\"brandSelected.emit()\"\r\n [attr.aria-label]=\"brandAriaLabel()\"\r\n >\r\n <span class=\"fly-topbar__brand-mark\"><ng-content select=\"[app-topbar-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"fly-topbar__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n\r\n @if (activeModule()) {\r\n <span class=\"fly-topbar__sep\" aria-hidden=\"true\">/</span>\r\n }\r\n\r\n <div class=\"fly-topbar__anchor\" (flyClickOutside)=\"close()\" [flyClickOutsideEnabled]=\"open()\">\r\n <button\r\n type=\"button\"\r\n class=\"fly-topbar__module\"\r\n [class.fly-topbar__module--on]=\"open()\"\r\n (click)=\"onAnchorClick()\"\r\n >\r\n @if (activeModule(); as active) {\r\n <span class=\"fly-topbar__module-icon\">\r\n @if (iconFor(active.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (active.iconClass) {\r\n <i [class]=\"active.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__module-label\">{{ active.labelKey | translate }}</span>\r\n } @else {\r\n <span class=\"fly-topbar__module-label fly-topbar__module-label--empty\">\r\n {{ 'ui.nav.selectModule' | translate }}\r\n </span>\r\n }\r\n </button>\r\n\r\n <button\r\n #trigger\r\n type=\"button\"\r\n class=\"fly-topbar__chevron-btn\"\r\n [class.fly-topbar__chevron-btn--on]=\"open()\"\r\n (click)=\"toggle()\"\r\n (keydown)=\"onTriggerKeydown($event)\"\r\n aria-haspopup=\"menu\"\r\n [attr.aria-expanded]=\"open()\"\r\n [attr.aria-label]=\"switchAriaLabel()\"\r\n >\r\n <svg class=\"fly-topbar__chevron\" [class.fly-topbar__chevron--on]=\"open()\" width=\"11\" height=\"11\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n\r\n @if (open()) {\r\n <div class=\"fly-topbar__pop\" role=\"menu\" [attr.aria-label]=\"switchAriaLabel()\">\r\n <div class=\"fly-topbar__cols\">\r\n @for (section of sections(); track $index) {\r\n <div class=\"fly-topbar__col\">\r\n @if (section.titleKey; as titleKey) {\r\n <div class=\"fly-topbar__col-title\">{{ titleKey | translate }}</div>\r\n }\r\n @for (mod of section.modules; track mod.key) {\r\n <button\r\n #row\r\n type=\"button\"\r\n class=\"fly-topbar__item\"\r\n [class.fly-topbar__item--on]=\"mod.key === activeKey()\"\r\n role=\"menuitem\"\r\n [disabled]=\"mod.disabled ?? false\"\r\n [attr.tabindex]=\"indexOf(mod) === focusIndex() ? 0 : -1\"\r\n [attr.aria-current]=\"mod.key === activeKey() ? 'page' : null\"\r\n (click)=\"select(mod)\"\r\n (keydown)=\"onRowKeydown($event)\"\r\n >\r\n <span class=\"fly-topbar__item-icon\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n <span class=\"fly-topbar__item-main\">\r\n <span class=\"fly-topbar__item-label\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"fly-topbar__item-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n @if (footerLabel()) {\r\n <div class=\"fly-topbar__foot\">{{ footerLabel() }}</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fly-topbar__actions\"><ng-content select=\"[app-topbar-actions]\" /></div>\r\n</header>\r\n", styles: [":host{display:block;position:relative;z-index:var(--z-sticky)}.fly-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:var(--sp-2) var(--sp-3);border-block-end:1px solid var(--w1);background:var(--bg-3)}.fly-topbar__lead{display:flex;align-items:center;gap:var(--sp-2);min-inline-size:0}.fly-topbar__brand,.fly-topbar__module{display:inline-flex;align-items:center;gap:var(--sp-2);appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__brand:hover,.fly-topbar__module:hover{background:var(--bg-hover)}.fly-topbar__brand:focus-visible,.fly-topbar__module:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.fly-topbar__brand-name{font-weight:var(--fw-semibold);white-space:nowrap}.fly-topbar__brand-mark{display:inline-flex;align-items:center;max-block-size:var(--icon-lg)}.fly-topbar__sep{color:var(--ink-4);-webkit-user-select:none;user-select:none}.fly-topbar__module{min-inline-size:0;border-start-end-radius:0;border-end-end-radius:0}.fly-topbar__module--on{background:var(--bg-hover)}.fly-topbar__module-label{font-weight:var(--fw-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fly-topbar__module-label--empty{color:var(--ink-3)}.fly-topbar__module-icon,.fly-topbar__item-icon{display:inline-flex;align-items:center;justify-content:center;inline-size:var(--icon-md);block-size:var(--icon-md);flex:0 0 auto;color:var(--accent)}.fly-topbar__chevron-btn{display:inline-flex;align-items:center;justify-content:center;align-self:stretch;flex:0 0 auto;appearance:none;border:0;background:transparent;cursor:pointer;color:var(--ink-3);padding:var(--sp-1);border-radius:var(--r-md);border-start-start-radius:0;border-end-start-radius:0;transition:background var(--t-state)}.fly-topbar__chevron-btn:hover,.fly-topbar__chevron-btn--on{background:var(--bg-hover)}.fly-topbar__chevron-btn:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.fly-topbar__chevron{flex:0 0 auto;color:inherit;transition:transform var(--t-state)}.fly-topbar__chevron--on{transform:rotate(180deg)}.fly-topbar__anchor{position:relative;display:inline-flex;align-items:center;gap:0;min-inline-size:0}:host(.fly-topbar--docked){flex:1 1 auto;min-inline-size:0;z-index:auto}:host(.fly-topbar--docked) .fly-topbar{padding:0;background:transparent;border-block-end:0}:host(.fly-topbar--docked) .fly-topbar__lead{gap:2px}:host(.fly-topbar--docked) .fly-topbar__brand,:host(.fly-topbar--docked) .fly-topbar__module{block-size:26px;padding-block:0;padding-inline:var(--sp-2);gap:6px;font-size:var(--text-sm);line-height:1;color:var(--w55)}:host(.fly-topbar--docked) .fly-topbar__brand:hover,:host(.fly-topbar--docked) .fly-topbar__module:hover{background:var(--w12);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__chevron-btn{block-size:26px;padding-block:0;padding-inline:var(--sp-2);background:var(--w06);color:var(--w55)}:host(.fly-topbar--docked) .fly-topbar__chevron-btn:hover{background:var(--w12);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__chevron-btn--on,:host(.fly-topbar--docked) .fly-topbar__chevron-btn--on:hover{background:var(--w18);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module{background:var(--w06);color:var(--label-primary)}:host(.fly-topbar--docked) .fly-topbar__module--on,:host(.fly-topbar--docked) .fly-topbar__module--on:hover{background:var(--w18)}:host(.fly-topbar--docked) .fly-topbar__brand-name{font-weight:var(--fw-medium)}:host(.fly-topbar--docked) .fly-topbar__module-label{font-weight:var(--fw-semibold);letter-spacing:-.006em}:host-context([dir=rtl]) :host(.fly-topbar--docked) .fly-topbar__module-label{letter-spacing:normal}:host(.fly-topbar--docked) .fly-topbar__sep{position:relative;display:inline-block;inline-size:7px;block-size:7px;color:transparent;border-block-start:1.5px solid var(--w28);border-inline-end:1.5px solid var(--w28);transform:rotate(45deg)}:host-context([dir=rtl]) :host(.fly-topbar--docked) .fly-topbar__sep{transform:rotate(-135deg)}:host(.fly-topbar--docked) .fly-topbar__actions{display:none}:host(.fly-topbar--docked) .fly-topbar__module-icon{inline-size:14px;block-size:14px}:host(.fly-topbar--docked) .fly-topbar__brand-mark{max-block-size:14px}:host(.fly-topbar--docked) .fly-topbar__brand-mark ::ng-deep *{max-inline-size:14px;max-block-size:14px}.fly-topbar__pop{position:absolute;inset-block-start:calc(100% + var(--sp-1));inset-inline-start:0;z-index:var(--z-overlay);min-inline-size:260px;max-inline-size:min(680px,92vw);padding:var(--sp-3);border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-solid-a),var(--mat-menu-solid-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.fly-topbar__pop{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.fly-topbar__pop:before,.fly-topbar__pop:after{display:none}}@media(prefers-contrast:more){.fly-topbar__pop{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.fly-topbar__pop:after{animation:none}}.fly-topbar__cols{display:flex;gap:var(--sp-4);align-items:flex-start}@media(width<=720px){.fly-topbar__cols{flex-direction:column;gap:var(--sp-3)}}.fly-topbar__col{display:flex;flex-direction:column;gap:2px;min-inline-size:220px;flex:1 1 0}.fly-topbar__col-title{font-size:var(--text-2xs);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-wide);text-transform:uppercase;color:var(--ink-3);padding:var(--sp-2) var(--sp-2) var(--sp-1)}.fly-topbar__item{display:flex;align-items:flex-start;gap:var(--sp-2);inline-size:100%;text-align:start;appearance:none;border:0;background:transparent;cursor:pointer;font:inherit;color:var(--ink);padding:var(--sp-2);border-radius:var(--r-md);transition:background var(--t-state)}.fly-topbar__item:hover:not(:disabled){background:var(--w1)}.fly-topbar__item:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:-2px}.fly-topbar__item:disabled{opacity:.5;cursor:default}.fly-topbar__item--on{background:var(--accent-soft);color:var(--on-accent-soft);box-shadow:inset 2px 0 0 0 var(--accent)}.fly-topbar__item-main{display:flex;flex-direction:column;gap:1px;min-inline-size:0}.fly-topbar__item-label{font-weight:var(--fw-medium);line-height:1.3}.fly-topbar__item-desc{font-size:var(--text-xs);color:var(--ink-3);line-height:1.35}.fly-topbar__foot{margin-block-start:var(--sp-3);padding-block-start:var(--sp-2);border-block-start:.5px solid var(--w08);font-size:var(--text-2xs);color:var(--ink-4)}.fly-topbar__actions{display:flex;align-items:center;gap:var(--sp-2);flex:0 0 auto}@media(forced-colors:active){.fly-topbar__item--on{border-inline-start:2px solid CanvasText}}@media(prefers-reduced-motion:reduce){.fly-topbar__brand,.fly-topbar__module,.fly-topbar__chevron-btn,.fly-topbar__item,.fly-topbar__chevron{transition:none}}\n"] }]
24350
24394
  }], ctorParameters: () => [], propDecorators: { brandLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandLabelKey", required: false }] }], sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], activeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeKey", required: false }] }], footerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerLabel", required: false }] }], moduleSelected: [{ type: i0.Output, args: ["moduleSelected"] }], brandSelected: [{ type: i0.Output, args: ["brandSelected"] }], icons: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FlyModuleIconDirective), { isSignal: true }] }], rows: [{ type: i0.ViewChildren, args: ['row', { isSignal: true }] }], trigger: [{ type: i0.ViewChildren, args: ['trigger', { isSignal: true }] }] } });
24351
24395
 
24352
24396
  /**
@@ -24477,11 +24521,11 @@ class FlyAppHomeComponent {
24477
24521
  return `fly-app-home-sec-${index}`;
24478
24522
  }
24479
24523
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyAppHomeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
24480
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyAppHomeComponent, isStandalone: true, selector: "fly-app-home", inputs: { brandLabelKey: { classPropertyName: "brandLabelKey", publicName: "brandLabelKey", isSignal: true, isRequired: false, transformFunction: null }, titleKey: { classPropertyName: "titleKey", publicName: "titleKey", isSignal: true, isRequired: false, transformFunction: null }, subtitleKey: { classPropertyName: "subtitleKey", publicName: "subtitleKey", isSignal: true, isRequired: false, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, modulesLabelKey: { classPropertyName: "modulesLabelKey", publicName: "modulesLabelKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { moduleSelected: "moduleSelected", brandSelected: "brandSelected" }, queries: [{ propertyName: "icons", predicate: FlyModuleIconDirective, isSignal: true }], ngImport: i0, template: "<div class=\"ah\">\r\n <header class=\"ah__util\">\r\n <button type=\"button\" class=\"ah__brand\" (click)=\"brandSelected.emit()\">\r\n <span class=\"ah__brand-mark\"><ng-content select=\"[app-home-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"ah__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n <ng-content select=\"[app-home-actions]\" />\r\n </header>\r\n\r\n <main class=\"ah__main\">\r\n @if (titleKey() || subtitleKey()) {\r\n <section class=\"ah__hero\">\r\n @if (titleKey(); as key) {\r\n <h1 class=\"ah__title\">{{ key | translate }}</h1>\r\n }\r\n @if (subtitleKey(); as key) {\r\n <p class=\"ah__sub\">{{ key | translate }}</p>\r\n }\r\n </section>\r\n }\r\n\r\n @for (row of rows(); track row.index) {\r\n <section\r\n class=\"ah__sec\"\r\n [class.ah__sec--secondary]=\"row.index > 0\"\r\n [attr.aria-label]=\"row.section.titleKey ? null : (modulesLabelKey() | translate)\"\r\n >\r\n @if (row.section.titleKey; as titleKey) {\r\n @if (row.section.collapsible) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__sec-hd\"\r\n (click)=\"toggle(row.index)\"\r\n [attr.aria-expanded]=\"row.expanded\"\r\n [attr.aria-controls]=\"sectionId(row.index)\"\r\n >\r\n <!-- Points end-ward when shut, down when open. `--open` wins over the RTL\r\n flip below because a downward chevron has no direction to mirror. -->\r\n <svg\r\n class=\"ah__sec-chev\"\r\n [class.ah__sec-chev--open]=\"row.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n <span class=\"ah__sec-title\">{{ titleKey | translate }}</span>\r\n <span class=\"ah__sec-count\">{{ row.section.modules.length }}</span>\r\n @if (row.hintKey; as hint) {\r\n <span class=\"ah__sec-hint\">{{ hint | translate }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <h2 class=\"ah__sec-title ah__sec-title--static\">{{ titleKey | translate }}</h2>\r\n }\r\n }\r\n\r\n @if (row.expanded) {\r\n <div class=\"ah__grid\" [class.ah__grid--compact]=\"row.layout === 'compact'\" [id]=\"sectionId(row.index)\">\r\n @for (mod of row.section.modules; track mod.key) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__card\"\r\n [class.ah__card--compact]=\"row.layout === 'compact'\"\r\n [disabled]=\"mod.disabled\"\r\n (click)=\"select(mod)\"\r\n >\r\n <span class=\"ah__card-ico\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n\r\n @if (row.layout === 'compact') {\r\n <span class=\"ah__card-main\">\r\n <span class=\"ah__card-title\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n <svg\r\n class=\"ah__card-arrow\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n } @else {\r\n <!-- No \"Open \u203A\" affordance row \u2014 the design's module card (MainContent.dc.html)\r\n ends at the description; the whole card is the click target and hover carries\r\n the affordance. Removed at the 2026-08-17 fidelity pass. -->\r\n <span class=\"ah__card-title ah__card-title--feature\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc ah__card-desc--feature\">{{ descKey | translate }}</span>\r\n }\r\n }\r\n </button>\r\n }\r\n </div>\r\n }\r\n </section>\r\n }\r\n </main>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:100%;container-type:inline-size}.ah{display:flex;flex-direction:column;flex:1;min-height:100%}.ah__util{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:var(--sp-4) var(--sp-6)}:host-context(.window-content) .ah__brand{display:none}:host-context(.window-content) .ah__util{justify-content:flex-end}:host-context(.window-content) .ah__util:not(:has(>:not(.ah__brand))){display:none}.ah__brand{display:inline-flex;align-items:center;gap:var(--sp-2);padding:0;border:0;background:none;color:var(--ink);font-family:inherit;cursor:pointer}.ah__brand:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__brand-name{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__main{flex:1;inline-size:100%;max-inline-size:1120px;margin-inline:auto;padding:56px 40px;display:flex;flex-direction:column;justify-content:center;gap:44px}.ah__hero{max-inline-size:640px}.ah__title{margin:0 0 var(--sp-3);font-size:44px;font-weight:var(--fw-semibold);letter-spacing:-.03em;text-wrap:balance;background:linear-gradient(180deg,var(--ink),var(--ink-2));-webkit-background-clip:text;background-clip:text;color:transparent}.ah__sub{margin:0;max-inline-size:560px;font-size:var(--text-lg);line-height:1.55;color:var(--ink-3);text-wrap:pretty}.ah__sec{display:flex;flex-direction:column;gap:var(--sp-4)}.ah__sec--secondary{padding-block-start:28px;border-block-start:1px solid var(--w08)}.ah__sec-hd{display:flex;align-items:center;gap:var(--sp-3);inline-size:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.ah__sec-hd:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__sec-chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.ah__sec-title{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__sec-title--static{margin:0;color:var(--ink-3);font-size:var(--text-xs);letter-spacing:var(--tracking-wide);text-transform:uppercase}.ah__sec-count{display:inline-grid;place-items:center;min-inline-size:22px;block-size:20px;padding-inline:6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-2xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.ah__sec-hint{margin-inline-start:auto;font-size:var(--text-xs);color:var(--ink-3)}.ah__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}.ah__card{display:flex;flex-direction:column;align-items:stretch;position:relative;overflow:hidden;text-align:start;padding:20px;background-image:linear-gradient(160deg,var(--w055),var(--w02));border:1px solid var(--w09);border-radius:20px;color:inherit;font-family:inherit;cursor:pointer;animation:appTileIn .3s var(--nova-ease-micro) both}.ah__card:nth-child(1){animation-delay:0ms}.ah__card:nth-child(2){animation-delay:20ms}.ah__card:nth-child(3){animation-delay:40ms}.ah__card:nth-child(4){animation-delay:60ms}.ah__card:nth-child(5){animation-delay:80ms}.ah__card:nth-child(6){animation-delay:.1s}.ah__card:nth-child(7){animation-delay:.12s}.ah__card:nth-child(8){animation-delay:.14s}.ah__card:nth-child(9){animation-delay:.16s}.ah__card:nth-child(10){animation-delay:.18s}.ah__card:nth-child(11){animation-delay:.2s}.ah__card:nth-child(12){animation-delay:.22s}.ah__card:nth-child(n+13){animation-delay:.22s}.ah__card{transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-state),background-image var(--t-state)}.ah__card:hover:not(:disabled){transform:translateY(-3px);border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:focus-visible{outline:0;border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 0 0 3px var(--accent-soft),0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:disabled{cursor:default;opacity:.5}.ah__card-ico{display:grid;place-items:center;inline-size:42px;block-size:42px;margin-block-end:16px;border-radius:13px;background:linear-gradient(140deg,color-mix(in srgb,var(--accent) 50%,transparent),color-mix(in srgb,var(--sys-teal) 22%,transparent));box-shadow:0 6px 16px color-mix(in srgb,var(--accent) 30%,transparent),inset 0 1px 0 var(--edge-highlight);border:0;color:var(--on-accent);font-size:var(--icon-lg)}.ah__card--compact:hover:not(:disabled) .ah__card-ico,.ah__card--compact:focus-visible .ah__card-ico{background:linear-gradient(135deg,var(--accent),var(--sys-teal));box-shadow:inset 0 1px 0 var(--edge-highlight);color:var(--on-accent)}.ah__card-title{font-size:var(--text-sm);font-weight:var(--fw-semibold);letter-spacing:-.01em;color:var(--ink)}.ah__card-title--feature{margin-block-end:5px;font-size:16.5px;line-height:1.25;letter-spacing:-.005em}.ah__card-desc{font-size:var(--text-xs);line-height:1.45;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ah__card-desc--feature{margin-block-end:0;font-size:13px;line-height:1.45;text-wrap:pretty;overflow:visible;white-space:normal}.ah__card-arrow{flex-shrink:0;transition:color var(--t-overlay),transform var(--t-overlay)}.ah__card--compact{flex-direction:row;align-items:center;gap:var(--sp-3);padding:14px 16px;background-color:var(--bg);background-image:linear-gradient(160deg,var(--w035),var(--w035));border-radius:16px;border-color:var(--w08)}.ah__card--compact:hover:not(:disabled),.ah__card--compact:focus-visible{border-color:color-mix(in oklab,var(--accent) 40%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent)}.ah__card--compact .ah__card-ico{inline-size:32px;block-size:32px;margin-block-end:0;flex-shrink:0;border-radius:10px;font-size:var(--icon-md);background:var(--bg-3);box-shadow:none;color:var(--ink)}.ah__card-main{display:flex;flex-direction:column;gap:2px;flex:1;min-inline-size:0}.ah__card--compact .ah__card-arrow{color:var(--ink-4)}.ah__card--compact:hover:not(:disabled) .ah__card-arrow{color:var(--accent);transform:translate(2px)}:host-context([dir=rtl]) .ah__card-arrow{transform:scaleX(-1)}:host-context([dir=rtl]) .ah__sec-chev:not(.ah__sec-chev--open){transform:scaleX(-1)}:host-context([dir=rtl]) .ah__card--compact:hover:not(:disabled) .ah__card-arrow{transform:scaleX(-1) translate(2px)}.ah__sec-chev--open{transform:rotate(90deg)}@container (width <= 900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@media(width<=900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@container (width <= 560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}@media(width<=560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24524
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyAppHomeComponent, isStandalone: true, selector: "fly-app-home", inputs: { brandLabelKey: { classPropertyName: "brandLabelKey", publicName: "brandLabelKey", isSignal: true, isRequired: false, transformFunction: null }, titleKey: { classPropertyName: "titleKey", publicName: "titleKey", isSignal: true, isRequired: false, transformFunction: null }, subtitleKey: { classPropertyName: "subtitleKey", publicName: "subtitleKey", isSignal: true, isRequired: false, transformFunction: null }, sections: { classPropertyName: "sections", publicName: "sections", isSignal: true, isRequired: false, transformFunction: null }, modulesLabelKey: { classPropertyName: "modulesLabelKey", publicName: "modulesLabelKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { moduleSelected: "moduleSelected", brandSelected: "brandSelected" }, queries: [{ propertyName: "icons", predicate: FlyModuleIconDirective, isSignal: true }], ngImport: i0, template: "<div class=\"ah\">\r\n <header class=\"ah__util\">\r\n <button type=\"button\" class=\"ah__brand\" (click)=\"brandSelected.emit()\">\r\n <span class=\"ah__brand-mark\"><ng-content select=\"[app-home-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"ah__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n <ng-content select=\"[app-home-actions]\" />\r\n </header>\r\n\r\n <main class=\"ah__main\">\r\n @if (titleKey() || subtitleKey()) {\r\n <section class=\"ah__hero\">\r\n @if (titleKey(); as key) {\r\n <h1 class=\"ah__title\">{{ key | translate }}</h1>\r\n }\r\n @if (subtitleKey(); as key) {\r\n <p class=\"ah__sub\">{{ key | translate }}</p>\r\n }\r\n </section>\r\n }\r\n\r\n @for (row of rows(); track row.index) {\r\n <section\r\n class=\"ah__sec\"\r\n [class.ah__sec--secondary]=\"row.index > 0\"\r\n [attr.aria-label]=\"row.section.titleKey ? null : (modulesLabelKey() | translate)\"\r\n >\r\n @if (row.section.titleKey; as titleKey) {\r\n @if (row.section.collapsible) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__sec-hd\"\r\n (click)=\"toggle(row.index)\"\r\n [attr.aria-expanded]=\"row.expanded\"\r\n [attr.aria-controls]=\"sectionId(row.index)\"\r\n >\r\n <!-- Points end-ward when shut, down when open. `--open` wins over the RTL\r\n flip below because a downward chevron has no direction to mirror. -->\r\n <svg\r\n class=\"ah__sec-chev\"\r\n [class.ah__sec-chev--open]=\"row.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n <span class=\"ah__sec-title\">{{ titleKey | translate }}</span>\r\n <span class=\"ah__sec-count\">{{ row.section.modules.length }}</span>\r\n @if (row.hintKey; as hint) {\r\n <span class=\"ah__sec-hint\">{{ hint | translate }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <h2 class=\"ah__sec-title ah__sec-title--static\">{{ titleKey | translate }}</h2>\r\n }\r\n }\r\n\r\n @if (row.expanded) {\r\n <div class=\"ah__grid\" [class.ah__grid--compact]=\"row.layout === 'compact'\" [id]=\"sectionId(row.index)\">\r\n @for (mod of row.section.modules; track mod.key) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__card\"\r\n [class.ah__card--compact]=\"row.layout === 'compact'\"\r\n [disabled]=\"mod.disabled\"\r\n (click)=\"select(mod)\"\r\n >\r\n <span class=\"ah__card-ico\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n\r\n @if (row.layout === 'compact') {\r\n <span class=\"ah__card-main\">\r\n <span class=\"ah__card-title\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n <svg\r\n class=\"ah__card-arrow\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n } @else {\r\n <!-- No \"Open \u203A\" affordance row \u2014 the design's module card (MainContent.dc.html)\r\n ends at the description; the whole card is the click target and hover carries\r\n the affordance. Removed at the 2026-08-17 fidelity pass. -->\r\n <span class=\"ah__card-title ah__card-title--feature\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc ah__card-desc--feature\">{{ descKey | translate }}</span>\r\n }\r\n }\r\n </button>\r\n }\r\n </div>\r\n }\r\n </section>\r\n }\r\n </main>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:100%;container-type:inline-size}.ah{display:flex;flex-direction:column;flex:1;min-height:100%}.ah__util{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:var(--sp-4) var(--sp-6)}:host-context(.window-content) .ah__brand{display:none}:host-context(.window-content) .ah__util{justify-content:flex-end}:host-context(.window-content) .ah__util:not(:has(>:not(.ah__brand))){display:none}.ah__brand{display:inline-flex;align-items:center;gap:var(--sp-2);padding:0;border:0;background:none;color:var(--ink);font-family:inherit;cursor:pointer}.ah__brand:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.ah__brand-name{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__main{flex:1;inline-size:100%;max-inline-size:1120px;margin-inline:auto;padding:56px 40px;display:flex;flex-direction:column;justify-content:center;gap:44px}.ah__hero{max-inline-size:640px}.ah__title{margin:0 0 var(--sp-3);font-size:44px;font-weight:var(--fw-semibold);letter-spacing:-.03em;text-wrap:balance;background:linear-gradient(180deg,var(--ink),var(--ink-2));-webkit-background-clip:text;background-clip:text;color:transparent}.ah__sub{margin:0;max-inline-size:560px;font-size:var(--text-lg);line-height:1.55;color:var(--ink-3);text-wrap:pretty}.ah__sec{display:flex;flex-direction:column;gap:var(--sp-4)}.ah__sec--secondary{padding-block-start:28px;border-block-start:1px solid var(--w08)}.ah__sec-hd{display:flex;align-items:center;gap:var(--sp-3);inline-size:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.ah__sec-hd:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.ah__sec-chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.ah__sec-title{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__sec-title--static{margin:0;color:var(--ink-3);font-size:var(--text-xs);letter-spacing:var(--tracking-wide);text-transform:uppercase}.ah__sec-count{display:inline-grid;place-items:center;min-inline-size:22px;block-size:20px;padding-inline:6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-2xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.ah__sec-hint{margin-inline-start:auto;font-size:var(--text-xs);color:var(--ink-3)}.ah__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}.ah__card{display:flex;flex-direction:column;align-items:stretch;position:relative;overflow:hidden;text-align:start;padding:20px;background-image:linear-gradient(160deg,var(--w055),var(--w02));border:1px solid var(--w09);border-radius:20px;color:inherit;font-family:inherit;cursor:pointer;animation:appTileIn .3s var(--nova-ease-micro) both}.ah__card:nth-child(1){animation-delay:0ms}.ah__card:nth-child(2){animation-delay:20ms}.ah__card:nth-child(3){animation-delay:40ms}.ah__card:nth-child(4){animation-delay:60ms}.ah__card:nth-child(5){animation-delay:80ms}.ah__card:nth-child(6){animation-delay:.1s}.ah__card:nth-child(7){animation-delay:.12s}.ah__card:nth-child(8){animation-delay:.14s}.ah__card:nth-child(9){animation-delay:.16s}.ah__card:nth-child(10){animation-delay:.18s}.ah__card:nth-child(11){animation-delay:.2s}.ah__card:nth-child(12){animation-delay:.22s}.ah__card:nth-child(n+13){animation-delay:.22s}.ah__card{transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-state),background-image var(--t-state)}.ah__card:hover:not(:disabled){transform:translateY(-3px);border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:focus-visible{outline:0;border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 0 0 3px var(--accent-soft),0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:disabled{cursor:default;opacity:.5}.ah__card-ico{display:grid;place-items:center;inline-size:42px;block-size:42px;margin-block-end:16px;border-radius:13px;background:linear-gradient(140deg,color-mix(in srgb,var(--accent) 50%,transparent),color-mix(in srgb,var(--sys-teal) 22%,transparent));box-shadow:0 6px 16px color-mix(in srgb,var(--accent) 30%,transparent),inset 0 1px 0 var(--edge-highlight);border:0;color:var(--on-accent);font-size:var(--icon-lg)}.ah__card--compact:hover:not(:disabled) .ah__card-ico,.ah__card--compact:focus-visible .ah__card-ico{background:linear-gradient(135deg,var(--accent),var(--sys-teal));box-shadow:inset 0 1px 0 var(--edge-highlight);color:var(--on-accent)}.ah__card-title{font-size:var(--text-sm);font-weight:var(--fw-semibold);letter-spacing:-.01em;color:var(--ink)}.ah__card-title--feature{margin-block-end:5px;font-size:16.5px;line-height:1.25;letter-spacing:-.005em}.ah__card-desc{font-size:var(--text-xs);line-height:1.45;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ah__card-desc--feature{margin-block-end:0;font-size:13px;line-height:1.45;text-wrap:pretty;overflow:visible;white-space:normal}.ah__card-arrow{flex-shrink:0;transition:color var(--t-overlay),transform var(--t-overlay)}.ah__card--compact{flex-direction:row;align-items:center;gap:var(--sp-3);padding:14px 16px;background-color:var(--bg);background-image:linear-gradient(160deg,var(--w035),var(--w035));border-radius:16px;border-color:var(--w08)}.ah__card--compact:hover:not(:disabled),.ah__card--compact:focus-visible{border-color:color-mix(in oklab,var(--accent) 40%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent)}.ah__card--compact .ah__card-ico{inline-size:32px;block-size:32px;margin-block-end:0;flex-shrink:0;border-radius:10px;font-size:var(--icon-md);background:var(--bg-3);box-shadow:none;color:var(--ink)}.ah__card-main{display:flex;flex-direction:column;gap:2px;flex:1;min-inline-size:0}.ah__card--compact .ah__card-arrow{color:var(--ink-4)}.ah__card--compact:hover:not(:disabled) .ah__card-arrow{color:var(--accent);transform:translate(2px)}:host-context([dir=rtl]) .ah__card-arrow{transform:scaleX(-1)}:host-context([dir=rtl]) .ah__sec-chev:not(.ah__sec-chev--open){transform:scaleX(-1)}:host-context([dir=rtl]) .ah__card--compact:hover:not(:disabled) .ah__card-arrow{transform:scaleX(-1) translate(2px)}.ah__sec-chev--open{transform:rotate(90deg)}@container (width <= 900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@media(width<=900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@container (width <= 560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}@media(width<=560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24481
24525
  }
24482
24526
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyAppHomeComponent, decorators: [{
24483
24527
  type: Component,
24484
- args: [{ selector: 'fly-app-home', standalone: true, imports: [NgTemplateOutlet, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ah\">\r\n <header class=\"ah__util\">\r\n <button type=\"button\" class=\"ah__brand\" (click)=\"brandSelected.emit()\">\r\n <span class=\"ah__brand-mark\"><ng-content select=\"[app-home-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"ah__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n <ng-content select=\"[app-home-actions]\" />\r\n </header>\r\n\r\n <main class=\"ah__main\">\r\n @if (titleKey() || subtitleKey()) {\r\n <section class=\"ah__hero\">\r\n @if (titleKey(); as key) {\r\n <h1 class=\"ah__title\">{{ key | translate }}</h1>\r\n }\r\n @if (subtitleKey(); as key) {\r\n <p class=\"ah__sub\">{{ key | translate }}</p>\r\n }\r\n </section>\r\n }\r\n\r\n @for (row of rows(); track row.index) {\r\n <section\r\n class=\"ah__sec\"\r\n [class.ah__sec--secondary]=\"row.index > 0\"\r\n [attr.aria-label]=\"row.section.titleKey ? null : (modulesLabelKey() | translate)\"\r\n >\r\n @if (row.section.titleKey; as titleKey) {\r\n @if (row.section.collapsible) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__sec-hd\"\r\n (click)=\"toggle(row.index)\"\r\n [attr.aria-expanded]=\"row.expanded\"\r\n [attr.aria-controls]=\"sectionId(row.index)\"\r\n >\r\n <!-- Points end-ward when shut, down when open. `--open` wins over the RTL\r\n flip below because a downward chevron has no direction to mirror. -->\r\n <svg\r\n class=\"ah__sec-chev\"\r\n [class.ah__sec-chev--open]=\"row.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n <span class=\"ah__sec-title\">{{ titleKey | translate }}</span>\r\n <span class=\"ah__sec-count\">{{ row.section.modules.length }}</span>\r\n @if (row.hintKey; as hint) {\r\n <span class=\"ah__sec-hint\">{{ hint | translate }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <h2 class=\"ah__sec-title ah__sec-title--static\">{{ titleKey | translate }}</h2>\r\n }\r\n }\r\n\r\n @if (row.expanded) {\r\n <div class=\"ah__grid\" [class.ah__grid--compact]=\"row.layout === 'compact'\" [id]=\"sectionId(row.index)\">\r\n @for (mod of row.section.modules; track mod.key) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__card\"\r\n [class.ah__card--compact]=\"row.layout === 'compact'\"\r\n [disabled]=\"mod.disabled\"\r\n (click)=\"select(mod)\"\r\n >\r\n <span class=\"ah__card-ico\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n\r\n @if (row.layout === 'compact') {\r\n <span class=\"ah__card-main\">\r\n <span class=\"ah__card-title\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n <svg\r\n class=\"ah__card-arrow\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n } @else {\r\n <!-- No \"Open \u203A\" affordance row \u2014 the design's module card (MainContent.dc.html)\r\n ends at the description; the whole card is the click target and hover carries\r\n the affordance. Removed at the 2026-08-17 fidelity pass. -->\r\n <span class=\"ah__card-title ah__card-title--feature\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc ah__card-desc--feature\">{{ descKey | translate }}</span>\r\n }\r\n }\r\n </button>\r\n }\r\n </div>\r\n }\r\n </section>\r\n }\r\n </main>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:100%;container-type:inline-size}.ah{display:flex;flex-direction:column;flex:1;min-height:100%}.ah__util{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:var(--sp-4) var(--sp-6)}:host-context(.window-content) .ah__brand{display:none}:host-context(.window-content) .ah__util{justify-content:flex-end}:host-context(.window-content) .ah__util:not(:has(>:not(.ah__brand))){display:none}.ah__brand{display:inline-flex;align-items:center;gap:var(--sp-2);padding:0;border:0;background:none;color:var(--ink);font-family:inherit;cursor:pointer}.ah__brand:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__brand-name{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__main{flex:1;inline-size:100%;max-inline-size:1120px;margin-inline:auto;padding:56px 40px;display:flex;flex-direction:column;justify-content:center;gap:44px}.ah__hero{max-inline-size:640px}.ah__title{margin:0 0 var(--sp-3);font-size:44px;font-weight:var(--fw-semibold);letter-spacing:-.03em;text-wrap:balance;background:linear-gradient(180deg,var(--ink),var(--ink-2));-webkit-background-clip:text;background-clip:text;color:transparent}.ah__sub{margin:0;max-inline-size:560px;font-size:var(--text-lg);line-height:1.55;color:var(--ink-3);text-wrap:pretty}.ah__sec{display:flex;flex-direction:column;gap:var(--sp-4)}.ah__sec--secondary{padding-block-start:28px;border-block-start:1px solid var(--w08)}.ah__sec-hd{display:flex;align-items:center;gap:var(--sp-3);inline-size:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.ah__sec-hd:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.ah__sec-chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.ah__sec-title{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__sec-title--static{margin:0;color:var(--ink-3);font-size:var(--text-xs);letter-spacing:var(--tracking-wide);text-transform:uppercase}.ah__sec-count{display:inline-grid;place-items:center;min-inline-size:22px;block-size:20px;padding-inline:6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-2xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.ah__sec-hint{margin-inline-start:auto;font-size:var(--text-xs);color:var(--ink-3)}.ah__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}.ah__card{display:flex;flex-direction:column;align-items:stretch;position:relative;overflow:hidden;text-align:start;padding:20px;background-image:linear-gradient(160deg,var(--w055),var(--w02));border:1px solid var(--w09);border-radius:20px;color:inherit;font-family:inherit;cursor:pointer;animation:appTileIn .3s var(--nova-ease-micro) both}.ah__card:nth-child(1){animation-delay:0ms}.ah__card:nth-child(2){animation-delay:20ms}.ah__card:nth-child(3){animation-delay:40ms}.ah__card:nth-child(4){animation-delay:60ms}.ah__card:nth-child(5){animation-delay:80ms}.ah__card:nth-child(6){animation-delay:.1s}.ah__card:nth-child(7){animation-delay:.12s}.ah__card:nth-child(8){animation-delay:.14s}.ah__card:nth-child(9){animation-delay:.16s}.ah__card:nth-child(10){animation-delay:.18s}.ah__card:nth-child(11){animation-delay:.2s}.ah__card:nth-child(12){animation-delay:.22s}.ah__card:nth-child(n+13){animation-delay:.22s}.ah__card{transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-state),background-image var(--t-state)}.ah__card:hover:not(:disabled){transform:translateY(-3px);border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:focus-visible{outline:0;border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 0 0 3px var(--accent-soft),0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:disabled{cursor:default;opacity:.5}.ah__card-ico{display:grid;place-items:center;inline-size:42px;block-size:42px;margin-block-end:16px;border-radius:13px;background:linear-gradient(140deg,color-mix(in srgb,var(--accent) 50%,transparent),color-mix(in srgb,var(--sys-teal) 22%,transparent));box-shadow:0 6px 16px color-mix(in srgb,var(--accent) 30%,transparent),inset 0 1px 0 var(--edge-highlight);border:0;color:var(--on-accent);font-size:var(--icon-lg)}.ah__card--compact:hover:not(:disabled) .ah__card-ico,.ah__card--compact:focus-visible .ah__card-ico{background:linear-gradient(135deg,var(--accent),var(--sys-teal));box-shadow:inset 0 1px 0 var(--edge-highlight);color:var(--on-accent)}.ah__card-title{font-size:var(--text-sm);font-weight:var(--fw-semibold);letter-spacing:-.01em;color:var(--ink)}.ah__card-title--feature{margin-block-end:5px;font-size:16.5px;line-height:1.25;letter-spacing:-.005em}.ah__card-desc{font-size:var(--text-xs);line-height:1.45;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ah__card-desc--feature{margin-block-end:0;font-size:13px;line-height:1.45;text-wrap:pretty;overflow:visible;white-space:normal}.ah__card-arrow{flex-shrink:0;transition:color var(--t-overlay),transform var(--t-overlay)}.ah__card--compact{flex-direction:row;align-items:center;gap:var(--sp-3);padding:14px 16px;background-color:var(--bg);background-image:linear-gradient(160deg,var(--w035),var(--w035));border-radius:16px;border-color:var(--w08)}.ah__card--compact:hover:not(:disabled),.ah__card--compact:focus-visible{border-color:color-mix(in oklab,var(--accent) 40%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent)}.ah__card--compact .ah__card-ico{inline-size:32px;block-size:32px;margin-block-end:0;flex-shrink:0;border-radius:10px;font-size:var(--icon-md);background:var(--bg-3);box-shadow:none;color:var(--ink)}.ah__card-main{display:flex;flex-direction:column;gap:2px;flex:1;min-inline-size:0}.ah__card--compact .ah__card-arrow{color:var(--ink-4)}.ah__card--compact:hover:not(:disabled) .ah__card-arrow{color:var(--accent);transform:translate(2px)}:host-context([dir=rtl]) .ah__card-arrow{transform:scaleX(-1)}:host-context([dir=rtl]) .ah__sec-chev:not(.ah__sec-chev--open){transform:scaleX(-1)}:host-context([dir=rtl]) .ah__card--compact:hover:not(:disabled) .ah__card-arrow{transform:scaleX(-1) translate(2px)}.ah__sec-chev--open{transform:rotate(90deg)}@container (width <= 900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@media(width<=900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@container (width <= 560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}@media(width<=560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}\n"] }]
24528
+ args: [{ selector: 'fly-app-home', standalone: true, imports: [NgTemplateOutlet, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ah\">\r\n <header class=\"ah__util\">\r\n <button type=\"button\" class=\"ah__brand\" (click)=\"brandSelected.emit()\">\r\n <span class=\"ah__brand-mark\"><ng-content select=\"[app-home-brand]\" /></span>\r\n @if (brandLabelKey(); as key) {\r\n <span class=\"ah__brand-name\">{{ key | translate }}</span>\r\n }\r\n </button>\r\n <ng-content select=\"[app-home-actions]\" />\r\n </header>\r\n\r\n <main class=\"ah__main\">\r\n @if (titleKey() || subtitleKey()) {\r\n <section class=\"ah__hero\">\r\n @if (titleKey(); as key) {\r\n <h1 class=\"ah__title\">{{ key | translate }}</h1>\r\n }\r\n @if (subtitleKey(); as key) {\r\n <p class=\"ah__sub\">{{ key | translate }}</p>\r\n }\r\n </section>\r\n }\r\n\r\n @for (row of rows(); track row.index) {\r\n <section\r\n class=\"ah__sec\"\r\n [class.ah__sec--secondary]=\"row.index > 0\"\r\n [attr.aria-label]=\"row.section.titleKey ? null : (modulesLabelKey() | translate)\"\r\n >\r\n @if (row.section.titleKey; as titleKey) {\r\n @if (row.section.collapsible) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__sec-hd\"\r\n (click)=\"toggle(row.index)\"\r\n [attr.aria-expanded]=\"row.expanded\"\r\n [attr.aria-controls]=\"sectionId(row.index)\"\r\n >\r\n <!-- Points end-ward when shut, down when open. `--open` wins over the RTL\r\n flip below because a downward chevron has no direction to mirror. -->\r\n <svg\r\n class=\"ah__sec-chev\"\r\n [class.ah__sec-chev--open]=\"row.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n <span class=\"ah__sec-title\">{{ titleKey | translate }}</span>\r\n <span class=\"ah__sec-count\">{{ row.section.modules.length }}</span>\r\n @if (row.hintKey; as hint) {\r\n <span class=\"ah__sec-hint\">{{ hint | translate }}</span>\r\n }\r\n </button>\r\n } @else {\r\n <h2 class=\"ah__sec-title ah__sec-title--static\">{{ titleKey | translate }}</h2>\r\n }\r\n }\r\n\r\n @if (row.expanded) {\r\n <div class=\"ah__grid\" [class.ah__grid--compact]=\"row.layout === 'compact'\" [id]=\"sectionId(row.index)\">\r\n @for (mod of row.section.modules; track mod.key) {\r\n <button\r\n type=\"button\"\r\n class=\"ah__card\"\r\n [class.ah__card--compact]=\"row.layout === 'compact'\"\r\n [disabled]=\"mod.disabled\"\r\n (click)=\"select(mod)\"\r\n >\r\n <span class=\"ah__card-ico\">\r\n @if (iconFor(mod.key); as tpl) {\r\n <ng-container *ngTemplateOutlet=\"tpl\" />\r\n } @else if (mod.iconClass) {\r\n <i [class]=\"mod.iconClass\" aria-hidden=\"true\"></i>\r\n }\r\n </span>\r\n\r\n @if (row.layout === 'compact') {\r\n <span class=\"ah__card-main\">\r\n <span class=\"ah__card-title\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc\">{{ descKey | translate }}</span>\r\n }\r\n </span>\r\n <svg\r\n class=\"ah__card-arrow\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"9 6 15 12 9 18\" />\r\n </svg>\r\n } @else {\r\n <!-- No \"Open \u203A\" affordance row \u2014 the design's module card (MainContent.dc.html)\r\n ends at the description; the whole card is the click target and hover carries\r\n the affordance. Removed at the 2026-08-17 fidelity pass. -->\r\n <span class=\"ah__card-title ah__card-title--feature\">{{ mod.labelKey | translate }}</span>\r\n @if (mod.descKey; as descKey) {\r\n <span class=\"ah__card-desc ah__card-desc--feature\">{{ descKey | translate }}</span>\r\n }\r\n }\r\n </button>\r\n }\r\n </div>\r\n }\r\n </section>\r\n }\r\n </main>\r\n</div>\r\n", styles: [":host{display:flex;flex-direction:column;min-height:100%;container-type:inline-size}.ah{display:flex;flex-direction:column;flex:1;min-height:100%}.ah__util{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:var(--sp-4) var(--sp-6)}:host-context(.window-content) .ah__brand{display:none}:host-context(.window-content) .ah__util{justify-content:flex-end}:host-context(.window-content) .ah__util:not(:has(>:not(.ah__brand))){display:none}.ah__brand{display:inline-flex;align-items:center;gap:var(--sp-2);padding:0;border:0;background:none;color:var(--ink);font-family:inherit;cursor:pointer}.ah__brand:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.ah__brand-name{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__main{flex:1;inline-size:100%;max-inline-size:1120px;margin-inline:auto;padding:56px 40px;display:flex;flex-direction:column;justify-content:center;gap:44px}.ah__hero{max-inline-size:640px}.ah__title{margin:0 0 var(--sp-3);font-size:44px;font-weight:var(--fw-semibold);letter-spacing:-.03em;text-wrap:balance;background:linear-gradient(180deg,var(--ink),var(--ink-2));-webkit-background-clip:text;background-clip:text;color:transparent}.ah__sub{margin:0;max-inline-size:560px;font-size:var(--text-lg);line-height:1.55;color:var(--ink-3);text-wrap:pretty}.ah__sec{display:flex;flex-direction:column;gap:var(--sp-4)}.ah__sec--secondary{padding-block-start:28px;border-block-start:1px solid var(--w08)}.ah__sec-hd{display:flex;align-items:center;gap:var(--sp-3);inline-size:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.ah__sec-hd:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.ah__sec-chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.ah__sec-title{font-size:var(--text-md);font-weight:var(--fw-semibold);letter-spacing:-.01em}.ah__sec-title--static{margin:0;color:var(--ink-3);font-size:var(--text-xs);letter-spacing:var(--tracking-wide);text-transform:uppercase}.ah__sec-count{display:inline-grid;place-items:center;min-inline-size:22px;block-size:20px;padding-inline:6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-2xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.ah__sec-hint{margin-inline-start:auto;font-size:var(--text-xs);color:var(--ink-3)}.ah__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}.ah__card{display:flex;flex-direction:column;align-items:stretch;position:relative;overflow:hidden;text-align:start;padding:20px;background-image:linear-gradient(160deg,var(--w055),var(--w02));border:1px solid var(--w09);border-radius:20px;color:inherit;font-family:inherit;cursor:pointer;animation:appTileIn .3s var(--nova-ease-micro) both}.ah__card:nth-child(1){animation-delay:0ms}.ah__card:nth-child(2){animation-delay:20ms}.ah__card:nth-child(3){animation-delay:40ms}.ah__card:nth-child(4){animation-delay:60ms}.ah__card:nth-child(5){animation-delay:80ms}.ah__card:nth-child(6){animation-delay:.1s}.ah__card:nth-child(7){animation-delay:.12s}.ah__card:nth-child(8){animation-delay:.14s}.ah__card:nth-child(9){animation-delay:.16s}.ah__card:nth-child(10){animation-delay:.18s}.ah__card:nth-child(11){animation-delay:.2s}.ah__card:nth-child(12){animation-delay:.22s}.ah__card:nth-child(n+13){animation-delay:.22s}.ah__card{transition:transform var(--t-overlay),box-shadow var(--t-overlay),border-color var(--t-state),background-image var(--t-state)}.ah__card:hover:not(:disabled){transform:translateY(-3px);border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:focus-visible{outline:0;border-color:color-mix(in oklab,var(--accent) 50%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent);box-shadow:0 0 0 3px var(--accent-soft),0 20px 46px color-mix(in oklab,var(--accent) 16%,transparent),var(--shadow-filter)}.ah__card:disabled{cursor:default;opacity:.5}.ah__card-ico{display:grid;place-items:center;inline-size:42px;block-size:42px;margin-block-end:16px;border-radius:13px;background:linear-gradient(140deg,color-mix(in srgb,var(--accent) 50%,transparent),color-mix(in srgb,var(--sys-teal) 22%,transparent));box-shadow:0 6px 16px color-mix(in srgb,var(--accent) 30%,transparent),inset 0 1px 0 var(--edge-highlight);border:0;color:var(--on-accent);font-size:var(--icon-lg)}.ah__card--compact:hover:not(:disabled) .ah__card-ico,.ah__card--compact:focus-visible .ah__card-ico{background:linear-gradient(135deg,var(--accent),var(--sys-teal));box-shadow:inset 0 1px 0 var(--edge-highlight);color:var(--on-accent)}.ah__card-title{font-size:var(--text-sm);font-weight:var(--fw-semibold);letter-spacing:-.01em;color:var(--ink)}.ah__card-title--feature{margin-block-end:5px;font-size:16.5px;line-height:1.25;letter-spacing:-.005em}.ah__card-desc{font-size:var(--text-xs);line-height:1.45;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ah__card-desc--feature{margin-block-end:0;font-size:13px;line-height:1.45;text-wrap:pretty;overflow:visible;white-space:normal}.ah__card-arrow{flex-shrink:0;transition:color var(--t-overlay),transform var(--t-overlay)}.ah__card--compact{flex-direction:row;align-items:center;gap:var(--sp-3);padding:14px 16px;background-color:var(--bg);background-image:linear-gradient(160deg,var(--w035),var(--w035));border-radius:16px;border-color:var(--w08)}.ah__card--compact:hover:not(:disabled),.ah__card--compact:focus-visible{border-color:color-mix(in oklab,var(--accent) 40%,transparent);background-image:linear-gradient(160deg,var(--tint-hover),transparent)}.ah__card--compact .ah__card-ico{inline-size:32px;block-size:32px;margin-block-end:0;flex-shrink:0;border-radius:10px;font-size:var(--icon-md);background:var(--bg-3);box-shadow:none;color:var(--ink)}.ah__card-main{display:flex;flex-direction:column;gap:2px;flex:1;min-inline-size:0}.ah__card--compact .ah__card-arrow{color:var(--ink-4)}.ah__card--compact:hover:not(:disabled) .ah__card-arrow{color:var(--accent);transform:translate(2px)}:host-context([dir=rtl]) .ah__card-arrow{transform:scaleX(-1)}:host-context([dir=rtl]) .ah__sec-chev:not(.ah__sec-chev--open){transform:scaleX(-1)}:host-context([dir=rtl]) .ah__card--compact:hover:not(:disabled) .ah__card-arrow{transform:scaleX(-1) translate(2px)}.ah__sec-chev--open{transform:rotate(90deg)}@container (width <= 900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@media(width<=900px){.ah__main{padding:40px 24px;gap:36px}.ah__title{font-size:36px}.ah__util{padding:var(--sp-3) var(--sp-5)}}@container (width <= 560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}@media(width<=560px){.ah__title{font-size:30px}.ah__sub{font-size:var(--text-sm)}.ah__sec-hint{display:none}}\n"] }]
24485
24529
  }], propDecorators: { brandLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandLabelKey", required: false }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }], subtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitleKey", required: false }] }], sections: [{ type: i0.Input, args: [{ isSignal: true, alias: "sections", required: false }] }], modulesLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "modulesLabelKey", required: false }] }], moduleSelected: [{ type: i0.Output, args: ["moduleSelected"] }], brandSelected: [{ type: i0.Output, args: ["brandSelected"] }], icons: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FlyModuleIconDirective), { isSignal: true }] }] } });
24486
24530
 
24487
24531
  /**
@@ -24590,7 +24634,7 @@ class FlyTabsComponent {
24590
24634
  }
24591
24635
  </div>
24592
24636
  <ng-content />
24593
- `, isInline: true, styles: [":host{display:block}.tb{display:flex;gap:0;min-inline-size:0;border-block-end:1px solid var(--w1)}.tb__tab{display:inline-flex;align-items:center;gap:6px;padding:6px 12px 10px;background:transparent;border:0;border-block-end:2px solid transparent;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--ink-3);cursor:pointer;font-family:inherit;margin-block-end:-1px;white-space:nowrap;transition:color var(--t-state),border-color var(--t-state)}.tb__tab:hover{color:var(--ink)}.tb__tab:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.tb__tab.tb__tab--active{color:var(--ink);border-block-end-color:var(--accent);font-weight:var(--fw-semibold)}.tb__count{font-family:var(--font-mono);font-size:10.5px;padding:1px 5px;background:var(--bg-3);border-radius:4px;color:var(--ink-4);font-variant-numeric:tabular-nums}.tb__tab--active .tb__count{color:var(--ink-3)}:host([data-variant=segmented]) .tb{display:inline-flex;gap:2px;padding:3px;border-radius:99px;background:var(--w07);border:1px solid var(--w08);border-block-end:1px solid var(--w08)}:host([data-variant=segmented]) .tb__tab{min-block-size:28px;padding:0 13px;margin-block-end:0;border-radius:99px;border-block-end:0;font-weight:var(--fw-medium);color:var(--w55)}:host([data-variant=segmented]) .tb__tab--active{background:var(--w14);box-shadow:var(--shadow-raised),inset 0 .5px 0 var(--w22);font-weight:var(--fw-semibold);color:var(--ink)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24637
+ `, isInline: true, styles: [":host{display:block}.tb{display:flex;gap:0;min-inline-size:0;border-block-end:1px solid var(--w1)}.tb__tab{display:inline-flex;align-items:center;gap:6px;padding:6px 12px 10px;background:transparent;border:0;border-block-end:2px solid transparent;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--ink-3);cursor:pointer;font-family:inherit;margin-block-end:-1px;white-space:nowrap;transition:color var(--t-state),border-color var(--t-state)}.tb__tab:hover{color:var(--ink)}.tb__tab:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px;outline-offset:-2px}.tb__tab.tb__tab--active{color:var(--ink);border-block-end-color:var(--accent);font-weight:var(--fw-semibold)}.tb__count{font-family:var(--font-mono);font-size:10.5px;padding:1px 5px;background:var(--bg-3);border-radius:4px;color:var(--ink-4);font-variant-numeric:tabular-nums}.tb__tab--active .tb__count{color:var(--ink-3)}:host([data-variant=segmented]) .tb{display:inline-flex;gap:2px;padding:3px;border-radius:99px;background:var(--w07);border:1px solid var(--w08);border-block-end:1px solid var(--w08)}:host([data-variant=segmented]) .tb__tab{min-block-size:28px;padding:0 13px;margin-block-end:0;border-radius:99px;border-block-end:0;font-weight:var(--fw-medium);color:var(--w55)}:host([data-variant=segmented]) .tb__tab--active{background:var(--w14);box-shadow:var(--shadow-raised),inset 0 .5px 0 var(--w22);font-weight:var(--fw-semibold);color:var(--ink)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24594
24638
  }
24595
24639
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyTabsComponent, decorators: [{
24596
24640
  type: Component,
@@ -24625,7 +24669,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
24625
24669
  }
24626
24670
  </div>
24627
24671
  <ng-content />
24628
- `, styles: [":host{display:block}.tb{display:flex;gap:0;min-inline-size:0;border-block-end:1px solid var(--w1)}.tb__tab{display:inline-flex;align-items:center;gap:6px;padding:6px 12px 10px;background:transparent;border:0;border-block-end:2px solid transparent;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--ink-3);cursor:pointer;font-family:inherit;margin-block-end:-1px;white-space:nowrap;transition:color var(--t-state),border-color var(--t-state)}.tb__tab:hover{color:var(--ink)}.tb__tab:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;outline-offset:-2px}.tb__tab.tb__tab--active{color:var(--ink);border-block-end-color:var(--accent);font-weight:var(--fw-semibold)}.tb__count{font-family:var(--font-mono);font-size:10.5px;padding:1px 5px;background:var(--bg-3);border-radius:4px;color:var(--ink-4);font-variant-numeric:tabular-nums}.tb__tab--active .tb__count{color:var(--ink-3)}:host([data-variant=segmented]) .tb{display:inline-flex;gap:2px;padding:3px;border-radius:99px;background:var(--w07);border:1px solid var(--w08);border-block-end:1px solid var(--w08)}:host([data-variant=segmented]) .tb__tab{min-block-size:28px;padding:0 13px;margin-block-end:0;border-radius:99px;border-block-end:0;font-weight:var(--fw-medium);color:var(--w55)}:host([data-variant=segmented]) .tb__tab--active{background:var(--w14);box-shadow:var(--shadow-raised),inset 0 .5px 0 var(--w22);font-weight:var(--fw-semibold);color:var(--ink)}\n"] }]
24672
+ `, styles: [":host{display:block}.tb{display:flex;gap:0;min-inline-size:0;border-block-end:1px solid var(--w1)}.tb__tab{display:inline-flex;align-items:center;gap:6px;padding:6px 12px 10px;background:transparent;border:0;border-block-end:2px solid transparent;font-size:var(--text-sm);font-weight:var(--fw-medium);color:var(--ink-3);cursor:pointer;font-family:inherit;margin-block-end:-1px;white-space:nowrap;transition:color var(--t-state),border-color var(--t-state)}.tb__tab:hover{color:var(--ink)}.tb__tab:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px;outline-offset:-2px}.tb__tab.tb__tab--active{color:var(--ink);border-block-end-color:var(--accent);font-weight:var(--fw-semibold)}.tb__count{font-family:var(--font-mono);font-size:10.5px;padding:1px 5px;background:var(--bg-3);border-radius:4px;color:var(--ink-4);font-variant-numeric:tabular-nums}.tb__tab--active .tb__count{color:var(--ink-3)}:host([data-variant=segmented]) .tb{display:inline-flex;gap:2px;padding:3px;border-radius:99px;background:var(--w07);border:1px solid var(--w08);border-block-end:1px solid var(--w08)}:host([data-variant=segmented]) .tb__tab{min-block-size:28px;padding:0 13px;margin-block-end:0;border-radius:99px;border-block-end:0;font-weight:var(--fw-medium);color:var(--w55)}:host([data-variant=segmented]) .tb__tab--active{background:var(--w14);box-shadow:var(--shadow-raised),inset 0 .5px 0 var(--w22);font-weight:var(--fw-semibold);color:var(--ink)}\n"] }]
24629
24673
  }], propDecorators: { tablist: [{ type: i0.ViewChild, args: ['tablist', { isSignal: true }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], ariaLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelKey", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], tabItems: [{ type: i0.ContentChildren, args: [forwardRef(() => FlyTabComponent), { isSignal: true }] }] } });
24630
24674
  /**
24631
24675
  * One tab of a `fly-tabs` group: declares the tab button (id, label, optional
@@ -24734,7 +24778,7 @@ class FlyCollapsibleComponent {
24734
24778
  <ng-content />
24735
24779
  </div>
24736
24780
  }
24737
- `, isInline: true, styles: [":host{display:flex;flex-direction:column;gap:var(--sp-4)}.cl__hd{display:flex;align-items:center;gap:10px;width:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.cl__hd:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.cl__chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.cl__chev.is-open{transform:rotate(90deg)}:host-context(.rtl) .cl__chev:not(.is-open),:host-context([dir=rtl]) .cl__chev:not(.is-open){transform:scaleX(-1)}.cl__t{font-size:15px;font-weight:var(--fw-semibold);letter-spacing:-.01em}.cl__count{display:inline-grid;place-items:center;min-width:22px;height:20px;padding:0 6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.cl__hint{margin-inline-start:auto;font-size:var(--text-sm);color:var(--ink-3)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24781
+ `, isInline: true, styles: [":host{display:flex;flex-direction:column;gap:var(--sp-4)}.cl__hd{display:flex;align-items:center;gap:10px;width:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.cl__hd:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.cl__chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.cl__chev.is-open{transform:rotate(90deg)}:host-context(.rtl) .cl__chev:not(.is-open),:host-context([dir=rtl]) .cl__chev:not(.is-open){transform:scaleX(-1)}.cl__t{font-size:15px;font-weight:var(--fw-semibold);letter-spacing:-.01em}.cl__count{display:inline-grid;place-items:center;min-width:22px;height:20px;padding:0 6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.cl__hint{margin-inline-start:auto;font-size:var(--text-sm);color:var(--ink-3)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24738
24782
  }
24739
24783
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyCollapsibleComponent, decorators: [{
24740
24784
  type: Component,
@@ -24778,7 +24822,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
24778
24822
  <ng-content />
24779
24823
  </div>
24780
24824
  }
24781
- `, styles: [":host{display:flex;flex-direction:column;gap:var(--sp-4)}.cl__hd{display:flex;align-items:center;gap:10px;width:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.cl__hd:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.cl__chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.cl__chev.is-open{transform:rotate(90deg)}:host-context(.rtl) .cl__chev:not(.is-open),:host-context([dir=rtl]) .cl__chev:not(.is-open){transform:scaleX(-1)}.cl__t{font-size:15px;font-weight:var(--fw-semibold);letter-spacing:-.01em}.cl__count{display:inline-grid;place-items:center;min-width:22px;height:20px;padding:0 6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.cl__hint{margin-inline-start:auto;font-size:var(--text-sm);color:var(--ink-3)}\n"] }]
24825
+ `, styles: [":host{display:flex;flex-direction:column;gap:var(--sp-4)}.cl__hd{display:flex;align-items:center;gap:10px;width:100%;padding:0;background:none;border:0;cursor:pointer;font-family:inherit;color:var(--ink);text-align:start}.cl__hd:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.cl__chev{flex-shrink:0;color:var(--ink-3);transition:transform var(--t-overlay)}.cl__chev.is-open{transform:rotate(90deg)}:host-context(.rtl) .cl__chev:not(.is-open),:host-context([dir=rtl]) .cl__chev:not(.is-open){transform:scaleX(-1)}.cl__t{font-size:15px;font-weight:var(--fw-semibold);letter-spacing:-.01em}.cl__count{display:inline-grid;place-items:center;min-width:22px;height:20px;padding:0 6px;border-radius:999px;background:var(--bg-3);border:1px solid var(--line);font-size:var(--text-xs);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums;color:var(--ink-3)}.cl__hint{margin-inline-start:auto;font-size:var(--text-sm);color:var(--ink-3)}\n"] }]
24782
24826
  }], propDecorators: { expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], hintKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintKey", required: false }] }] } });
24783
24827
 
24784
24828
  /**
@@ -24959,7 +25003,7 @@ class FlyCheckboxComponent {
24959
25003
  }
24960
25004
  </span>
24961
25005
  </label>
24962
- `, isInline: true, styles: [":host{display:block}.cb{display:inline-flex;align-items:flex-start;gap:10px;cursor:pointer;padding:10px 12px;border:1px solid var(--w1);border-radius:12px;background:var(--w035);width:100%;box-sizing:border-box;position:relative;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.cb:hover{background:var(--w05)}.cb:has(input:disabled){opacity:.38;filter:saturate(.6);cursor:not-allowed}.cb input{position:absolute;opacity:0;pointer-events:none}.cb__box{width:15px;height:15px;border:1.5px solid var(--w22);border-radius:4px;background:var(--w05);flex-shrink:0;margin-top:1px;position:relative;transition:background var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.cb input:checked+.cb__box{background:var(--accent);border-color:var(--accent)}.cb input:checked+.cb__box:after{content:\"\";position:absolute;top:2px;inset-inline-start:4px;width:4px;height:8px;border:solid var(--on-accent);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.cb input:focus-visible+.cb__box{outline:3px solid var(--accent);outline-offset:3px}.cb__l{display:flex;flex-direction:column;gap:1px}.cb__text{font:600 12.5px/1.35 var(--font-family);color:var(--w85)}.cb__hint{font:400 11.5px/1.4 var(--font-family);color:var(--w42)}@media(pointer:coarse){.cb{min-block-size:44px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25006
+ `, isInline: true, styles: [":host{display:block}.cb{display:inline-flex;align-items:flex-start;gap:10px;cursor:pointer;padding:10px 12px;border:1px solid var(--w1);border-radius:12px;background:var(--w035);width:100%;box-sizing:border-box;position:relative;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.cb:hover{background:var(--w05)}.cb:has(input:disabled){opacity:.38;filter:saturate(.6);cursor:not-allowed}.cb input{position:absolute;opacity:0;pointer-events:none}.cb__box{width:15px;height:15px;border:1.5px solid var(--w22);border-radius:4px;background:var(--w05);flex-shrink:0;margin-top:1px;position:relative;transition:background var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.cb input:checked+.cb__box{background:var(--accent);border-color:var(--accent)}.cb input:checked+.cb__box:after{content:\"\";position:absolute;top:2px;inset-inline-start:4px;width:4px;height:8px;border:solid var(--on-accent);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.cb input:focus-visible+.cb__box{outline:3px solid;outline-color:var(--accent);outline-offset:3px}.cb__l{display:flex;flex-direction:column;gap:1px}.cb__text{font:600 12.5px/1.35 var(--font-family);color:var(--w85)}.cb__hint{font:400 11.5px/1.4 var(--font-family);color:var(--w42)}@media(pointer:coarse){.cb{min-block-size:44px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
24963
25007
  }
24964
25008
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyCheckboxComponent, decorators: [{
24965
25009
  type: Component,
@@ -24985,7 +25029,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
24985
25029
  }
24986
25030
  </span>
24987
25031
  </label>
24988
- `, styles: [":host{display:block}.cb{display:inline-flex;align-items:flex-start;gap:10px;cursor:pointer;padding:10px 12px;border:1px solid var(--w1);border-radius:12px;background:var(--w035);width:100%;box-sizing:border-box;position:relative;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.cb:hover{background:var(--w05)}.cb:has(input:disabled){opacity:.38;filter:saturate(.6);cursor:not-allowed}.cb input{position:absolute;opacity:0;pointer-events:none}.cb__box{width:15px;height:15px;border:1.5px solid var(--w22);border-radius:4px;background:var(--w05);flex-shrink:0;margin-top:1px;position:relative;transition:background var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.cb input:checked+.cb__box{background:var(--accent);border-color:var(--accent)}.cb input:checked+.cb__box:after{content:\"\";position:absolute;top:2px;inset-inline-start:4px;width:4px;height:8px;border:solid var(--on-accent);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.cb input:focus-visible+.cb__box{outline:3px solid var(--accent);outline-offset:3px}.cb__l{display:flex;flex-direction:column;gap:1px}.cb__text{font:600 12.5px/1.35 var(--font-family);color:var(--w85)}.cb__hint{font:400 11.5px/1.4 var(--font-family);color:var(--w42)}@media(pointer:coarse){.cb{min-block-size:44px}}\n"] }]
25032
+ `, styles: [":host{display:block}.cb{display:inline-flex;align-items:flex-start;gap:10px;cursor:pointer;padding:10px 12px;border:1px solid var(--w1);border-radius:12px;background:var(--w035);width:100%;box-sizing:border-box;position:relative;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.cb:hover{background:var(--w05)}.cb:has(input:disabled){opacity:.38;filter:saturate(.6);cursor:not-allowed}.cb input{position:absolute;opacity:0;pointer-events:none}.cb__box{width:15px;height:15px;border:1.5px solid var(--w22);border-radius:4px;background:var(--w05);flex-shrink:0;margin-top:1px;position:relative;transition:background var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.cb input:checked+.cb__box{background:var(--accent);border-color:var(--accent)}.cb input:checked+.cb__box:after{content:\"\";position:absolute;top:2px;inset-inline-start:4px;width:4px;height:8px;border:solid var(--on-accent);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.cb input:focus-visible+.cb__box{outline:3px solid;outline-color:var(--accent);outline-offset:3px}.cb__l{display:flex;flex-direction:column;gap:1px}.cb__text{font:600 12.5px/1.35 var(--font-family);color:var(--w85)}.cb__hint{font:400 11.5px/1.4 var(--font-family);color:var(--w42)}@media(pointer:coarse){.cb{min-block-size:44px}}\n"] }]
24989
25033
  }], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], labelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelKey", required: false }] }], hintKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintKey", required: false }] }] } });
24990
25034
 
24991
25035
  /**
@@ -25098,7 +25142,7 @@ class FlySegmentedComponent {
25098
25142
  </button>
25099
25143
  }
25100
25144
  </div>
25101
- `, isInline: true, styles: [":host{display:inline-flex}.seg{display:flex;flex-wrap:wrap;gap:3px;padding:3px;background:var(--w07);border:1px solid var(--w08);border-radius:99px}.seg[data-variant=pills]{gap:6px;padding:0;background:transparent;border:0;border-radius:0}.seg__btn{display:inline-flex;align-items:center;gap:6px;min-block-size:28px;padding:0 13px;border:0;background:transparent;color:var(--w55);font:500 12.5px/1.3 var(--font-family);font-family:inherit;border-radius:99px;cursor:pointer;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.seg__btn:hover{color:var(--w85)}.seg__btn:focus-visible{outline:3px solid var(--accent);outline-offset:3px}.seg__btn:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.seg__btn.on{background:var(--w14);color:var(--w95);font-weight:600;box-shadow:var(--shadow-card),var(--glass2-inset)}.seg__count{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:10.5px;padding:1px 5px;background:var(--w1);border-radius:4px;color:var(--w42)}.seg__btn.on .seg__count{color:var(--w55)}.seg[data-variant=pills] .seg__btn{min-block-size:30px;padding:0 12px;border:.5px solid var(--w12);background:var(--w04);color:var(--w7);border-radius:99px;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.seg[data-variant=pills] .seg__btn:hover:not(.on){background:var(--w08);border-color:var(--w2);color:var(--ink)}.seg[data-variant=pills] .seg__btn.on{border-color:transparent;background:var(--accent);color:var(--on-accent);font-weight:500;box-shadow:none}.seg[data-variant=pills] .seg__count{padding:2px 6px;border-radius:7px;font-family:var(--font-family);font-size:10.5px;font-weight:var(--fw-semibold);color:inherit}.seg[data-variant=pills] .seg__btn.on .seg__count{background:var(--w22);color:inherit}@media(pointer:coarse){.seg__btn,.seg[data-variant=pills] .seg__btn{min-block-size:44px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25145
+ `, isInline: true, styles: [":host{display:inline-flex}.seg{display:flex;flex-wrap:wrap;gap:3px;padding:3px;background:var(--w07);border:1px solid var(--w08);border-radius:99px}.seg[data-variant=pills]{gap:6px;padding:0;background:transparent;border:0;border-radius:0}.seg__btn{display:inline-flex;align-items:center;gap:6px;min-block-size:28px;padding:0 13px;border:0;background:transparent;color:var(--w55);font:500 12.5px/1.3 var(--font-family);font-family:inherit;border-radius:99px;cursor:pointer;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.seg__btn:hover{color:var(--w85)}.seg__btn:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px}.seg__btn:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.seg__btn.on{background:var(--w14);color:var(--w95);font-weight:600;box-shadow:var(--shadow-card),var(--glass2-inset)}.seg__count{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:10.5px;padding:1px 5px;background:var(--w1);border-radius:4px;color:var(--w42)}.seg__btn.on .seg__count{color:var(--w55)}.seg[data-variant=pills] .seg__btn{min-block-size:30px;padding:0 12px;border:.5px solid var(--w12);background:var(--w04);color:var(--w7);border-radius:99px;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.seg[data-variant=pills] .seg__btn:hover:not(.on){background:var(--w08);border-color:var(--w2);color:var(--ink)}.seg[data-variant=pills] .seg__btn.on{border-color:transparent;background:var(--accent);color:var(--on-accent);font-weight:500;box-shadow:none}.seg[data-variant=pills] .seg__count{padding:2px 6px;border-radius:7px;font-family:var(--font-family);font-size:10.5px;font-weight:var(--fw-semibold);color:inherit}.seg[data-variant=pills] .seg__btn.on .seg__count{background:var(--w22);color:inherit}@media(pointer:coarse){.seg__btn,.seg[data-variant=pills] .seg__btn{min-block-size:44px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25102
25146
  }
25103
25147
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlySegmentedComponent, decorators: [{
25104
25148
  type: Component,
@@ -25130,7 +25174,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
25130
25174
  </button>
25131
25175
  }
25132
25176
  </div>
25133
- `, styles: [":host{display:inline-flex}.seg{display:flex;flex-wrap:wrap;gap:3px;padding:3px;background:var(--w07);border:1px solid var(--w08);border-radius:99px}.seg[data-variant=pills]{gap:6px;padding:0;background:transparent;border:0;border-radius:0}.seg__btn{display:inline-flex;align-items:center;gap:6px;min-block-size:28px;padding:0 13px;border:0;background:transparent;color:var(--w55);font:500 12.5px/1.3 var(--font-family);font-family:inherit;border-radius:99px;cursor:pointer;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.seg__btn:hover{color:var(--w85)}.seg__btn:focus-visible{outline:3px solid var(--accent);outline-offset:3px}.seg__btn:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.seg__btn.on{background:var(--w14);color:var(--w95);font-weight:600;box-shadow:var(--shadow-card),var(--glass2-inset)}.seg__count{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:10.5px;padding:1px 5px;background:var(--w1);border-radius:4px;color:var(--w42)}.seg__btn.on .seg__count{color:var(--w55)}.seg[data-variant=pills] .seg__btn{min-block-size:30px;padding:0 12px;border:.5px solid var(--w12);background:var(--w04);color:var(--w7);border-radius:99px;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.seg[data-variant=pills] .seg__btn:hover:not(.on){background:var(--w08);border-color:var(--w2);color:var(--ink)}.seg[data-variant=pills] .seg__btn.on{border-color:transparent;background:var(--accent);color:var(--on-accent);font-weight:500;box-shadow:none}.seg[data-variant=pills] .seg__count{padding:2px 6px;border-radius:7px;font-family:var(--font-family);font-size:10.5px;font-weight:var(--fw-semibold);color:inherit}.seg[data-variant=pills] .seg__btn.on .seg__count{background:var(--w22);color:inherit}@media(pointer:coarse){.seg__btn,.seg[data-variant=pills] .seg__btn{min-block-size:44px}}\n"] }]
25177
+ `, styles: [":host{display:inline-flex}.seg{display:flex;flex-wrap:wrap;gap:3px;padding:3px;background:var(--w07);border:1px solid var(--w08);border-radius:99px}.seg[data-variant=pills]{gap:6px;padding:0;background:transparent;border:0;border-radius:0}.seg__btn{display:inline-flex;align-items:center;gap:6px;min-block-size:28px;padding:0 13px;border:0;background:transparent;color:var(--w55);font:500 12.5px/1.3 var(--font-family);font-family:inherit;border-radius:99px;cursor:pointer;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro)}.seg__btn:hover{color:var(--w85)}.seg__btn:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px}.seg__btn:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.seg__btn.on{background:var(--w14);color:var(--w95);font-weight:600;box-shadow:var(--shadow-card),var(--glass2-inset)}.seg__count{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:10.5px;padding:1px 5px;background:var(--w1);border-radius:4px;color:var(--w42)}.seg__btn.on .seg__count{color:var(--w55)}.seg[data-variant=pills] .seg__btn{min-block-size:30px;padding:0 12px;border:.5px solid var(--w12);background:var(--w04);color:var(--w7);border-radius:99px;transition:background var(--nova-duration-hover) var(--nova-ease-micro),color var(--nova-duration-hover) var(--nova-ease-micro),border-color var(--nova-duration-hover) var(--nova-ease-micro)}.seg[data-variant=pills] .seg__btn:hover:not(.on){background:var(--w08);border-color:var(--w2);color:var(--ink)}.seg[data-variant=pills] .seg__btn.on{border-color:transparent;background:var(--accent);color:var(--on-accent);font-weight:500;box-shadow:none}.seg[data-variant=pills] .seg__count{padding:2px 6px;border-radius:7px;font-family:var(--font-family);font-size:10.5px;font-weight:var(--fw-semibold);color:inherit}.seg[data-variant=pills] .seg__btn.on .seg__count{background:var(--w22);color:inherit}@media(pointer:coarse){.seg__btn,.seg[data-variant=pills] .seg__btn{min-block-size:44px}}\n"] }]
25134
25178
  }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelKey", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], values: [{ type: i0.Input, args: [{ isSignal: true, alias: "values", required: false }] }, { type: i0.Output, args: ["valuesChange"] }] } });
25135
25179
 
25136
25180
  /**
@@ -25160,7 +25204,7 @@ class FlyToggleComponent {
25160
25204
  <span class="tg__l">{{ key | translate }}</span>
25161
25205
  }
25162
25206
  </button>
25163
- `, isInline: true, styles: [":host{display:inline-flex}.tg{display:inline-flex;align-items:center;gap:8px;border:0;background:transparent;padding:0;cursor:pointer;font-family:inherit}.tg:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.tg:focus-visible{outline:none}.tg:focus-visible .tg__track{outline:3px solid var(--accent);outline-offset:3px}.tg__track{width:30px;height:18px;border-radius:999px;background:var(--w22);position:relative;flex-shrink:0;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.tg__knob{position:absolute;top:2px;inset-inline-start:2px;width:14px;height:14px;border-radius:50%;background:var(--on-accent);box-shadow:var(--shadow-raised);transition:transform var(--nova-duration-settle) var(--nova-ease-structural)}.tg[aria-checked=true] .tg__track{background:var(--accent)}.tg[aria-checked=true] .tg__knob{transform:translate(12px)}:host-context([dir=rtl]) .tg[aria-checked=true] .tg__knob{transform:translate(-12px)}.tg__l{font:400 13px/1.3 var(--font-family);color:var(--w7)}@media(pointer:coarse){.tg{min-block-size:44px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25207
+ `, isInline: true, styles: [":host{display:inline-flex}.tg{display:inline-flex;align-items:center;gap:8px;border:0;background:transparent;padding:0;cursor:pointer;font-family:inherit}.tg:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.tg:focus-visible{outline:none}.tg:focus-visible .tg__track{outline:3px solid;outline-color:var(--accent);outline-offset:3px}.tg__track{width:30px;height:18px;border-radius:999px;background:var(--w22);position:relative;flex-shrink:0;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.tg__knob{position:absolute;top:2px;inset-inline-start:2px;width:14px;height:14px;border-radius:50%;background:var(--on-accent);box-shadow:var(--shadow-raised);transition:transform var(--nova-duration-settle) var(--nova-ease-structural)}.tg[aria-checked=true] .tg__track{background:var(--accent)}.tg[aria-checked=true] .tg__knob{transform:translate(12px)}:host-context([dir=rtl]) .tg[aria-checked=true] .tg__knob{transform:translate(-12px)}.tg__l{font:400 13px/1.3 var(--font-family);color:var(--w7)}@media(pointer:coarse){.tg{min-block-size:44px}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25164
25208
  }
25165
25209
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyToggleComponent, decorators: [{
25166
25210
  type: Component,
@@ -25179,7 +25223,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
25179
25223
  <span class="tg__l">{{ key | translate }}</span>
25180
25224
  }
25181
25225
  </button>
25182
- `, styles: [":host{display:inline-flex}.tg{display:inline-flex;align-items:center;gap:8px;border:0;background:transparent;padding:0;cursor:pointer;font-family:inherit}.tg:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.tg:focus-visible{outline:none}.tg:focus-visible .tg__track{outline:3px solid var(--accent);outline-offset:3px}.tg__track{width:30px;height:18px;border-radius:999px;background:var(--w22);position:relative;flex-shrink:0;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.tg__knob{position:absolute;top:2px;inset-inline-start:2px;width:14px;height:14px;border-radius:50%;background:var(--on-accent);box-shadow:var(--shadow-raised);transition:transform var(--nova-duration-settle) var(--nova-ease-structural)}.tg[aria-checked=true] .tg__track{background:var(--accent)}.tg[aria-checked=true] .tg__knob{transform:translate(12px)}:host-context([dir=rtl]) .tg[aria-checked=true] .tg__knob{transform:translate(-12px)}.tg__l{font:400 13px/1.3 var(--font-family);color:var(--w7)}@media(pointer:coarse){.tg{min-block-size:44px}}\n"] }]
25226
+ `, styles: [":host{display:inline-flex}.tg{display:inline-flex;align-items:center;gap:8px;border:0;background:transparent;padding:0;cursor:pointer;font-family:inherit}.tg:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.tg:focus-visible{outline:none}.tg:focus-visible .tg__track{outline:3px solid;outline-color:var(--accent);outline-offset:3px}.tg__track{width:30px;height:18px;border-radius:999px;background:var(--w22);position:relative;flex-shrink:0;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.tg__knob{position:absolute;top:2px;inset-inline-start:2px;width:14px;height:14px;border-radius:50%;background:var(--on-accent);box-shadow:var(--shadow-raised);transition:transform var(--nova-duration-settle) var(--nova-ease-structural)}.tg[aria-checked=true] .tg__track{background:var(--accent)}.tg[aria-checked=true] .tg__knob{transform:translate(12px)}:host-context([dir=rtl]) .tg[aria-checked=true] .tg__knob{transform:translate(-12px)}.tg__l{font:400 13px/1.3 var(--font-family);color:var(--w7)}@media(pointer:coarse){.tg{min-block-size:44px}}\n"] }]
25183
25227
  }], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], labelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelKey", required: false }] }], ariaLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelKey", required: false }] }] } });
25184
25228
 
25185
25229
  /** Clamp a slider value into [min, max]; NaN collapses to min. */
@@ -25302,7 +25346,7 @@ class FlySliderComponent {
25302
25346
  />
25303
25347
  <span class="rng__pct" aria-hidden="true">{{ unit() }}</span>
25304
25348
  </div>
25305
- `, isInline: true, styles: [":host{display:block}.rng{display:grid;grid-template-columns:1fr 64px auto;gap:8px;align-items:center}.rng input[type=range]{appearance:none;height:6px;border-radius:999px;outline:none;cursor:pointer;background:var(--rng-track, var(--w14));padding:0;border:0;margin:0;width:100%;min-width:0}.rng input[type=range]:focus-visible{outline:3px solid var(--accent);outline-offset:3px}.rng input[type=range]:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.rng input[type=range]::-webkit-slider-thumb{appearance:none;width:16px;height:16px;background:var(--on-accent);border:2px solid var(--accent);border-radius:50%;box-shadow:var(--shadow-raised);cursor:grab}.rng input[type=range]::-moz-range-thumb{width:16px;height:16px;background:var(--on-accent);border:2px solid var(--accent);border-radius:50%;box-shadow:var(--shadow-raised);cursor:grab}.rng__num{width:100%;box-sizing:border-box;height:32px;padding:0 10px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:12.5px;text-align:center;outline:none;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.rng__num:focus,.rng__num:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.rng__pct{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:12.5px;color:var(--w42)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25349
+ `, isInline: true, styles: [":host{display:block}.rng{display:grid;grid-template-columns:1fr 64px auto;gap:8px;align-items:center}.rng input[type=range]{appearance:none;height:6px;border-radius:999px;outline:none;cursor:pointer;background:var(--rng-track, var(--w14));padding:0;border:0;margin:0;width:100%;min-width:0}.rng input[type=range]:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px}.rng input[type=range]:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.rng input[type=range]::-webkit-slider-thumb{appearance:none;width:16px;height:16px;background:var(--on-accent);border:2px solid var(--accent);border-radius:50%;box-shadow:var(--shadow-raised);cursor:grab}.rng input[type=range]::-moz-range-thumb{width:16px;height:16px;background:var(--on-accent);border:2px solid var(--accent);border-radius:50%;box-shadow:var(--shadow-raised);cursor:grab}.rng__num{width:100%;box-sizing:border-box;height:32px;padding:0 10px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:12.5px;text-align:center;outline:none;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.rng__num:focus,.rng__num:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.rng__pct{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:12.5px;color:var(--w42)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25306
25350
  }
25307
25351
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlySliderComponent, decorators: [{
25308
25352
  type: Component,
@@ -25332,7 +25376,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
25332
25376
  />
25333
25377
  <span class="rng__pct" aria-hidden="true">{{ unit() }}</span>
25334
25378
  </div>
25335
- `, styles: [":host{display:block}.rng{display:grid;grid-template-columns:1fr 64px auto;gap:8px;align-items:center}.rng input[type=range]{appearance:none;height:6px;border-radius:999px;outline:none;cursor:pointer;background:var(--rng-track, var(--w14));padding:0;border:0;margin:0;width:100%;min-width:0}.rng input[type=range]:focus-visible{outline:3px solid var(--accent);outline-offset:3px}.rng input[type=range]:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.rng input[type=range]::-webkit-slider-thumb{appearance:none;width:16px;height:16px;background:var(--on-accent);border:2px solid var(--accent);border-radius:50%;box-shadow:var(--shadow-raised);cursor:grab}.rng input[type=range]::-moz-range-thumb{width:16px;height:16px;background:var(--on-accent);border:2px solid var(--accent);border-radius:50%;box-shadow:var(--shadow-raised);cursor:grab}.rng__num{width:100%;box-sizing:border-box;height:32px;padding:0 10px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:12.5px;text-align:center;outline:none;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.rng__num:focus,.rng__num:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.rng__pct{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:12.5px;color:var(--w42)}\n"] }]
25379
+ `, styles: [":host{display:block}.rng{display:grid;grid-template-columns:1fr 64px auto;gap:8px;align-items:center}.rng input[type=range]{appearance:none;height:6px;border-radius:999px;outline:none;cursor:pointer;background:var(--rng-track, var(--w14));padding:0;border:0;margin:0;width:100%;min-width:0}.rng input[type=range]:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px}.rng input[type=range]:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.rng input[type=range]::-webkit-slider-thumb{appearance:none;width:16px;height:16px;background:var(--on-accent);border:2px solid var(--accent);border-radius:50%;box-shadow:var(--shadow-raised);cursor:grab}.rng input[type=range]::-moz-range-thumb{width:16px;height:16px;background:var(--on-accent);border:2px solid var(--accent);border-radius:50%;box-shadow:var(--shadow-raised);cursor:grab}.rng__num{width:100%;box-sizing:border-box;height:32px;padding:0 10px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:12.5px;text-align:center;outline:none;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.rng__num:focus,.rng__num:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.rng__pct{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:12.5px;color:var(--w42)}\n"] }]
25336
25380
  }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clampOnInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "clampOnInput", required: false }] }], ariaLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelKey", required: false }] }], numberBox: [{ type: i0.ViewChild, args: ['num', { isSignal: true }] }] } });
25337
25381
 
25338
25382
  /** Parse free text into tags. Default mode splits on any run of whitespace
@@ -25467,7 +25511,7 @@ class FlyTagsInputComponent {
25467
25511
  @if (invalidTags().length > 0) {
25468
25512
  <div class="ti__err"><ng-content select="[tags-error]" /></div>
25469
25513
  }
25470
- `, isInline: true, styles: [":host{display:flex;flex-direction:column;min-width:0}.ti__input{width:100%;box-sizing:border-box;height:36px;padding:0 11px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family);min-width:0;max-width:100%;outline:none;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.ti__input::placeholder{color:var(--w42)}.ti__input:focus,.ti__input:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.ti__input.invalid{border-color:var(--sys-red-txt)}.ti__input:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.ti__suggestions{margin:6px 0 0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:5px}.ti__suggestions li{display:inline-block}.ti__suggestions button{border:0;border-radius:99px;padding:3px 8px;font:500 12px/1.3 var(--font-family);color:var(--w85);background:var(--w06);cursor:pointer;font-family:inherit;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.ti__suggestions button:hover{background:var(--w1)}.ti__suggestions button:focus-visible{outline:3px solid var(--accent);outline-offset:3px}.ti__err{margin-top:2px;font-size:11px;color:var(--sys-red-txt)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25514
+ `, isInline: true, styles: [":host{display:flex;flex-direction:column;min-width:0}.ti__input{width:100%;box-sizing:border-box;height:36px;padding:0 11px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family);min-width:0;max-width:100%;outline:none;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.ti__input::placeholder{color:var(--w42)}.ti__input:focus,.ti__input:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.ti__input.invalid{border-color:var(--sys-red-txt)}.ti__input:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.ti__suggestions{margin:6px 0 0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:5px}.ti__suggestions li{display:inline-block}.ti__suggestions button{border:0;border-radius:99px;padding:3px 8px;font:500 12px/1.3 var(--font-family);color:var(--w85);background:var(--w06);cursor:pointer;font-family:inherit;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.ti__suggestions button:hover{background:var(--w1)}.ti__suggestions button:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px}.ti__err{margin-top:2px;font-size:11px;color:var(--sys-red-txt)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25471
25515
  }
25472
25516
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyTagsInputComponent, decorators: [{
25473
25517
  type: Component,
@@ -25493,7 +25537,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
25493
25537
  @if (invalidTags().length > 0) {
25494
25538
  <div class="ti__err"><ng-content select="[tags-error]" /></div>
25495
25539
  }
25496
- `, styles: [":host{display:flex;flex-direction:column;min-width:0}.ti__input{width:100%;box-sizing:border-box;height:36px;padding:0 11px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family);min-width:0;max-width:100%;outline:none;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.ti__input::placeholder{color:var(--w42)}.ti__input:focus,.ti__input:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.ti__input.invalid{border-color:var(--sys-red-txt)}.ti__input:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.ti__suggestions{margin:6px 0 0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:5px}.ti__suggestions li{display:inline-block}.ti__suggestions button{border:0;border-radius:99px;padding:3px 8px;font:500 12px/1.3 var(--font-family);color:var(--w85);background:var(--w06);cursor:pointer;font-family:inherit;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.ti__suggestions button:hover{background:var(--w1)}.ti__suggestions button:focus-visible{outline:3px solid var(--accent);outline-offset:3px}.ti__err{margin-top:2px;font-size:11px;color:var(--sys-red-txt)}\n"] }]
25540
+ `, styles: [":host{display:flex;flex-direction:column;min-width:0}.ti__input{width:100%;box-sizing:border-box;height:36px;padding:0 11px;border:1px solid var(--w14);border-radius:10px;background:var(--w05);color:var(--w85);font:500 13px/1.3 var(--font-family);min-width:0;max-width:100%;outline:none;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.ti__input::placeholder{color:var(--w42)}.ti__input:focus,.ti__input:focus-visible{outline:none;border-color:var(--accent);background:var(--w07)}.ti__input.invalid{border-color:var(--sys-red-txt)}.ti__input:disabled{opacity:.38;filter:saturate(.6);cursor:not-allowed}.ti__suggestions{margin:6px 0 0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:5px}.ti__suggestions li{display:inline-block}.ti__suggestions button{border:0;border-radius:99px;padding:3px 8px;font:500 12px/1.3 var(--font-family);color:var(--w85);background:var(--w06);cursor:pointer;font-family:inherit;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.ti__suggestions button:hover{background:var(--w1)}.ti__suggestions button:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px}.ti__err{margin-top:2px;font-size:11px;color:var(--sys-red-txt)}\n"] }]
25497
25541
  }], ctorParameters: () => [], propDecorators: { tags: [{ type: i0.Input, args: [{ isSignal: true, alias: "tags", required: false }] }, { type: i0.Output, args: ["tagsChange"] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], placeholderKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholderKey", required: false }] }], invalidTags: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalidTags", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelKey", required: false }] }], separators: [{ type: i0.Input, args: [{ isSignal: true, alias: "separators", required: false }] }], dedupe: [{ type: i0.Input, args: [{ isSignal: true, alias: "dedupe", required: false }] }] } });
25498
25542
 
25499
25543
  /**
@@ -25641,11 +25685,11 @@ class BilingualFieldComponent {
25641
25685
  this.valueAr.set(cleaned);
25642
25686
  }
25643
25687
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: BilingualFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
25644
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: BilingualFieldComponent, isStandalone: true, selector: "fly-bilingual-field", inputs: { labelEnKey: { classPropertyName: "labelEnKey", publicName: "labelEnKey", isSignal: true, isRequired: false, transformFunction: null }, labelArKey: { classPropertyName: "labelArKey", publicName: "labelArKey", isSignal: true, isRequired: false, transformFunction: null }, placeholderEn: { classPropertyName: "placeholderEn", publicName: "placeholderEn", isSignal: true, isRequired: false, transformFunction: null }, placeholderAr: { classPropertyName: "placeholderAr", publicName: "placeholderAr", isSignal: true, isRequired: false, transformFunction: null }, multiline: { classPropertyName: "multiline", publicName: "multiline", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, fieldId: { classPropertyName: "fieldId", publicName: "fieldId", isSignal: true, isRequired: false, transformFunction: null }, valueEn: { classPropertyName: "valueEn", publicName: "valueEn", isSignal: true, isRequired: false, transformFunction: null }, valueAr: { classPropertyName: "valueAr", publicName: "valueAr", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueEn: "valueEnChange", valueAr: "valueArChange" }, ngImport: i0, template: "<div class=\"bilingual-field\">\r\n <div class=\"bilingual-field__row\">\r\n <!-- UAE DS 3.0 \u2014 explicit for/id association required -->\r\n <label [for]=\"fieldIdEn()\" class=\"bilingual-field__label\">{{ labelEnKey() | translate }}</label>\r\n @if (multiline()) {\r\n <textarea\r\n [id]=\"fieldIdEn()\"\r\n class=\"bilingual-field__input\"\r\n [placeholder]=\"placeholderEn()\"\r\n [value]=\"valueEn() ?? ''\"\r\n (input)=\"onEnInput($event)\"\r\n [rows]=\"rows()\"\r\n ></textarea>\r\n } @else {\r\n <input\r\n [id]=\"fieldIdEn()\"\r\n class=\"bilingual-field__input\"\r\n type=\"text\"\r\n [placeholder]=\"placeholderEn()\"\r\n [value]=\"valueEn() ?? ''\"\r\n (input)=\"onEnInput($event)\"\r\n />\r\n }\r\n </div>\r\n <div class=\"bilingual-field__row bilingual-field__row--rtl\">\r\n <label [for]=\"fieldIdAr()\" class=\"bilingual-field__label\">{{ labelArKey() | translate }}</label>\r\n @if (multiline()) {\r\n <textarea\r\n [id]=\"fieldIdAr()\"\r\n class=\"bilingual-field__input\"\r\n dir=\"rtl\"\r\n lang=\"ar\"\r\n [placeholder]=\"placeholderAr()\"\r\n [value]=\"valueAr() ?? ''\"\r\n (input)=\"onArInput($event)\"\r\n [rows]=\"rows()\"\r\n ></textarea>\r\n } @else {\r\n <input\r\n [id]=\"fieldIdAr()\"\r\n class=\"bilingual-field__input\"\r\n type=\"text\"\r\n dir=\"rtl\"\r\n lang=\"ar\"\r\n [placeholder]=\"placeholderAr()\"\r\n [value]=\"valueAr() ?? ''\"\r\n (input)=\"onArInput($event)\"\r\n />\r\n }\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.bilingual-field{display:flex;flex-direction:column;gap:8px}.bilingual-field__row{display:flex;flex-direction:column;gap:4px}.bilingual-field__label{font-size:14px;font-weight:500;color:var(--w6)}.bilingual-field__input{padding:0 11px;height:36px;box-sizing:border-box;border:1px solid var(--w14);border-radius:10px;width:100%;background:var(--w05);color:var(--w85);font-size:16px;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.bilingual-field__input:focus{outline:none;border-color:var(--accent);background:var(--w07)}.bilingual-field__input:focus-visible{outline:3px solid var(--accent);outline-offset:3px}textarea.bilingual-field__input{height:auto;padding-block:9px;resize:vertical}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25688
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: BilingualFieldComponent, isStandalone: true, selector: "fly-bilingual-field", inputs: { labelEnKey: { classPropertyName: "labelEnKey", publicName: "labelEnKey", isSignal: true, isRequired: false, transformFunction: null }, labelArKey: { classPropertyName: "labelArKey", publicName: "labelArKey", isSignal: true, isRequired: false, transformFunction: null }, placeholderEn: { classPropertyName: "placeholderEn", publicName: "placeholderEn", isSignal: true, isRequired: false, transformFunction: null }, placeholderAr: { classPropertyName: "placeholderAr", publicName: "placeholderAr", isSignal: true, isRequired: false, transformFunction: null }, multiline: { classPropertyName: "multiline", publicName: "multiline", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, fieldId: { classPropertyName: "fieldId", publicName: "fieldId", isSignal: true, isRequired: false, transformFunction: null }, valueEn: { classPropertyName: "valueEn", publicName: "valueEn", isSignal: true, isRequired: false, transformFunction: null }, valueAr: { classPropertyName: "valueAr", publicName: "valueAr", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueEn: "valueEnChange", valueAr: "valueArChange" }, ngImport: i0, template: "<div class=\"bilingual-field\">\r\n <div class=\"bilingual-field__row\">\r\n <!-- UAE DS 3.0 \u2014 explicit for/id association required -->\r\n <label [for]=\"fieldIdEn()\" class=\"bilingual-field__label\">{{ labelEnKey() | translate }}</label>\r\n @if (multiline()) {\r\n <textarea\r\n [id]=\"fieldIdEn()\"\r\n class=\"bilingual-field__input\"\r\n [placeholder]=\"placeholderEn()\"\r\n [value]=\"valueEn() ?? ''\"\r\n (input)=\"onEnInput($event)\"\r\n [rows]=\"rows()\"\r\n ></textarea>\r\n } @else {\r\n <input\r\n [id]=\"fieldIdEn()\"\r\n class=\"bilingual-field__input\"\r\n type=\"text\"\r\n [placeholder]=\"placeholderEn()\"\r\n [value]=\"valueEn() ?? ''\"\r\n (input)=\"onEnInput($event)\"\r\n />\r\n }\r\n </div>\r\n <div class=\"bilingual-field__row bilingual-field__row--rtl\">\r\n <label [for]=\"fieldIdAr()\" class=\"bilingual-field__label\">{{ labelArKey() | translate }}</label>\r\n @if (multiline()) {\r\n <textarea\r\n [id]=\"fieldIdAr()\"\r\n class=\"bilingual-field__input\"\r\n dir=\"rtl\"\r\n lang=\"ar\"\r\n [placeholder]=\"placeholderAr()\"\r\n [value]=\"valueAr() ?? ''\"\r\n (input)=\"onArInput($event)\"\r\n [rows]=\"rows()\"\r\n ></textarea>\r\n } @else {\r\n <input\r\n [id]=\"fieldIdAr()\"\r\n class=\"bilingual-field__input\"\r\n type=\"text\"\r\n dir=\"rtl\"\r\n lang=\"ar\"\r\n [placeholder]=\"placeholderAr()\"\r\n [value]=\"valueAr() ?? ''\"\r\n (input)=\"onArInput($event)\"\r\n />\r\n }\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.bilingual-field{display:flex;flex-direction:column;gap:8px}.bilingual-field__row{display:flex;flex-direction:column;gap:4px}.bilingual-field__label{font-size:14px;font-weight:500;color:var(--w6)}.bilingual-field__input{padding:0 11px;height:36px;box-sizing:border-box;border:1px solid var(--w14);border-radius:10px;width:100%;background:var(--w05);color:var(--w85);font-size:16px;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.bilingual-field__input:focus{outline:none;border-color:var(--accent);background:var(--w07)}.bilingual-field__input:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px}textarea.bilingual-field__input{height:auto;padding-block:9px;resize:vertical}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25645
25689
  }
25646
25690
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: BilingualFieldComponent, decorators: [{
25647
25691
  type: Component,
25648
- args: [{ selector: 'fly-bilingual-field', standalone: true, imports: [FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"bilingual-field\">\r\n <div class=\"bilingual-field__row\">\r\n <!-- UAE DS 3.0 \u2014 explicit for/id association required -->\r\n <label [for]=\"fieldIdEn()\" class=\"bilingual-field__label\">{{ labelEnKey() | translate }}</label>\r\n @if (multiline()) {\r\n <textarea\r\n [id]=\"fieldIdEn()\"\r\n class=\"bilingual-field__input\"\r\n [placeholder]=\"placeholderEn()\"\r\n [value]=\"valueEn() ?? ''\"\r\n (input)=\"onEnInput($event)\"\r\n [rows]=\"rows()\"\r\n ></textarea>\r\n } @else {\r\n <input\r\n [id]=\"fieldIdEn()\"\r\n class=\"bilingual-field__input\"\r\n type=\"text\"\r\n [placeholder]=\"placeholderEn()\"\r\n [value]=\"valueEn() ?? ''\"\r\n (input)=\"onEnInput($event)\"\r\n />\r\n }\r\n </div>\r\n <div class=\"bilingual-field__row bilingual-field__row--rtl\">\r\n <label [for]=\"fieldIdAr()\" class=\"bilingual-field__label\">{{ labelArKey() | translate }}</label>\r\n @if (multiline()) {\r\n <textarea\r\n [id]=\"fieldIdAr()\"\r\n class=\"bilingual-field__input\"\r\n dir=\"rtl\"\r\n lang=\"ar\"\r\n [placeholder]=\"placeholderAr()\"\r\n [value]=\"valueAr() ?? ''\"\r\n (input)=\"onArInput($event)\"\r\n [rows]=\"rows()\"\r\n ></textarea>\r\n } @else {\r\n <input\r\n [id]=\"fieldIdAr()\"\r\n class=\"bilingual-field__input\"\r\n type=\"text\"\r\n dir=\"rtl\"\r\n lang=\"ar\"\r\n [placeholder]=\"placeholderAr()\"\r\n [value]=\"valueAr() ?? ''\"\r\n (input)=\"onArInput($event)\"\r\n />\r\n }\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.bilingual-field{display:flex;flex-direction:column;gap:8px}.bilingual-field__row{display:flex;flex-direction:column;gap:4px}.bilingual-field__label{font-size:14px;font-weight:500;color:var(--w6)}.bilingual-field__input{padding:0 11px;height:36px;box-sizing:border-box;border:1px solid var(--w14);border-radius:10px;width:100%;background:var(--w05);color:var(--w85);font-size:16px;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.bilingual-field__input:focus{outline:none;border-color:var(--accent);background:var(--w07)}.bilingual-field__input:focus-visible{outline:3px solid var(--accent);outline-offset:3px}textarea.bilingual-field__input{height:auto;padding-block:9px;resize:vertical}\n"] }]
25692
+ args: [{ selector: 'fly-bilingual-field', standalone: true, imports: [FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"bilingual-field\">\r\n <div class=\"bilingual-field__row\">\r\n <!-- UAE DS 3.0 \u2014 explicit for/id association required -->\r\n <label [for]=\"fieldIdEn()\" class=\"bilingual-field__label\">{{ labelEnKey() | translate }}</label>\r\n @if (multiline()) {\r\n <textarea\r\n [id]=\"fieldIdEn()\"\r\n class=\"bilingual-field__input\"\r\n [placeholder]=\"placeholderEn()\"\r\n [value]=\"valueEn() ?? ''\"\r\n (input)=\"onEnInput($event)\"\r\n [rows]=\"rows()\"\r\n ></textarea>\r\n } @else {\r\n <input\r\n [id]=\"fieldIdEn()\"\r\n class=\"bilingual-field__input\"\r\n type=\"text\"\r\n [placeholder]=\"placeholderEn()\"\r\n [value]=\"valueEn() ?? ''\"\r\n (input)=\"onEnInput($event)\"\r\n />\r\n }\r\n </div>\r\n <div class=\"bilingual-field__row bilingual-field__row--rtl\">\r\n <label [for]=\"fieldIdAr()\" class=\"bilingual-field__label\">{{ labelArKey() | translate }}</label>\r\n @if (multiline()) {\r\n <textarea\r\n [id]=\"fieldIdAr()\"\r\n class=\"bilingual-field__input\"\r\n dir=\"rtl\"\r\n lang=\"ar\"\r\n [placeholder]=\"placeholderAr()\"\r\n [value]=\"valueAr() ?? ''\"\r\n (input)=\"onArInput($event)\"\r\n [rows]=\"rows()\"\r\n ></textarea>\r\n } @else {\r\n <input\r\n [id]=\"fieldIdAr()\"\r\n class=\"bilingual-field__input\"\r\n type=\"text\"\r\n dir=\"rtl\"\r\n lang=\"ar\"\r\n [placeholder]=\"placeholderAr()\"\r\n [value]=\"valueAr() ?? ''\"\r\n (input)=\"onArInput($event)\"\r\n />\r\n }\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.bilingual-field{display:flex;flex-direction:column;gap:8px}.bilingual-field__row{display:flex;flex-direction:column;gap:4px}.bilingual-field__label{font-size:14px;font-weight:500;color:var(--w6)}.bilingual-field__input{padding:0 11px;height:36px;box-sizing:border-box;border:1px solid var(--w14);border-radius:10px;width:100%;background:var(--w05);color:var(--w85);font-size:16px;transition:border-color var(--nova-duration-hover) var(--nova-ease-micro),background var(--nova-duration-hover) var(--nova-ease-micro)}.bilingual-field__input:focus{outline:none;border-color:var(--accent);background:var(--w07)}.bilingual-field__input:focus-visible{outline:3px solid;outline-color:var(--accent);outline-offset:3px}textarea.bilingual-field__input{height:auto;padding-block:9px;resize:vertical}\n"] }]
25649
25693
  }], propDecorators: { labelEnKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelEnKey", required: false }] }], labelArKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelArKey", required: false }] }], placeholderEn: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholderEn", required: false }] }], placeholderAr: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholderAr", required: false }] }], multiline: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiline", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], fieldId: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldId", required: false }] }], valueEn: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueEn", required: false }] }, { type: i0.Output, args: ["valueEnChange"] }], valueAr: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueAr", required: false }] }, { type: i0.Output, args: ["valueArChange"] }] } });
25650
25694
 
25651
25695
  /**
@@ -25732,7 +25776,7 @@ class FlyModalComponent {
25732
25776
  <ng-content select="[modal-footer]" />
25733
25777
  </div>
25734
25778
  </div>
25735
- `, isInline: true, styles: ["@charset \"UTF-8\";.mo{position:fixed;inset:0;z-index:var(--z-dialog);place-items:center;padding:var(--sp-5);pointer-events:none;display:none}.mo--open{display:grid;pointer-events:auto}.mo__scrim{position:absolute;inset:0;background:transparent;-webkit-backdrop-filter:blur(0);backdrop-filter:blur(0);transition:background var(--t-overlay),backdrop-filter var(--t-overlay)}.mo--open .mo__scrim{background:var(--scrim);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.mo__panel{position:relative;width:100%;max-height:90vh;display:flex;flex-direction:column;border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.mo__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.mo__panel:before,.mo__panel:after{display:none}}@media(prefers-contrast:more){.mo__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.mo__panel:after{animation:none}}.mo__panel{opacity:0;transform:translateY(8px) scale(.985);visibility:hidden;transition:opacity var(--t-overlay),transform var(--t-overlay),visibility 0s var(--t-overlay)}.mo--open .mo__panel{opacity:1;transform:none;visibility:visible;transition:opacity var(--t-overlay),transform var(--t-overlay),visibility 0s}.mo__panel[data-size=sm]{max-width:400px}.mo__panel[data-size=md]{max-width:640px}.mo__panel[data-size=lg]{max-width:920px}.mo__hd{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:16px 20px;border-block-end:1px solid var(--w08);flex-shrink:0}.mo__t{margin:0;font-size:var(--text-xl);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-tight);color:var(--ink);min-width:0}.mo__close{width:32px;height:32px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-md);font-size:22px;line-height:1;display:grid;place-items:center;flex-shrink:0;margin-inline-start:auto;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.mo__close:hover{color:var(--ink);background:var(--bg-hover)}.mo__close:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.mo__body{flex:1 1 auto;overflow:hidden auto;padding:16px 20px;scrollbar-width:thin}.mo__panel ::ng-deep [modal-footer]{display:flex;align-items:center;justify-content:flex-end;gap:var(--sp-2);flex-wrap:wrap;padding:12px 20px;border-block-start:1px solid var(--w08);flex-shrink:0}@media(width<=720px){.mo{padding:var(--sp-4)}.mo__hd,.mo__body{padding-inline:var(--sp-4)}}\n"], dependencies: [{ kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25779
+ `, isInline: true, styles: ["@charset \"UTF-8\";.mo{position:fixed;inset:0;z-index:var(--z-dialog);place-items:center;padding:var(--sp-5);pointer-events:none;display:none}.mo--open{display:grid;pointer-events:auto}.mo__scrim{position:absolute;inset:0;background:transparent;-webkit-backdrop-filter:blur(0);backdrop-filter:blur(0);transition:background var(--t-overlay),backdrop-filter var(--t-overlay)}.mo--open .mo__scrim{background:var(--scrim);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.mo__panel{position:relative;width:100%;max-height:90vh;display:flex;flex-direction:column;border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.mo__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.mo__panel:before,.mo__panel:after{display:none}}@media(prefers-contrast:more){.mo__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.mo__panel:after{animation:none}}.mo__panel{opacity:0;transform:translateY(8px) scale(.985);visibility:hidden;transition:opacity var(--t-overlay),transform var(--t-overlay),visibility 0s var(--t-overlay)}.mo--open .mo__panel{opacity:1;transform:none;visibility:visible;transition:opacity var(--t-overlay),transform var(--t-overlay),visibility 0s}.mo__panel[data-size=sm]{max-width:400px}.mo__panel[data-size=md]{max-width:640px}.mo__panel[data-size=lg]{max-width:920px}.mo__hd{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:16px 20px;border-block-end:1px solid var(--w08);flex-shrink:0}.mo__t{margin:0;font-size:var(--text-xl);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-tight);color:var(--ink);min-width:0}.mo__close{width:32px;height:32px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-md);font-size:22px;line-height:1;display:grid;place-items:center;flex-shrink:0;margin-inline-start:auto;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.mo__close:hover{color:var(--ink);background:var(--bg-hover)}.mo__close:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.mo__body{flex:1 1 auto;overflow:hidden auto;padding:16px 20px;scrollbar-width:thin}.mo__panel ::ng-deep [modal-footer]{display:flex;align-items:center;justify-content:flex-end;gap:var(--sp-2);flex-wrap:wrap;padding:12px 20px;border-block-start:1px solid var(--w08);flex-shrink:0}@media(width<=720px){.mo{padding:var(--sp-4)}.mo__hd,.mo__body{padding-inline:var(--sp-4)}}\n"], dependencies: [{ kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25736
25780
  }
25737
25781
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyModalComponent, decorators: [{
25738
25782
  type: Component,
@@ -25764,7 +25808,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
25764
25808
  <ng-content select="[modal-footer]" />
25765
25809
  </div>
25766
25810
  </div>
25767
- `, styles: ["@charset \"UTF-8\";.mo{position:fixed;inset:0;z-index:var(--z-dialog);place-items:center;padding:var(--sp-5);pointer-events:none;display:none}.mo--open{display:grid;pointer-events:auto}.mo__scrim{position:absolute;inset:0;background:transparent;-webkit-backdrop-filter:blur(0);backdrop-filter:blur(0);transition:background var(--t-overlay),backdrop-filter var(--t-overlay)}.mo--open .mo__scrim{background:var(--scrim);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.mo__panel{position:relative;width:100%;max-height:90vh;display:flex;flex-direction:column;border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.mo__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.mo__panel:before,.mo__panel:after{display:none}}@media(prefers-contrast:more){.mo__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.mo__panel:after{animation:none}}.mo__panel{opacity:0;transform:translateY(8px) scale(.985);visibility:hidden;transition:opacity var(--t-overlay),transform var(--t-overlay),visibility 0s var(--t-overlay)}.mo--open .mo__panel{opacity:1;transform:none;visibility:visible;transition:opacity var(--t-overlay),transform var(--t-overlay),visibility 0s}.mo__panel[data-size=sm]{max-width:400px}.mo__panel[data-size=md]{max-width:640px}.mo__panel[data-size=lg]{max-width:920px}.mo__hd{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:16px 20px;border-block-end:1px solid var(--w08);flex-shrink:0}.mo__t{margin:0;font-size:var(--text-xl);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-tight);color:var(--ink);min-width:0}.mo__close{width:32px;height:32px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-md);font-size:22px;line-height:1;display:grid;place-items:center;flex-shrink:0;margin-inline-start:auto;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.mo__close:hover{color:var(--ink);background:var(--bg-hover)}.mo__close:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.mo__body{flex:1 1 auto;overflow:hidden auto;padding:16px 20px;scrollbar-width:thin}.mo__panel ::ng-deep [modal-footer]{display:flex;align-items:center;justify-content:flex-end;gap:var(--sp-2);flex-wrap:wrap;padding:12px 20px;border-block-start:1px solid var(--w08);flex-shrink:0}@media(width<=720px){.mo{padding:var(--sp-4)}.mo__hd,.mo__body{padding-inline:var(--sp-4)}}\n"] }]
25811
+ `, styles: ["@charset \"UTF-8\";.mo{position:fixed;inset:0;z-index:var(--z-dialog);place-items:center;padding:var(--sp-5);pointer-events:none;display:none}.mo--open{display:grid;pointer-events:auto}.mo__scrim{position:absolute;inset:0;background:transparent;-webkit-backdrop-filter:blur(0);backdrop-filter:blur(0);transition:background var(--t-overlay),backdrop-filter var(--t-overlay)}.mo--open .mo__scrim{background:var(--scrim);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.mo__panel{position:relative;width:100%;max-height:90vh;display:flex;flex-direction:column;border-radius:var(--r-lg);border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.mo__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.mo__panel:before,.mo__panel:after{display:none}}@media(prefers-contrast:more){.mo__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.mo__panel:after{animation:none}}.mo__panel{opacity:0;transform:translateY(8px) scale(.985);visibility:hidden;transition:opacity var(--t-overlay),transform var(--t-overlay),visibility 0s var(--t-overlay)}.mo--open .mo__panel{opacity:1;transform:none;visibility:visible;transition:opacity var(--t-overlay),transform var(--t-overlay),visibility 0s}.mo__panel[data-size=sm]{max-width:400px}.mo__panel[data-size=md]{max-width:640px}.mo__panel[data-size=lg]{max-width:920px}.mo__hd{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);padding:16px 20px;border-block-end:1px solid var(--w08);flex-shrink:0}.mo__t{margin:0;font-size:var(--text-xl);font-weight:var(--fw-semibold);letter-spacing:var(--tracking-tight);color:var(--ink);min-width:0}.mo__close{width:32px;height:32px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-md);font-size:22px;line-height:1;display:grid;place-items:center;flex-shrink:0;margin-inline-start:auto;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.mo__close:hover{color:var(--ink);background:var(--bg-hover)}.mo__close:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.mo__body{flex:1 1 auto;overflow:hidden auto;padding:16px 20px;scrollbar-width:thin}.mo__panel ::ng-deep [modal-footer]{display:flex;align-items:center;justify-content:flex-end;gap:var(--sp-2);flex-wrap:wrap;padding:12px 20px;border-block-start:1px solid var(--w08);flex-shrink:0}@media(width<=720px){.mo{padding:var(--sp-4)}.mo__hd,.mo__body{padding-inline:var(--sp-4)}}\n"] }]
25768
25812
  }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: true }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
25769
25813
 
25770
25814
  /**
@@ -25902,7 +25946,7 @@ class FlyConfirmDialogComponent {
25902
25946
  this.confirmed.emit();
25903
25947
  }
25904
25948
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyConfirmDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
25905
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyConfirmDialogComponent, isStandalone: true, selector: "fly-confirm-dialog", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: true, transformFunction: null }, kind: { classPropertyName: "kind", publicName: "kind", isSignal: true, isRequired: false, transformFunction: null }, titleKey: { classPropertyName: "titleKey", publicName: "titleKey", isSignal: true, isRequired: true, transformFunction: null }, messageKey: { classPropertyName: "messageKey", publicName: "messageKey", isSignal: true, isRequired: false, transformFunction: null }, confirmLabelKey: { classPropertyName: "confirmLabelKey", publicName: "confirmLabelKey", isSignal: true, isRequired: false, transformFunction: null }, cancelLabelKey: { classPropertyName: "cancelLabelKey", publicName: "cancelLabelKey", isSignal: true, isRequired: false, transformFunction: null }, requireText: { classPropertyName: "requireText", publicName: "requireText", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed", cancelled: "cancelled" }, host: { listeners: { "document:keydown.escape": "onEscape()", "document:keydown.enter": "onEnter()" }, properties: { "class.fly-confirm-dialog--mobile": "isMobile()" } }, ngImport: i0, template: "@if (open()) {\r\n <div class=\"cf\" role=\"presentation\">\r\n <div class=\"cf__scrim\" role=\"presentation\" (click)=\"cancel()\"></div>\r\n <div\r\n class=\"cf__panel\"\r\n [attr.data-kind]=\"kind()\"\r\n role=\"alertdialog\"\r\n aria-modal=\"true\"\r\n cdkTrapFocus\r\n cdkTrapFocusAutoCapture\r\n [attr.aria-label]=\"titleKey() | translate\"\r\n >\r\n <div class=\"cf__head\">\r\n <div class=\"cf__icon\" [attr.data-kind]=\"kind()\" aria-hidden=\"true\">\r\n @switch (kind()) {\r\n @case ('danger') {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\r\n <path d=\"M12 8v5M12 16h.01\"/>\r\n </svg>\r\n }\r\n @case ('warn') {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M12 9v4M12 17h.01\"/>\r\n <path d=\"M10.3 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z\"/>\r\n </svg>\r\n }\r\n @default {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\r\n <path d=\"M12 8v.01M12 11v5\"/>\r\n </svg>\r\n }\r\n }\r\n </div>\r\n <h3 class=\"cf__title\">{{ titleKey() | translate }}</h3>\r\n <button\r\n type=\"button\"\r\n class=\"cf__close\"\r\n (click)=\"cancel()\"\r\n [attr.aria-label]=\"'ui.action.close' | translate\"\r\n >\u00D7</button>\r\n </div>\r\n\r\n <div class=\"cf__body\">\r\n @if (messageKey(); as key) {\r\n <p class=\"cf__msg\">{{ key | translate }}</p>\r\n }\r\n <ng-content />\r\n\r\n @if (requireText(); as text) {\r\n <label class=\"cf__gate\">\r\n <span class=\"cf__gate-l\">{{ 'ui.confirm.typeToConfirm' | translate: { text: text } }}</span>\r\n <input\r\n class=\"cf__gate-i mono\"\r\n [value]=\"typed()\"\r\n (input)=\"typed.set($any($event.target).value)\"\r\n [placeholder]=\"text\"\r\n autocomplete=\"off\"\r\n />\r\n </label>\r\n }\r\n </div>\r\n\r\n <div class=\"cf__ft\">\r\n <button type=\"button\" fly-button (click)=\"cancel()\">\r\n {{ cancelLabelKey() | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n fly-button\r\n [variant]=\"kind() === 'danger' ? 'danger-fill' : 'primary'\"\r\n [loading]=\"busy()\"\r\n [disabled]=\"!allowConfirm()\"\r\n (click)=\"confirm()\"\r\n >\r\n {{ confirmLabelKey() | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@charset \"UTF-8\";.cf{position:fixed;inset:0;z-index:var(--z-dialog);display:grid;place-items:center;padding:var(--sp-5)}.cf__scrim{position:absolute;inset:0;background:var(--scrim);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);animation:cf-scrim-in var(--t-overlay)}@keyframes cf-scrim-in{0%{background:transparent;-webkit-backdrop-filter:blur(0);backdrop-filter:blur(0)}}.cf__panel{position:relative;width:min(480px,100%);border-radius:var(--r-lg);display:flex;flex-direction:column;border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.cf__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.cf__panel:before,.cf__panel:after{display:none}}@media(prefers-contrast:more){.cf__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.cf__panel:after{animation:none}}.cf__panel{animation:menuIn .24s var(--nova-ease-structural) both}.cf__panel[data-kind=danger]{border-color:var(--danger-line)}.cf__panel[data-kind=warn]{border-color:var(--warning)}.cf__head{display:flex;align-items:flex-start;gap:14px;padding:20px 20px 14px}.cf__icon{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;flex-shrink:0;background:var(--w05);color:var(--ink-2);border:1px solid var(--w12)}.cf__icon[data-kind=warn]{background:var(--warning-bg);color:var(--warning-fg);border-color:var(--warning)}.cf__icon[data-kind=danger]{background:var(--danger-bg);color:var(--danger);border-color:var(--danger-line)}.cf__title{flex:1;min-width:0;font-size:var(--text-lg);font-weight:var(--fw-semibold);letter-spacing:-.005em;margin:0;padding-block-start:6px;color:var(--ink);line-height:1.35}.cf__close{width:28px;height:28px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:20px;line-height:1;display:grid;place-items:center;flex-shrink:0;margin-block-start:-4px;margin-inline-end:-4px;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.cf__close:hover{color:var(--ink);background:var(--w08)}.cf__close:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.cf__body{padding:0 20px 18px;display:flex;flex-direction:column;gap:14px}.cf__msg{font-size:var(--text-md);line-height:1.55;color:var(--ink-2);margin:0}.cf__gate{display:flex;flex-direction:column;gap:6px;padding-block-start:var(--sp-1)}.cf__gate-l{font-size:var(--text-2xs);color:var(--ink-2)}.cf__gate-i{width:100%;box-sizing:border-box;padding:var(--sp-2) var(--sp-3);background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r-md);color:var(--ink);font-family:inherit;font-size:var(--text-base);transition:border-color var(--t-state),background var(--t-state)}.cf__gate-i::placeholder{color:var(--ink-4)}.cf__gate-i:hover{border-color:var(--line-2)}.cf__gate-i:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-1px;border-color:transparent}.cf__gate-i:disabled{opacity:.5;cursor:not-allowed;background:var(--bg-3)}.cf__gate-i{height:32px;padding-block:0;font-size:var(--text-sm)}.cf__gate-i.mono{font-family:var(--font-mono)}.cf__ft{display:flex;justify-content:flex-end;gap:var(--sp-2);padding:12px 16px;border-block-start:1px solid var(--w08);background:var(--w03);border-end-start-radius:var(--r-lg);border-end-end-radius:var(--r-lg)}@media(width<=480px){.cf__head{padding:16px 16px 12px}.cf__body{padding:0 16px 14px}.cf__ft{padding:10px 12px;flex-wrap:wrap}.cf__ft [fly-button]{flex:1 1 auto;justify-content:center}}:host(.fly-confirm-dialog--mobile) .cf{padding:16px}:host(.fly-confirm-dialog--mobile) .cf__panel{inline-size:100%;border-radius:18px}:host(.fly-confirm-dialog--mobile) .cf__ft{flex-wrap:nowrap;border-end-start-radius:18px;border-end-end-radius:18px}:host(.fly-confirm-dialog--mobile) .cf__ft [fly-button]{flex:1 1 0;min-inline-size:0;min-block-size:44px}\n"], dependencies: [{ kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: FlyButtonComponent, selector: "button[fly-button], a[fly-button]", inputs: ["variant", "size", "loading"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25949
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FlyConfirmDialogComponent, isStandalone: true, selector: "fly-confirm-dialog", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: true, transformFunction: null }, kind: { classPropertyName: "kind", publicName: "kind", isSignal: true, isRequired: false, transformFunction: null }, titleKey: { classPropertyName: "titleKey", publicName: "titleKey", isSignal: true, isRequired: true, transformFunction: null }, messageKey: { classPropertyName: "messageKey", publicName: "messageKey", isSignal: true, isRequired: false, transformFunction: null }, confirmLabelKey: { classPropertyName: "confirmLabelKey", publicName: "confirmLabelKey", isSignal: true, isRequired: false, transformFunction: null }, cancelLabelKey: { classPropertyName: "cancelLabelKey", publicName: "cancelLabelKey", isSignal: true, isRequired: false, transformFunction: null }, requireText: { classPropertyName: "requireText", publicName: "requireText", isSignal: true, isRequired: false, transformFunction: null }, busy: { classPropertyName: "busy", publicName: "busy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed", cancelled: "cancelled" }, host: { listeners: { "document:keydown.escape": "onEscape()", "document:keydown.enter": "onEnter()" }, properties: { "class.fly-confirm-dialog--mobile": "isMobile()" } }, ngImport: i0, template: "@if (open()) {\r\n <div class=\"cf\" role=\"presentation\">\r\n <div class=\"cf__scrim\" role=\"presentation\" (click)=\"cancel()\"></div>\r\n <div\r\n class=\"cf__panel\"\r\n [attr.data-kind]=\"kind()\"\r\n role=\"alertdialog\"\r\n aria-modal=\"true\"\r\n cdkTrapFocus\r\n cdkTrapFocusAutoCapture\r\n [attr.aria-label]=\"titleKey() | translate\"\r\n >\r\n <div class=\"cf__head\">\r\n <div class=\"cf__icon\" [attr.data-kind]=\"kind()\" aria-hidden=\"true\">\r\n @switch (kind()) {\r\n @case ('danger') {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\r\n <path d=\"M12 8v5M12 16h.01\"/>\r\n </svg>\r\n }\r\n @case ('warn') {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M12 9v4M12 17h.01\"/>\r\n <path d=\"M10.3 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z\"/>\r\n </svg>\r\n }\r\n @default {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\r\n <path d=\"M12 8v.01M12 11v5\"/>\r\n </svg>\r\n }\r\n }\r\n </div>\r\n <h3 class=\"cf__title\">{{ titleKey() | translate }}</h3>\r\n <button\r\n type=\"button\"\r\n class=\"cf__close\"\r\n (click)=\"cancel()\"\r\n [attr.aria-label]=\"'ui.action.close' | translate\"\r\n >\u00D7</button>\r\n </div>\r\n\r\n <div class=\"cf__body\">\r\n @if (messageKey(); as key) {\r\n <p class=\"cf__msg\">{{ key | translate }}</p>\r\n }\r\n <ng-content />\r\n\r\n @if (requireText(); as text) {\r\n <label class=\"cf__gate\">\r\n <span class=\"cf__gate-l\">{{ 'ui.confirm.typeToConfirm' | translate: { text: text } }}</span>\r\n <input\r\n class=\"cf__gate-i mono\"\r\n [value]=\"typed()\"\r\n (input)=\"typed.set($any($event.target).value)\"\r\n [placeholder]=\"text\"\r\n autocomplete=\"off\"\r\n />\r\n </label>\r\n }\r\n </div>\r\n\r\n <div class=\"cf__ft\">\r\n <button type=\"button\" fly-button (click)=\"cancel()\">\r\n {{ cancelLabelKey() | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n fly-button\r\n [variant]=\"kind() === 'danger' ? 'danger-fill' : 'primary'\"\r\n [loading]=\"busy()\"\r\n [disabled]=\"!allowConfirm()\"\r\n (click)=\"confirm()\"\r\n >\r\n {{ confirmLabelKey() | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@charset \"UTF-8\";.cf{position:fixed;inset:0;z-index:var(--z-dialog);display:grid;place-items:center;padding:var(--sp-5)}.cf__scrim{position:absolute;inset:0;background:var(--scrim);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);animation:cf-scrim-in var(--t-overlay)}@keyframes cf-scrim-in{0%{background:transparent;-webkit-backdrop-filter:blur(0);backdrop-filter:blur(0)}}.cf__panel{position:relative;width:min(480px,100%);border-radius:var(--r-lg);display:flex;flex-direction:column;border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.cf__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.cf__panel:before,.cf__panel:after{display:none}}@media(prefers-contrast:more){.cf__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.cf__panel:after{animation:none}}.cf__panel{animation:menuIn .24s var(--nova-ease-structural) both}.cf__panel[data-kind=danger]{border-color:var(--danger-line)}.cf__panel[data-kind=warn]{border-color:var(--warning)}.cf__head{display:flex;align-items:flex-start;gap:14px;padding:20px 20px 14px}.cf__icon{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;flex-shrink:0;background:var(--w05);color:var(--ink-2);border:1px solid var(--w12)}.cf__icon[data-kind=warn]{background:var(--warning-bg);color:var(--warning-fg);border-color:var(--warning)}.cf__icon[data-kind=danger]{background:var(--danger-bg);color:var(--danger);border-color:var(--danger-line)}.cf__title{flex:1;min-width:0;font-size:var(--text-lg);font-weight:var(--fw-semibold);letter-spacing:-.005em;margin:0;padding-block-start:6px;color:var(--ink);line-height:1.35}.cf__close{width:28px;height:28px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:20px;line-height:1;display:grid;place-items:center;flex-shrink:0;margin-block-start:-4px;margin-inline-end:-4px;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.cf__close:hover{color:var(--ink);background:var(--w08)}.cf__close:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.cf__body{padding:0 20px 18px;display:flex;flex-direction:column;gap:14px}.cf__msg{font-size:var(--text-md);line-height:1.55;color:var(--ink-2);margin:0}.cf__gate{display:flex;flex-direction:column;gap:6px;padding-block-start:var(--sp-1)}.cf__gate-l{font-size:var(--text-2xs);color:var(--ink-2)}.cf__gate-i{width:100%;box-sizing:border-box;padding:var(--sp-2) var(--sp-3);background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r-md);color:var(--ink);font-family:inherit;font-size:var(--text-base);transition:border-color var(--t-state),background var(--t-state)}.cf__gate-i::placeholder{color:var(--ink-4)}.cf__gate-i:hover{border-color:var(--line-2)}.cf__gate-i:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:-1px;border-color:transparent}.cf__gate-i:disabled{opacity:.5;cursor:not-allowed;background:var(--bg-3)}.cf__gate-i{height:32px;padding-block:0;font-size:var(--text-sm)}.cf__gate-i.mono{font-family:var(--font-mono)}.cf__ft{display:flex;justify-content:flex-end;gap:var(--sp-2);padding:12px 16px;border-block-start:1px solid var(--w08);background:var(--w03);border-end-start-radius:var(--r-lg);border-end-end-radius:var(--r-lg)}@media(width<=480px){.cf__head{padding:16px 16px 12px}.cf__body{padding:0 16px 14px}.cf__ft{padding:10px 12px;flex-wrap:wrap}.cf__ft [fly-button]{flex:1 1 auto;justify-content:center}}:host(.fly-confirm-dialog--mobile) .cf{padding:16px}:host(.fly-confirm-dialog--mobile) .cf__panel{inline-size:100%;border-radius:18px}:host(.fly-confirm-dialog--mobile) .cf__ft{flex-wrap:nowrap;border-end-start-radius:18px;border-end-end-radius:18px}:host(.fly-confirm-dialog--mobile) .cf__ft [fly-button]{flex:1 1 0;min-inline-size:0;min-block-size:44px}\n"], dependencies: [{ kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: FlyButtonComponent, selector: "button[fly-button], a[fly-button]", inputs: ["variant", "size", "loading"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25906
25950
  }
25907
25951
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyConfirmDialogComponent, decorators: [{
25908
25952
  type: Component,
@@ -25913,7 +25957,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
25913
25957
  // geometry, as `fly-message-box` — the two confirm surfaces of the platform
25914
25958
  // must not diverge on a phone just because one of them has no consumers yet.
25915
25959
  '[class.fly-confirm-dialog--mobile]': 'isMobile()',
25916
- }, template: "@if (open()) {\r\n <div class=\"cf\" role=\"presentation\">\r\n <div class=\"cf__scrim\" role=\"presentation\" (click)=\"cancel()\"></div>\r\n <div\r\n class=\"cf__panel\"\r\n [attr.data-kind]=\"kind()\"\r\n role=\"alertdialog\"\r\n aria-modal=\"true\"\r\n cdkTrapFocus\r\n cdkTrapFocusAutoCapture\r\n [attr.aria-label]=\"titleKey() | translate\"\r\n >\r\n <div class=\"cf__head\">\r\n <div class=\"cf__icon\" [attr.data-kind]=\"kind()\" aria-hidden=\"true\">\r\n @switch (kind()) {\r\n @case ('danger') {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\r\n <path d=\"M12 8v5M12 16h.01\"/>\r\n </svg>\r\n }\r\n @case ('warn') {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M12 9v4M12 17h.01\"/>\r\n <path d=\"M10.3 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z\"/>\r\n </svg>\r\n }\r\n @default {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\r\n <path d=\"M12 8v.01M12 11v5\"/>\r\n </svg>\r\n }\r\n }\r\n </div>\r\n <h3 class=\"cf__title\">{{ titleKey() | translate }}</h3>\r\n <button\r\n type=\"button\"\r\n class=\"cf__close\"\r\n (click)=\"cancel()\"\r\n [attr.aria-label]=\"'ui.action.close' | translate\"\r\n >\u00D7</button>\r\n </div>\r\n\r\n <div class=\"cf__body\">\r\n @if (messageKey(); as key) {\r\n <p class=\"cf__msg\">{{ key | translate }}</p>\r\n }\r\n <ng-content />\r\n\r\n @if (requireText(); as text) {\r\n <label class=\"cf__gate\">\r\n <span class=\"cf__gate-l\">{{ 'ui.confirm.typeToConfirm' | translate: { text: text } }}</span>\r\n <input\r\n class=\"cf__gate-i mono\"\r\n [value]=\"typed()\"\r\n (input)=\"typed.set($any($event.target).value)\"\r\n [placeholder]=\"text\"\r\n autocomplete=\"off\"\r\n />\r\n </label>\r\n }\r\n </div>\r\n\r\n <div class=\"cf__ft\">\r\n <button type=\"button\" fly-button (click)=\"cancel()\">\r\n {{ cancelLabelKey() | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n fly-button\r\n [variant]=\"kind() === 'danger' ? 'danger-fill' : 'primary'\"\r\n [loading]=\"busy()\"\r\n [disabled]=\"!allowConfirm()\"\r\n (click)=\"confirm()\"\r\n >\r\n {{ confirmLabelKey() | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@charset \"UTF-8\";.cf{position:fixed;inset:0;z-index:var(--z-dialog);display:grid;place-items:center;padding:var(--sp-5)}.cf__scrim{position:absolute;inset:0;background:var(--scrim);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);animation:cf-scrim-in var(--t-overlay)}@keyframes cf-scrim-in{0%{background:transparent;-webkit-backdrop-filter:blur(0);backdrop-filter:blur(0)}}.cf__panel{position:relative;width:min(480px,100%);border-radius:var(--r-lg);display:flex;flex-direction:column;border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.cf__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.cf__panel:before,.cf__panel:after{display:none}}@media(prefers-contrast:more){.cf__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.cf__panel:after{animation:none}}.cf__panel{animation:menuIn .24s var(--nova-ease-structural) both}.cf__panel[data-kind=danger]{border-color:var(--danger-line)}.cf__panel[data-kind=warn]{border-color:var(--warning)}.cf__head{display:flex;align-items:flex-start;gap:14px;padding:20px 20px 14px}.cf__icon{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;flex-shrink:0;background:var(--w05);color:var(--ink-2);border:1px solid var(--w12)}.cf__icon[data-kind=warn]{background:var(--warning-bg);color:var(--warning-fg);border-color:var(--warning)}.cf__icon[data-kind=danger]{background:var(--danger-bg);color:var(--danger);border-color:var(--danger-line)}.cf__title{flex:1;min-width:0;font-size:var(--text-lg);font-weight:var(--fw-semibold);letter-spacing:-.005em;margin:0;padding-block-start:6px;color:var(--ink);line-height:1.35}.cf__close{width:28px;height:28px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:20px;line-height:1;display:grid;place-items:center;flex-shrink:0;margin-block-start:-4px;margin-inline-end:-4px;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.cf__close:hover{color:var(--ink);background:var(--w08)}.cf__close:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}.cf__body{padding:0 20px 18px;display:flex;flex-direction:column;gap:14px}.cf__msg{font-size:var(--text-md);line-height:1.55;color:var(--ink-2);margin:0}.cf__gate{display:flex;flex-direction:column;gap:6px;padding-block-start:var(--sp-1)}.cf__gate-l{font-size:var(--text-2xs);color:var(--ink-2)}.cf__gate-i{width:100%;box-sizing:border-box;padding:var(--sp-2) var(--sp-3);background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r-md);color:var(--ink);font-family:inherit;font-size:var(--text-base);transition:border-color var(--t-state),background var(--t-state)}.cf__gate-i::placeholder{color:var(--ink-4)}.cf__gate-i:hover{border-color:var(--line-2)}.cf__gate-i:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-1px;border-color:transparent}.cf__gate-i:disabled{opacity:.5;cursor:not-allowed;background:var(--bg-3)}.cf__gate-i{height:32px;padding-block:0;font-size:var(--text-sm)}.cf__gate-i.mono{font-family:var(--font-mono)}.cf__ft{display:flex;justify-content:flex-end;gap:var(--sp-2);padding:12px 16px;border-block-start:1px solid var(--w08);background:var(--w03);border-end-start-radius:var(--r-lg);border-end-end-radius:var(--r-lg)}@media(width<=480px){.cf__head{padding:16px 16px 12px}.cf__body{padding:0 16px 14px}.cf__ft{padding:10px 12px;flex-wrap:wrap}.cf__ft [fly-button]{flex:1 1 auto;justify-content:center}}:host(.fly-confirm-dialog--mobile) .cf{padding:16px}:host(.fly-confirm-dialog--mobile) .cf__panel{inline-size:100%;border-radius:18px}:host(.fly-confirm-dialog--mobile) .cf__ft{flex-wrap:nowrap;border-end-start-radius:18px;border-end-end-radius:18px}:host(.fly-confirm-dialog--mobile) .cf__ft [fly-button]{flex:1 1 0;min-inline-size:0;min-block-size:44px}\n"] }]
25960
+ }, template: "@if (open()) {\r\n <div class=\"cf\" role=\"presentation\">\r\n <div class=\"cf__scrim\" role=\"presentation\" (click)=\"cancel()\"></div>\r\n <div\r\n class=\"cf__panel\"\r\n [attr.data-kind]=\"kind()\"\r\n role=\"alertdialog\"\r\n aria-modal=\"true\"\r\n cdkTrapFocus\r\n cdkTrapFocusAutoCapture\r\n [attr.aria-label]=\"titleKey() | translate\"\r\n >\r\n <div class=\"cf__head\">\r\n <div class=\"cf__icon\" [attr.data-kind]=\"kind()\" aria-hidden=\"true\">\r\n @switch (kind()) {\r\n @case ('danger') {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\r\n <path d=\"M12 8v5M12 16h.01\"/>\r\n </svg>\r\n }\r\n @case ('warn') {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M12 9v4M12 17h.01\"/>\r\n <path d=\"M10.3 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z\"/>\r\n </svg>\r\n }\r\n @default {\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\r\n <path d=\"M12 8v.01M12 11v5\"/>\r\n </svg>\r\n }\r\n }\r\n </div>\r\n <h3 class=\"cf__title\">{{ titleKey() | translate }}</h3>\r\n <button\r\n type=\"button\"\r\n class=\"cf__close\"\r\n (click)=\"cancel()\"\r\n [attr.aria-label]=\"'ui.action.close' | translate\"\r\n >\u00D7</button>\r\n </div>\r\n\r\n <div class=\"cf__body\">\r\n @if (messageKey(); as key) {\r\n <p class=\"cf__msg\">{{ key | translate }}</p>\r\n }\r\n <ng-content />\r\n\r\n @if (requireText(); as text) {\r\n <label class=\"cf__gate\">\r\n <span class=\"cf__gate-l\">{{ 'ui.confirm.typeToConfirm' | translate: { text: text } }}</span>\r\n <input\r\n class=\"cf__gate-i mono\"\r\n [value]=\"typed()\"\r\n (input)=\"typed.set($any($event.target).value)\"\r\n [placeholder]=\"text\"\r\n autocomplete=\"off\"\r\n />\r\n </label>\r\n }\r\n </div>\r\n\r\n <div class=\"cf__ft\">\r\n <button type=\"button\" fly-button (click)=\"cancel()\">\r\n {{ cancelLabelKey() | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n fly-button\r\n [variant]=\"kind() === 'danger' ? 'danger-fill' : 'primary'\"\r\n [loading]=\"busy()\"\r\n [disabled]=\"!allowConfirm()\"\r\n (click)=\"confirm()\"\r\n >\r\n {{ confirmLabelKey() | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@charset \"UTF-8\";.cf{position:fixed;inset:0;z-index:var(--z-dialog);display:grid;place-items:center;padding:var(--sp-5)}.cf__scrim{position:absolute;inset:0;background:var(--scrim);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);animation:cf-scrim-in var(--t-overlay)}@keyframes cf-scrim-in{0%{background:transparent;-webkit-backdrop-filter:blur(0);backdrop-filter:blur(0)}}.cf__panel{position:relative;width:min(480px,100%);border-radius:var(--r-lg);display:flex;flex-direction:column;border:1px solid var(--glass2-border);background-image:var(--glass2-bg);box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset)}@media(prefers-reduced-transparency:reduce){.cf__panel{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.cf__panel:before,.cf__panel:after{display:none}}@media(prefers-contrast:more){.cf__panel{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.cf__panel:after{animation:none}}.cf__panel{animation:menuIn .24s var(--nova-ease-structural) both}.cf__panel[data-kind=danger]{border-color:var(--danger-line)}.cf__panel[data-kind=warn]{border-color:var(--warning)}.cf__head{display:flex;align-items:flex-start;gap:14px;padding:20px 20px 14px}.cf__icon{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;flex-shrink:0;background:var(--w05);color:var(--ink-2);border:1px solid var(--w12)}.cf__icon[data-kind=warn]{background:var(--warning-bg);color:var(--warning-fg);border-color:var(--warning)}.cf__icon[data-kind=danger]{background:var(--danger-bg);color:var(--danger);border-color:var(--danger-line)}.cf__title{flex:1;min-width:0;font-size:var(--text-lg);font-weight:var(--fw-semibold);letter-spacing:-.005em;margin:0;padding-block-start:6px;color:var(--ink);line-height:1.35}.cf__close{width:28px;height:28px;border:0;background:transparent;color:var(--ink-3);cursor:pointer;border-radius:var(--r-sm);font-size:20px;line-height:1;display:grid;place-items:center;flex-shrink:0;margin-block-start:-4px;margin-inline-end:-4px;font-family:inherit;transition:background var(--t-state),color var(--t-state)}.cf__close:hover{color:var(--ink);background:var(--w08)}.cf__close:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:2px}.cf__body{padding:0 20px 18px;display:flex;flex-direction:column;gap:14px}.cf__msg{font-size:var(--text-md);line-height:1.55;color:var(--ink-2);margin:0}.cf__gate{display:flex;flex-direction:column;gap:6px;padding-block-start:var(--sp-1)}.cf__gate-l{font-size:var(--text-2xs);color:var(--ink-2)}.cf__gate-i{width:100%;box-sizing:border-box;padding:var(--sp-2) var(--sp-3);background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r-md);color:var(--ink);font-family:inherit;font-size:var(--text-base);transition:border-color var(--t-state),background var(--t-state)}.cf__gate-i::placeholder{color:var(--ink-4)}.cf__gate-i:hover{border-color:var(--line-2)}.cf__gate-i:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:-1px;border-color:transparent}.cf__gate-i:disabled{opacity:.5;cursor:not-allowed;background:var(--bg-3)}.cf__gate-i{height:32px;padding-block:0;font-size:var(--text-sm)}.cf__gate-i.mono{font-family:var(--font-mono)}.cf__ft{display:flex;justify-content:flex-end;gap:var(--sp-2);padding:12px 16px;border-block-start:1px solid var(--w08);background:var(--w03);border-end-start-radius:var(--r-lg);border-end-end-radius:var(--r-lg)}@media(width<=480px){.cf__head{padding:16px 16px 12px}.cf__body{padding:0 16px 14px}.cf__ft{padding:10px 12px;flex-wrap:wrap}.cf__ft [fly-button]{flex:1 1 auto;justify-content:center}}:host(.fly-confirm-dialog--mobile) .cf{padding:16px}:host(.fly-confirm-dialog--mobile) .cf__panel{inline-size:100%;border-radius:18px}:host(.fly-confirm-dialog--mobile) .cf__ft{flex-wrap:nowrap;border-end-start-radius:18px;border-end-end-radius:18px}:host(.fly-confirm-dialog--mobile) .cf__ft [fly-button]{flex:1 1 0;min-inline-size:0;min-block-size:44px}\n"] }]
25917
25961
  }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: true }] }], kind: [{ type: i0.Input, args: [{ isSignal: true, alias: "kind", required: false }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: true }] }], messageKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageKey", required: false }] }], confirmLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabelKey", required: false }] }], cancelLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabelKey", required: false }] }], requireText: [{ type: i0.Input, args: [{ isSignal: true, alias: "requireText", required: false }] }], busy: [{ type: i0.Input, args: [{ isSignal: true, alias: "busy", required: false }] }], confirmed: [{ type: i0.Output, args: ["confirmed"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }] } });
25918
25962
 
25919
25963
  /**
@@ -26111,7 +26155,7 @@ class FlyActionMenuComponent {
26111
26155
  }
26112
26156
  </div>
26113
26157
  </ng-template>
26114
- `, isInline: true, styles: [":host{display:inline-flex}.am{min-width:180px;padding:6px;border-radius:14px;display:flex;flex-direction:column;gap:2px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.am{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.am:before,.am:after{display:none}}@media(prefers-contrast:more){.am{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.am:after{animation:none}}.am{animation:menuIn .24s var(--nova-ease-structural) both}.am__item{display:flex;align-items:center;gap:10px;width:100%;min-height:32px;padding:7px 9px;border:0;background:transparent;color:var(--w95);font:var(--nova-font-menu-item);letter-spacing:var(--nova-tracking-menu-item);font-family:inherit;text-align:start;border-radius:8px;cursor:pointer;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.am__item .pi{font-size:14px;color:var(--w95);opacity:.7;flex-shrink:0}.am__item:hover{background:var(--w1)}.am__item:hover .pi{opacity:1}.am__item:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}.am__item[aria-disabled=true]{opacity:.38;filter:saturate(.6);cursor:default}.am__item[aria-disabled=true]:hover{background:transparent}.am__item[aria-disabled=true]:hover .pi{opacity:.7}.am__item--danger,.am__item--danger .pi{color:var(--sys-red)}.am__item--danger:hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.am__item--danger[aria-disabled=true]:hover{color:var(--sys-red)}.am__label{min-width:0;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: FlyIconButtonComponent, selector: "button[fly-icon-button]", inputs: ["variant", "active", "tooltipKey"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
26158
+ `, isInline: true, styles: [":host{display:inline-flex}.am{min-width:180px;padding:6px;border-radius:14px;display:flex;flex-direction:column;gap:2px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.am{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.am:before,.am:after{display:none}}@media(prefers-contrast:more){.am{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.am:after{animation:none}}.am{animation:menuIn .24s var(--nova-ease-structural) both}.am__item{display:flex;align-items:center;gap:10px;width:100%;min-height:32px;padding:7px 9px;border:0;background:transparent;color:var(--w95);font:var(--nova-font-menu-item);letter-spacing:var(--nova-tracking-menu-item);font-family:inherit;text-align:start;border-radius:8px;cursor:pointer;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.am__item .pi{font-size:14px;color:var(--w95);opacity:.7;flex-shrink:0}.am__item:hover{background:var(--w1)}.am__item:hover .pi{opacity:1}.am__item:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:-2px}.am__item[aria-disabled=true]{opacity:.38;filter:saturate(.6);cursor:default}.am__item[aria-disabled=true]:hover{background:transparent}.am__item[aria-disabled=true]:hover .pi{opacity:.7}.am__item--danger,.am__item--danger .pi{color:var(--sys-red)}.am__item--danger:hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.am__item--danger[aria-disabled=true]:hover{color:var(--sys-red)}.am__label{min-width:0;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: FlyIconButtonComponent, selector: "button[fly-icon-button]", inputs: ["variant", "active", "tooltipKey"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
26115
26159
  }
26116
26160
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FlyActionMenuComponent, decorators: [{
26117
26161
  type: Component,
@@ -26157,7 +26201,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
26157
26201
  }
26158
26202
  </div>
26159
26203
  </ng-template>
26160
- `, styles: [":host{display:inline-flex}.am{min-width:180px;padding:6px;border-radius:14px;display:flex;flex-direction:column;gap:2px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.am{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.am:before,.am:after{display:none}}@media(prefers-contrast:more){.am{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.am:after{animation:none}}.am{animation:menuIn .24s var(--nova-ease-structural) both}.am__item{display:flex;align-items:center;gap:10px;width:100%;min-height:32px;padding:7px 9px;border:0;background:transparent;color:var(--w95);font:var(--nova-font-menu-item);letter-spacing:var(--nova-tracking-menu-item);font-family:inherit;text-align:start;border-radius:8px;cursor:pointer;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.am__item .pi{font-size:14px;color:var(--w95);opacity:.7;flex-shrink:0}.am__item:hover{background:var(--w1)}.am__item:hover .pi{opacity:1}.am__item:focus-visible{outline:2px solid var(--focus-ring);outline-offset:-2px}.am__item[aria-disabled=true]{opacity:.38;filter:saturate(.6);cursor:default}.am__item[aria-disabled=true]:hover{background:transparent}.am__item[aria-disabled=true]:hover .pi{opacity:.7}.am__item--danger,.am__item--danger .pi{color:var(--sys-red)}.am__item--danger:hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.am__item--danger[aria-disabled=true]:hover{color:var(--sys-red)}.am__label{min-width:0;overflow:hidden;text-overflow:ellipsis}\n"] }]
26204
+ `, styles: [":host{display:inline-flex}.am{min-width:180px;padding:6px;border-radius:14px;display:flex;flex-direction:column;gap:2px;border:1px solid var(--glass2-border);background-image:radial-gradient(70% 60% at 50% 100%,var(--w07),transparent 70%),linear-gradient(180deg,var(--w08),transparent 20%),linear-gradient(180deg,var(--mat-menu-a),var(--mat-menu-b));box-shadow:0 16px 40px #0003,0 4px 10px #0000001a,var(--glass2-inset);-webkit-backdrop-filter:var(--glass2-blur);backdrop-filter:var(--glass2-blur)}@media(prefers-reduced-transparency:reduce){.am{border-color:transparent;background-color:light-dark(#eef2f8,#2c2c2e);background-image:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}.am:before,.am:after{display:none}}@media(prefers-contrast:more){.am{border-color:var(--w6)}}@media(prefers-reduced-motion:reduce){.am:after{animation:none}}.am{animation:menuIn .24s var(--nova-ease-structural) both}.am__item{display:flex;align-items:center;gap:10px;width:100%;min-height:32px;padding:7px 9px;border:0;background:transparent;color:var(--w95);font:var(--nova-font-menu-item);letter-spacing:var(--nova-tracking-menu-item);font-family:inherit;text-align:start;border-radius:8px;cursor:pointer;white-space:nowrap;transition:background var(--nova-duration-hover) var(--nova-ease-micro)}.am__item .pi{font-size:14px;color:var(--w95);opacity:.7;flex-shrink:0}.am__item:hover{background:var(--w1)}.am__item:hover .pi{opacity:1}.am__item:focus-visible{outline:2px solid;outline-color:var(--focus-ring);outline-offset:-2px}.am__item[aria-disabled=true]{opacity:.38;filter:saturate(.6);cursor:default}.am__item[aria-disabled=true]:hover{background:transparent}.am__item[aria-disabled=true]:hover .pi{opacity:.7}.am__item--danger,.am__item--danger .pi{color:var(--sys-red)}.am__item--danger:hover{background:color-mix(in oklab,var(--sys-red) 18%,transparent);color:var(--sys-red)}.am__item--danger[aria-disabled=true]:hover{color:var(--sys-red)}.am__label{min-width:0;overflow:hidden;text-overflow:ellipsis}\n"] }]
26161
26205
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], triggerTooltipKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerTooltipKey", required: false }] }], selected: [{ type: i0.Output, args: ["selected"] }], menu: [{ type: i0.ViewChild, args: ['menu', { isSignal: true }] }] } });
26162
26206
 
26163
26207
  /** Matches the leave animation in toast-host.component.scss (ts-out). */