@eui/ecl 22.0.0-alpha.2 → 22.0.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/docs/changelog.html +618 -0
  2. package/docs/components/EclDateBlockComponent.html +0 -9
  3. package/docs/components/EclDescriptionListDefinitionComponent.html +6 -44
  4. package/docs/components/EclIconComponent.html +1 -1
  5. package/docs/components/EclListIllustrationComponent.html +0 -171
  6. package/docs/components/EclListIllustrationItemComponent.html +77 -83
  7. package/docs/components/EclLoadingIndicatorComponent.html +4 -91
  8. package/docs/components/EclMegaMenuComponent.html +5 -203
  9. package/docs/components/EclMegaMenuFeaturedComponent.html +10 -126
  10. package/docs/components/EclMegaMenuInfoComponent.html +0 -91
  11. package/docs/components/EclMegaMenuItemComponent.html +38 -115
  12. package/docs/components/EclMegaMenuSubitemComponent.html +4 -68
  13. package/docs/components/EclMenuItemComponent.html +46 -0
  14. package/docs/components/EclModalBodyComponent.html +4 -45
  15. package/docs/components/EclModalComponent.html +5 -178
  16. package/docs/components/EclModalFooterComponent.html +4 -45
  17. package/docs/components/EclModalHeaderComponent.html +9 -76
  18. package/docs/components/EclSiteFooterRowCommonComponent.html +1 -1
  19. package/docs/components/EclSiteHeaderLanguageComponent.html +5 -627
  20. package/docs/components/EclSiteHeaderLanguagePopoverComponent.html +99 -440
  21. package/docs/components/EclSiteHeaderLoginComponent.html +9 -453
  22. package/docs/components/EclSiteHeaderSearchComponent.html +18 -470
  23. package/docs/components/EclSocialMediaFollowComponent.html +28 -39
  24. package/docs/components/EclSocialMediaFollowItemComponent.html +26 -129
  25. package/docs/components/EclStoryCardComponent.html +1 -1
  26. package/docs/directives/ECLClickOutsideDirective.html +3 -0
  27. package/docs/directives/EclDescriptionListDefinitionItemDirective.html +6 -47
  28. package/docs/directives/EclDescriptionListDefinitionListDirective.html +0 -116
  29. package/docs/directives/EclDividerDirective.html +0 -116
  30. package/docs/directives/EclFileUploadDirective.html +2 -390
  31. package/docs/directives/EclLabelDirective.html +0 -46
  32. package/docs/directives/EclLinkDirective.html +0 -39
  33. package/docs/directives/EclLoadingIndicatorLabelDirective.html +0 -61
  34. package/docs/directives/EclLoadingIndicatorOverlayDirective.html +0 -45
  35. package/docs/directives/EclMediaContainerCaptionDirective.html +0 -39
  36. package/docs/directives/EclMediaContainerCreditDirective.html +0 -39
  37. package/docs/directives/EclMediaContainerIframeDirective.html +13 -19
  38. package/docs/directives/EclMediaContainerItemAudioDescriptionDirective.html +0 -39
  39. package/docs/directives/EclMediaContainerItemDirective.html +0 -39
  40. package/docs/directives/EclMediaContainerPictureDirective.html +0 -39
  41. package/docs/directives/EclMegaMenuContainerDirective.html +0 -104
  42. package/docs/directives/EclMegaMenuFeaturedImageDirective.html +0 -104
  43. package/docs/directives/EclMegaMenuFeaturedListDirective.html +0 -104
  44. package/docs/directives/EclMegaMenuFeaturedListItemDescriptionDirective.html +0 -104
  45. package/docs/directives/EclMegaMenuFeaturedListItemDirective.html +0 -104
  46. package/docs/directives/EclMegaMenuFeaturedPictureDirective.html +0 -39
  47. package/docs/directives/EclMegaMenuListDirective.html +0 -104
  48. package/docs/directives/EclMegaMenuSpacerDirective.html +0 -104
  49. package/docs/directives/EclMegaMenuSublistDirective.html +0 -165
  50. package/docs/directives/EclModalBodyFixedContentDirective.html +0 -61
  51. package/docs/directives/EclModalCloseDirective.html +1 -90
  52. package/docs/directives/EclModalTriggerDirective.html +1 -90
  53. package/docs/js/search/search_index.js +2 -2
  54. package/docs/json/EclIconComponent.md +1 -1
  55. package/docs/json/EclMediaContainerIframeDirective.md +0 -1
  56. package/docs/json/EclSiteHeaderLanguagePopoverComponent.md +6 -6
  57. package/docs/json/EclSiteHeaderSearchComponent.md +1 -0
  58. package/docs/json/EclSocialMediaFollowComponent.md +1 -0
  59. package/docs/json/documentation.json +1261 -2880
  60. package/docs/llms.txt +31 -84
  61. package/docs/miscellaneous/variables.html +222 -41
  62. package/docs/properties.html +1 -1
  63. package/fesm2022/eui-ecl-components-ecl-date-block.mjs +2 -2
  64. package/fesm2022/eui-ecl-components-ecl-date-block.mjs.map +1 -1
  65. package/fesm2022/eui-ecl-components-ecl-divider.mjs +6 -13
  66. package/fesm2022/eui-ecl-components-ecl-divider.mjs.map +1 -1
  67. package/fesm2022/eui-ecl-components-ecl-file-upload.mjs +13 -27
  68. package/fesm2022/eui-ecl-components-ecl-file-upload.mjs.map +1 -1
  69. package/fesm2022/eui-ecl-components-ecl-icon.mjs.map +1 -1
  70. package/fesm2022/eui-ecl-components-ecl-inpage-navigation.mjs +55 -9
  71. package/fesm2022/eui-ecl-components-ecl-inpage-navigation.mjs.map +1 -1
  72. package/fesm2022/eui-ecl-components-ecl-label.mjs +6 -6
  73. package/fesm2022/eui-ecl-components-ecl-label.mjs.map +1 -1
  74. package/fesm2022/eui-ecl-components-ecl-link.mjs +10 -13
  75. package/fesm2022/eui-ecl-components-ecl-link.mjs.map +1 -1
  76. package/fesm2022/eui-ecl-components-ecl-list-illustration.mjs +19 -30
  77. package/fesm2022/eui-ecl-components-ecl-list-illustration.mjs.map +1 -1
  78. package/fesm2022/eui-ecl-components-ecl-list.mjs +44 -41
  79. package/fesm2022/eui-ecl-components-ecl-list.mjs.map +1 -1
  80. package/fesm2022/eui-ecl-components-ecl-loading-indicator.mjs +17 -20
  81. package/fesm2022/eui-ecl-components-ecl-loading-indicator.mjs.map +1 -1
  82. package/fesm2022/eui-ecl-components-ecl-media-container.mjs +36 -33
  83. package/fesm2022/eui-ecl-components-ecl-media-container.mjs.map +1 -1
  84. package/fesm2022/eui-ecl-components-ecl-mega-menu.mjs +100 -159
  85. package/fesm2022/eui-ecl-components-ecl-mega-menu.mjs.map +1 -1
  86. package/fesm2022/eui-ecl-components-ecl-menu.mjs +16 -3
  87. package/fesm2022/eui-ecl-components-ecl-menu.mjs.map +1 -1
  88. package/fesm2022/eui-ecl-components-ecl-modal.mjs +94 -88
  89. package/fesm2022/eui-ecl-components-ecl-modal.mjs.map +1 -1
  90. package/fesm2022/eui-ecl-components-ecl-site-footer.mjs +2 -2
  91. package/fesm2022/eui-ecl-components-ecl-site-footer.mjs.map +1 -1
  92. package/fesm2022/eui-ecl-components-ecl-site-header.mjs +326 -261
  93. package/fesm2022/eui-ecl-components-ecl-site-header.mjs.map +1 -1
  94. package/fesm2022/eui-ecl-components-ecl-social-media-follow.mjs +17 -17
  95. package/fesm2022/eui-ecl-components-ecl-social-media-follow.mjs.map +1 -1
  96. package/fesm2022/eui-ecl-components-ecl-story-card.mjs +2 -2
  97. package/fesm2022/eui-ecl-components-ecl-story-card.mjs.map +1 -1
  98. package/package.json +1 -1
  99. package/types/eui-ecl-components-ecl-date-block.d.ts.map +1 -1
  100. package/types/eui-ecl-components-ecl-divider.d.ts +0 -4
  101. package/types/eui-ecl-components-ecl-divider.d.ts.map +1 -1
  102. package/types/eui-ecl-components-ecl-file-upload.d.ts.map +1 -1
  103. package/types/eui-ecl-components-ecl-inpage-navigation.d.ts +25 -0
  104. package/types/eui-ecl-components-ecl-inpage-navigation.d.ts.map +1 -1
  105. package/types/eui-ecl-components-ecl-label.d.ts.map +1 -1
  106. package/types/eui-ecl-components-ecl-link.d.ts +2 -4
  107. package/types/eui-ecl-components-ecl-link.d.ts.map +1 -1
  108. package/types/eui-ecl-components-ecl-list-illustration.d.ts +3 -3
  109. package/types/eui-ecl-components-ecl-list-illustration.d.ts.map +1 -1
  110. package/types/eui-ecl-components-ecl-list.d.ts +9 -12
  111. package/types/eui-ecl-components-ecl-list.d.ts.map +1 -1
  112. package/types/eui-ecl-components-ecl-loading-indicator.d.ts.map +1 -1
  113. package/types/eui-ecl-components-ecl-media-container.d.ts +7 -2
  114. package/types/eui-ecl-components-ecl-media-container.d.ts.map +1 -1
  115. package/types/eui-ecl-components-ecl-mega-menu.d.ts +12 -22
  116. package/types/eui-ecl-components-ecl-mega-menu.d.ts.map +1 -1
  117. package/types/eui-ecl-components-ecl-menu.d.ts +12 -1
  118. package/types/eui-ecl-components-ecl-menu.d.ts.map +1 -1
  119. package/types/eui-ecl-components-ecl-modal.d.ts +20 -10
  120. package/types/eui-ecl-components-ecl-modal.d.ts.map +1 -1
  121. package/types/eui-ecl-components-ecl-site-header.d.ts +240 -216
  122. package/types/eui-ecl-components-ecl-site-header.d.ts.map +1 -1
  123. package/types/eui-ecl-components-ecl-social-media-follow.d.ts +5 -3
  124. package/types/eui-ecl-components-ecl-social-media-follow.d.ts.map +1 -1
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { HostBinding, Component, inject, PLATFORM_ID, Directive, EventEmitter, contentChild, forwardRef, HostListener, Output, Input, ElementRef, Renderer2, afterNextRender, viewChild, input, booleanAttribute, output, NgZone, DOCUMENT, Injectable, ChangeDetectorRef } from '@angular/core';
2
+ import { HostBinding, Component, inject, PLATFORM_ID, Directive, EventEmitter, contentChild, forwardRef, HostListener, Output, Input, ElementRef, Renderer2, afterNextRender, viewChild, input, booleanAttribute, output, NgZone, DOCUMENT, signal, Injectable } from '@angular/core';
3
3
  import * as i1 from '@eui/ecl/core';
4
4
  import { ECLBaseDirective, ECLClickOutsideDirective, EclBaseEvent, EclThemeService, EclRtlService, logoLanguageCode } from '@eui/ecl/core';
5
5
  import { isPlatformBrowser, UpperCasePipe, AsyncPipe } from '@angular/common';
@@ -21,9 +21,9 @@ import { EclMenuComponent } from '@eui/ecl/components/ecl-menu';
21
21
  import { EclHeaderMenuComunicationService } from '@eui/ecl/shared';
22
22
  import { TranslatePipe } from '@ngx-translate/core';
23
23
  import { ScrollDispatcher } from '@angular/cdk/scrolling';
24
- import * as i1$1 from '@angular/forms';
24
+ import * as i2$2 from '@angular/forms';
25
25
  import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
26
- import * as i2$2 from '@eui/ecl/components/ecl-search-form';
26
+ import * as i3$2 from '@eui/ecl/components/ecl-search-form';
27
27
  import { EUI_ECL_SEARCH_FORM } from '@eui/ecl/components/ecl-search-form';
28
28
 
29
29
  /**
@@ -404,9 +404,6 @@ class EclAreaChangeEvent {
404
404
  * Emits events when language is selected and when dialog is closed.
405
405
  */
406
406
  class EclSiteHeaderLanguagePopoverComponent extends ECLBaseDirective {
407
- get display() {
408
- return this.isHidden() ? 'none' : 'block';
409
- }
410
407
  constructor() {
411
408
  super();
412
409
  this.el = inject(ElementRef);
@@ -416,8 +413,15 @@ class EclSiteHeaderLanguagePopoverComponent extends ECLBaseDirective {
416
413
  */
417
414
  this.languageContent = viewChild('languageContent', /* @ts-ignore */
418
415
  ...(ngDevMode ? [{ debugName: "languageContent" }] : /* istanbul ignore next */ []));
419
- this.euLanguages = [];
420
- this.nonEuLanguages = [];
416
+ /**
417
+ * Current language
418
+ */
419
+ this.languageCode = input(undefined, /* @ts-ignore */
420
+ ...(ngDevMode ? [{ debugName: "languageCode" }] : /* istanbul ignore next */ []));
421
+ this.euLanguages = input([], /* @ts-ignore */
422
+ ...(ngDevMode ? [{ debugName: "euLanguages" }] : /* istanbul ignore next */ []));
423
+ this.nonEuLanguages = input([], /* @ts-ignore */
424
+ ...(ngDevMode ? [{ debugName: "nonEuLanguages" }] : /* istanbul ignore next */ []));
421
425
  /**
422
426
  * Number of columns for eu languages. Calculated by the parent component 'ecl-site-header-language'.
423
427
  */
@@ -448,13 +452,23 @@ class EclSiteHeaderLanguagePopoverComponent extends ECLBaseDirective {
448
452
  * Property to position the dialog correctly. Calculated by the parent component 'ecl-site-header-language'.
449
453
  */
450
454
  this.isFull = input(false, { ...(ngDevMode ? { debugName: "isFull" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
451
- this.languageClosed = output();
452
- this.languageSelected = output();
453
455
  /**
454
- * The role of the dialog is 'dialog'. Should not be changed.
456
+ * Property to position the dialog correctly. Calculated by the parent component 'ecl-site-header-language'.
457
+ */
458
+ this.rightPosition = input(undefined, /* @ts-ignore */
459
+ ...(ngDevMode ? [{ debugName: "rightPosition" }] : /* istanbul ignore next */ []));
460
+ /**
461
+ * Property to position the dialog correctly. Calculated by the parent component 'ecl-site-header-language'.
462
+ */
463
+ this.leftPosition = input(undefined, /* @ts-ignore */
464
+ ...(ngDevMode ? [{ debugName: "leftPosition" }] : /* istanbul ignore next */ []));
465
+ /**
466
+ * Property to position the arrow of the dialog correctly. Calculated by the parent component 'ecl-site-header-language'.
455
467
  */
456
- this.role = 'dialog';
457
- this.labelledBy = 'ecl-site-header__language-title';
468
+ this.languageArrowPosition = input(undefined, /* @ts-ignore */
469
+ ...(ngDevMode ? [{ debugName: "languageArrowPosition" }] : /* istanbul ignore next */ []));
470
+ this.languageClosed = output();
471
+ this.languageSelected = output();
458
472
  this.destroy$ = new Subject();
459
473
  this.scrollDispatcher = inject(ScrollDispatcher);
460
474
  this.zone = inject(NgZone);
@@ -478,6 +492,9 @@ class EclSiteHeaderLanguagePopoverComponent extends ECLBaseDirective {
478
492
  .join(' ')
479
493
  .trim();
480
494
  }
495
+ get display() {
496
+ return this.isHidden() ? 'none' : 'block';
497
+ }
481
498
  get isModal() {
482
499
  return !this.isHidden() || undefined;
483
500
  }
@@ -492,7 +509,6 @@ class EclSiteHeaderLanguagePopoverComponent extends ECLBaseDirective {
492
509
  this.languageClosed.emit(new EclSiteHeaderLanguageCloseEvent());
493
510
  }
494
511
  onLanguageClick(language, evt) {
495
- this.languageCode = language.code;
496
512
  this.languageSelected.emit(new EclSiteHeaderLanguageSelectedEvent(language));
497
513
  evt.preventDefault();
498
514
  }
@@ -518,76 +534,26 @@ class EclSiteHeaderLanguagePopoverComponent extends ECLBaseDirective {
518
534
  });
519
535
  }
520
536
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclSiteHeaderLanguagePopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
521
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: EclSiteHeaderLanguagePopoverComponent, isStandalone: true, selector: "ecl-site-header-language-popover", inputs: { languageCode: { classPropertyName: "languageCode", publicName: "languageCode", isSignal: false, isRequired: false, transformFunction: null }, euLanguages: { classPropertyName: "euLanguages", publicName: "euLanguages", isSignal: false, isRequired: false, transformFunction: null }, nonEuLanguages: { classPropertyName: "nonEuLanguages", publicName: "nonEuLanguages", isSignal: false, isRequired: false, transformFunction: null }, euColumnsCount: { classPropertyName: "euColumnsCount", publicName: "euColumnsCount", isSignal: true, isRequired: false, transformFunction: null }, nonEuColumnsCount: { classPropertyName: "nonEuColumnsCount", publicName: "nonEuColumnsCount", isSignal: true, isRequired: false, transformFunction: null }, isHidden: { classPropertyName: "isHidden", publicName: "isHidden", isSignal: true, isRequired: false, transformFunction: null }, isPushRight: { classPropertyName: "isPushRight", publicName: "isPushRight", isSignal: true, isRequired: false, transformFunction: null }, isPushLeft: { classPropertyName: "isPushLeft", publicName: "isPushLeft", isSignal: true, isRequired: false, transformFunction: null }, isStack: { classPropertyName: "isStack", publicName: "isStack", isSignal: true, isRequired: false, transformFunction: null }, isFull: { classPropertyName: "isFull", publicName: "isFull", isSignal: true, isRequired: false, transformFunction: null }, rightPosition: { classPropertyName: "rightPosition", publicName: "rightPosition", isSignal: false, isRequired: false, transformFunction: null }, leftPosition: { classPropertyName: "leftPosition", publicName: "leftPosition", isSignal: false, isRequired: false, transformFunction: null }, languageArrowPosition: { classPropertyName: "languageArrowPosition", publicName: "languageArrowPosition", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { languageClosed: "languageClosed", languageSelected: "languageSelected" }, host: { properties: { "style.right.px": "this.rightPosition", "style.left.px": "this.leftPosition", "style.--ecl-language-arrow-position": "this.languageArrowPosition", "attr.role": "this.role", "attr.aria-labelledby": "this.labelledBy", "style.display": "this.display", "class": "this.cssClasses", "attr.aria-modal": "this.isModal", "attr.hidden": "this.isDropdownHidden" } }, viewQueries: [{ propertyName: "languageContent", first: true, predicate: ["languageContent"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ecl-site-header__language-header\">\n <div class=\"ecl-site-header__language-title\">\n {{ 'ecl.language-list.SELECT-LANGUAGE' | translate }}\n </div>\n <button eclButton variant=\"tertiary\" eclStyle=\"neutral\" isIconOnly class=\"ecl-site-header__language-close\" (click)=\"onCloseClick()\">\n <span class=\"ecl-button__container\">\n <span class=\"ecl-button__label\">\n {{ 'ecl.common.CLOSE' | translate }}\n </span>\n <ecl-icon icon=\"close\" size=\"m\"></ecl-icon>\n </span>\n </button>\n</div>\n\n<div #languageContent class=\"ecl-site-header__language-content\" [style.max-height.px]=\"languageContentMaxHeight\"\n [class.ecl-site-header__language-content--stack]=\"isStack()\">\n @if (euLanguages.length) {\n <div class=\"ecl-site-header__language-category ecl-site-header__language-category--{{ euColumnsCount() }}-col\">\n <div class=\"ecl-site-header__language-category-title\">\n {{ 'ecl.language-list.EU-LANGUAGES' | translate }}\n </div>\n <ul class=\"ecl-site-header__language-list\" [attr.translate]=\"'no'\">\n @for (item of euLanguages; track item.code) {\n <li class=\"ecl-site-header__language-item\">\n <a\n eclLink\n href=\"#\"\n variant=\"standalone\"\n [lang]=\"item.code\"\n [hreflang]=\"item.code\"\n class=\"ecl-site-header__language-link\"\n [class.ecl-site-header__language-link--active]=\"item.code === languageCode\"\n (click)=\"onLanguageClick(item, $event)\">\n <span class=\"ecl-site-header__language-link-code\">{{ item.code }}</span>\n <span class=\"ecl-site-header__language-link-label\">{{ item.label }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n }\n @if (nonEuLanguages.length) {\n <div class=\"ecl-site-header__language-category ecl-site-header__language-category--{{ nonEuColumnsCount() }}-col\">\n <div class=\"ecl-site-header__language-category-title\">\n {{ 'ecl.language-list.NON-EU-LANGUAGES' | translate }}\n </div>\n <ul class=\"ecl-site-header__language-list\" [attr.translate]=\"'no'\">\n @for (item of nonEuLanguages; track item.code) {\n <li class=\"ecl-site-header__language-item\">\n <a\n eclLink\n href=\"#\"\n [lang]=\"item.code\"\n [hreflang]=\"item.code\"\n variant=\"standalone\"\n class=\"ecl-site-header__language-link\"\n [class.ecl-site-header__language-link--active]=\"item.code === languageCode\"\n (click)=\"onLanguageClick(item, $event)\">\n <span class=\"ecl-site-header__language-link-code\">{{ item.code }}</span>\n <span class=\"ecl-site-header__language-link-label\">{{ item.label }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n }\n</div>\n", dependencies: [{ kind: "component", type: i3.EclButtonComponent, selector: "button[eclButton], button[ecl-button], a[eclButton]", inputs: ["isIconOnly", "variant", "eclStyle", "size", "containerStyleClass"] }, { kind: "component", type: i2$1.EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "title", "ariaHidden", "focusable", "isFlipHorizontal"] }, { kind: "directive", type: i3$1.EclLinkDirective, selector: "[eclLink]", inputs: ["extraAttributes", "isInverted", "isIconOnly", "isHighlight", "isNoVisited", "isBranded", "variant"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
537
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: EclSiteHeaderLanguagePopoverComponent, isStandalone: true, selector: "ecl-site-header-language-popover", inputs: { languageCode: { classPropertyName: "languageCode", publicName: "languageCode", isSignal: true, isRequired: false, transformFunction: null }, euLanguages: { classPropertyName: "euLanguages", publicName: "euLanguages", isSignal: true, isRequired: false, transformFunction: null }, nonEuLanguages: { classPropertyName: "nonEuLanguages", publicName: "nonEuLanguages", isSignal: true, isRequired: false, transformFunction: null }, euColumnsCount: { classPropertyName: "euColumnsCount", publicName: "euColumnsCount", isSignal: true, isRequired: false, transformFunction: null }, nonEuColumnsCount: { classPropertyName: "nonEuColumnsCount", publicName: "nonEuColumnsCount", isSignal: true, isRequired: false, transformFunction: null }, isHidden: { classPropertyName: "isHidden", publicName: "isHidden", isSignal: true, isRequired: false, transformFunction: null }, isPushRight: { classPropertyName: "isPushRight", publicName: "isPushRight", isSignal: true, isRequired: false, transformFunction: null }, isPushLeft: { classPropertyName: "isPushLeft", publicName: "isPushLeft", isSignal: true, isRequired: false, transformFunction: null }, isStack: { classPropertyName: "isStack", publicName: "isStack", isSignal: true, isRequired: false, transformFunction: null }, isFull: { classPropertyName: "isFull", publicName: "isFull", isSignal: true, isRequired: false, transformFunction: null }, rightPosition: { classPropertyName: "rightPosition", publicName: "rightPosition", isSignal: true, isRequired: false, transformFunction: null }, leftPosition: { classPropertyName: "leftPosition", publicName: "leftPosition", isSignal: true, isRequired: false, transformFunction: null }, languageArrowPosition: { classPropertyName: "languageArrowPosition", publicName: "languageArrowPosition", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { languageClosed: "languageClosed", languageSelected: "languageSelected" }, host: { attributes: { "role": "dialog", "aria-labelledby": "ecl-site-header__language-title" }, properties: { "class": "cssClasses", "style.display": "display", "style.right.px": "rightPosition()", "style.left.px": "leftPosition()", "style.--ecl-overlay-arrow-position": "languageArrowPosition()", "attr.aria-modal": "isModal", "attr.hidden": "isDropdownHidden" } }, viewQueries: [{ propertyName: "languageContent", first: true, predicate: ["languageContent"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ecl-site-header__language-header\">\n <div class=\"ecl-site-header__language-title\">\n {{ 'ecl.language-list.SELECT-LANGUAGE' | translate }}\n </div>\n <button eclButton variant=\"tertiary\" eclStyle=\"neutral\" isIconOnly class=\"ecl-site-header__language-close\" (click)=\"onCloseClick()\">\n <span class=\"ecl-button__container\">\n <span class=\"ecl-button__label\">\n {{ 'ecl.common.CLOSE' | translate }}\n </span>\n <ecl-icon icon=\"close\" size=\"m\"></ecl-icon>\n </span>\n </button>\n</div>\n\n<div #languageContent class=\"ecl-site-header__language-content\" [style.max-height.px]=\"languageContentMaxHeight\"\n [class.ecl-site-header__language-content--stack]=\"isStack()\">\n @if (euLanguages().length) {\n <div class=\"ecl-site-header__language-category ecl-site-header__language-category--{{ euColumnsCount() }}-col\">\n <div class=\"ecl-site-header__language-category-title\">\n {{ 'ecl.language-list.EU-LANGUAGES' | translate }}\n </div>\n <ul class=\"ecl-site-header__language-list\" [attr.translate]=\"'no'\">\n @for (item of euLanguages(); track item.code) {\n <li class=\"ecl-site-header__language-item\">\n <a\n eclLink\n href=\"#\"\n variant=\"standalone\"\n [lang]=\"item.code\"\n [hreflang]=\"item.code\"\n class=\"ecl-site-header__language-link\"\n [class.ecl-site-header__language-link--active]=\"item.code === languageCode()\"\n (click)=\"onLanguageClick(item, $event)\">\n <span class=\"ecl-site-header__language-link-code\">{{ item.code }}</span>\n <span class=\"ecl-site-header__language-link-label\">{{ item.label }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n }\n @if (nonEuLanguages().length) {\n <div class=\"ecl-site-header__language-category ecl-site-header__language-category--{{ nonEuColumnsCount() }}-col\">\n <div class=\"ecl-site-header__language-category-title\">\n {{ 'ecl.language-list.NON-EU-LANGUAGES' | translate }}\n </div>\n <ul class=\"ecl-site-header__language-list\" [attr.translate]=\"'no'\">\n @for (item of nonEuLanguages(); track item.code) {\n <li class=\"ecl-site-header__language-item\">\n <a\n eclLink\n href=\"#\"\n [lang]=\"item.code\"\n [hreflang]=\"item.code\"\n variant=\"standalone\"\n class=\"ecl-site-header__language-link\"\n [class.ecl-site-header__language-link--active]=\"item.code === languageCode()\"\n (click)=\"onLanguageClick(item, $event)\">\n <span class=\"ecl-site-header__language-link-code\">{{ item.code }}</span>\n <span class=\"ecl-site-header__language-link-label\">{{ item.label }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n }\n</div>\n", dependencies: [{ kind: "component", type: i3.EclButtonComponent, selector: "button[eclButton], button[ecl-button], a[eclButton]", inputs: ["isIconOnly", "variant", "eclStyle", "size", "containerStyleClass"] }, { kind: "component", type: i2$1.EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "title", "ariaHidden", "focusable", "isFlipHorizontal"] }, { kind: "directive", type: i3$1.EclLinkDirective, selector: "[eclLink]", inputs: ["extraAttributes", "isInverted", "isIconOnly", "isHighlight", "isNoVisited", "isBranded", "variant"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
522
538
  }
523
539
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclSiteHeaderLanguagePopoverComponent, decorators: [{
524
540
  type: Component,
525
- args: [{ selector: 'ecl-site-header-language-popover', imports: [TranslatePipe, ...EUI_ECL_BUTTON, ...EUI_ECL_ICON, ...EUI_ECL_LINK], template: "<div class=\"ecl-site-header__language-header\">\n <div class=\"ecl-site-header__language-title\">\n {{ 'ecl.language-list.SELECT-LANGUAGE' | translate }}\n </div>\n <button eclButton variant=\"tertiary\" eclStyle=\"neutral\" isIconOnly class=\"ecl-site-header__language-close\" (click)=\"onCloseClick()\">\n <span class=\"ecl-button__container\">\n <span class=\"ecl-button__label\">\n {{ 'ecl.common.CLOSE' | translate }}\n </span>\n <ecl-icon icon=\"close\" size=\"m\"></ecl-icon>\n </span>\n </button>\n</div>\n\n<div #languageContent class=\"ecl-site-header__language-content\" [style.max-height.px]=\"languageContentMaxHeight\"\n [class.ecl-site-header__language-content--stack]=\"isStack()\">\n @if (euLanguages.length) {\n <div class=\"ecl-site-header__language-category ecl-site-header__language-category--{{ euColumnsCount() }}-col\">\n <div class=\"ecl-site-header__language-category-title\">\n {{ 'ecl.language-list.EU-LANGUAGES' | translate }}\n </div>\n <ul class=\"ecl-site-header__language-list\" [attr.translate]=\"'no'\">\n @for (item of euLanguages; track item.code) {\n <li class=\"ecl-site-header__language-item\">\n <a\n eclLink\n href=\"#\"\n variant=\"standalone\"\n [lang]=\"item.code\"\n [hreflang]=\"item.code\"\n class=\"ecl-site-header__language-link\"\n [class.ecl-site-header__language-link--active]=\"item.code === languageCode\"\n (click)=\"onLanguageClick(item, $event)\">\n <span class=\"ecl-site-header__language-link-code\">{{ item.code }}</span>\n <span class=\"ecl-site-header__language-link-label\">{{ item.label }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n }\n @if (nonEuLanguages.length) {\n <div class=\"ecl-site-header__language-category ecl-site-header__language-category--{{ nonEuColumnsCount() }}-col\">\n <div class=\"ecl-site-header__language-category-title\">\n {{ 'ecl.language-list.NON-EU-LANGUAGES' | translate }}\n </div>\n <ul class=\"ecl-site-header__language-list\" [attr.translate]=\"'no'\">\n @for (item of nonEuLanguages; track item.code) {\n <li class=\"ecl-site-header__language-item\">\n <a\n eclLink\n href=\"#\"\n [lang]=\"item.code\"\n [hreflang]=\"item.code\"\n variant=\"standalone\"\n class=\"ecl-site-header__language-link\"\n [class.ecl-site-header__language-link--active]=\"item.code === languageCode\"\n (click)=\"onLanguageClick(item, $event)\">\n <span class=\"ecl-site-header__language-link-code\">{{ item.code }}</span>\n <span class=\"ecl-site-header__language-link-label\">{{ item.label }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n }\n</div>\n" }]
526
- }], ctorParameters: () => [], propDecorators: { languageContent: [{ type: i0.ViewChild, args: ['languageContent', { isSignal: true }] }], languageCode: [{
527
- type: Input
528
- }], euLanguages: [{
529
- type: Input
530
- }], nonEuLanguages: [{
531
- type: Input
532
- }], euColumnsCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "euColumnsCount", required: false }] }], nonEuColumnsCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "nonEuColumnsCount", required: false }] }], isHidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "isHidden", required: false }] }], isPushRight: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPushRight", required: false }] }], isPushLeft: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPushLeft", required: false }] }], isStack: [{ type: i0.Input, args: [{ isSignal: true, alias: "isStack", required: false }] }], isFull: [{ type: i0.Input, args: [{ isSignal: true, alias: "isFull", required: false }] }], rightPosition: [{
533
- type: Input
534
- }, {
535
- type: HostBinding,
536
- args: ['style.right.px']
537
- }], leftPosition: [{
538
- type: Input
539
- }, {
540
- type: HostBinding,
541
- args: ['style.left.px']
542
- }], languageArrowPosition: [{
543
- type: Input
544
- }, {
545
- type: HostBinding,
546
- args: ['style.--ecl-language-arrow-position']
547
- }], languageClosed: [{ type: i0.Output, args: ["languageClosed"] }], languageSelected: [{ type: i0.Output, args: ["languageSelected"] }], role: [{
548
- type: HostBinding,
549
- args: ['attr.role']
550
- }], labelledBy: [{
551
- type: HostBinding,
552
- args: ['attr.aria-labelledby']
553
- }], display: [{
554
- type: HostBinding,
555
- args: ['style.display']
556
- }], cssClasses: [{
557
- type: HostBinding,
558
- args: ['class']
559
- }], isModal: [{
560
- type: HostBinding,
561
- args: ['attr.aria-modal']
562
- }], isDropdownHidden: [{
563
- type: HostBinding,
564
- args: ['attr.hidden']
565
- }] } });
566
-
567
- /**
568
- * This class is used for methods, that serve for communication between the components in ecl-side-header.
569
- */
570
- class EclAreaDataService {
571
- constructor() {
572
- this.dataSubject = new Subject();
573
- this.dataSubject$ = this.dataSubject.asObservable();
574
- }
575
- /**
576
- * When header is resized, some of it's chidren parameters for positioning on the screen need to be recalculated.
577
- * This event publishes the new site header position, so that the chidren can adjust their position accordingly.
578
- * @param event
579
- */
580
- publishEvent(event) {
581
- this.dataSubject.next(event);
582
- }
583
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclAreaDataService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
584
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclAreaDataService, providedIn: 'root' }); }
585
- }
586
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclAreaDataService, decorators: [{
587
- type: Injectable,
588
- args: [{ providedIn: 'root' }]
589
- }], ctorParameters: () => [] });
541
+ args: [{ selector: 'ecl-site-header-language-popover', imports: [TranslatePipe, ...EUI_ECL_BUTTON, ...EUI_ECL_ICON, ...EUI_ECL_LINK], host: {
542
+ // The role of the dialog is 'dialog'. Should not be changed.
543
+ role: 'dialog',
544
+ 'aria-labelledby': 'ecl-site-header__language-title',
545
+ '[class]': 'cssClasses',
546
+ '[style.display]': 'display',
547
+ '[style.right.px]': 'rightPosition()',
548
+ '[style.left.px]': 'leftPosition()',
549
+ '[style.--ecl-overlay-arrow-position]': 'languageArrowPosition()',
550
+ '[attr.aria-modal]': 'isModal',
551
+ '[attr.hidden]': 'isDropdownHidden',
552
+ }, template: "<div class=\"ecl-site-header__language-header\">\n <div class=\"ecl-site-header__language-title\">\n {{ 'ecl.language-list.SELECT-LANGUAGE' | translate }}\n </div>\n <button eclButton variant=\"tertiary\" eclStyle=\"neutral\" isIconOnly class=\"ecl-site-header__language-close\" (click)=\"onCloseClick()\">\n <span class=\"ecl-button__container\">\n <span class=\"ecl-button__label\">\n {{ 'ecl.common.CLOSE' | translate }}\n </span>\n <ecl-icon icon=\"close\" size=\"m\"></ecl-icon>\n </span>\n </button>\n</div>\n\n<div #languageContent class=\"ecl-site-header__language-content\" [style.max-height.px]=\"languageContentMaxHeight\"\n [class.ecl-site-header__language-content--stack]=\"isStack()\">\n @if (euLanguages().length) {\n <div class=\"ecl-site-header__language-category ecl-site-header__language-category--{{ euColumnsCount() }}-col\">\n <div class=\"ecl-site-header__language-category-title\">\n {{ 'ecl.language-list.EU-LANGUAGES' | translate }}\n </div>\n <ul class=\"ecl-site-header__language-list\" [attr.translate]=\"'no'\">\n @for (item of euLanguages(); track item.code) {\n <li class=\"ecl-site-header__language-item\">\n <a\n eclLink\n href=\"#\"\n variant=\"standalone\"\n [lang]=\"item.code\"\n [hreflang]=\"item.code\"\n class=\"ecl-site-header__language-link\"\n [class.ecl-site-header__language-link--active]=\"item.code === languageCode()\"\n (click)=\"onLanguageClick(item, $event)\">\n <span class=\"ecl-site-header__language-link-code\">{{ item.code }}</span>\n <span class=\"ecl-site-header__language-link-label\">{{ item.label }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n }\n @if (nonEuLanguages().length) {\n <div class=\"ecl-site-header__language-category ecl-site-header__language-category--{{ nonEuColumnsCount() }}-col\">\n <div class=\"ecl-site-header__language-category-title\">\n {{ 'ecl.language-list.NON-EU-LANGUAGES' | translate }}\n </div>\n <ul class=\"ecl-site-header__language-list\" [attr.translate]=\"'no'\">\n @for (item of nonEuLanguages(); track item.code) {\n <li class=\"ecl-site-header__language-item\">\n <a\n eclLink\n href=\"#\"\n [lang]=\"item.code\"\n [hreflang]=\"item.code\"\n variant=\"standalone\"\n class=\"ecl-site-header__language-link\"\n [class.ecl-site-header__language-link--active]=\"item.code === languageCode()\"\n (click)=\"onLanguageClick(item, $event)\">\n <span class=\"ecl-site-header__language-link-code\">{{ item.code }}</span>\n <span class=\"ecl-site-header__language-link-label\">{{ item.label }}</span>\n </a>\n </li>\n }\n </ul>\n </div>\n }\n</div>\n" }]
553
+ }], ctorParameters: () => [], propDecorators: { languageContent: [{ type: i0.ViewChild, args: ['languageContent', { isSignal: true }] }], languageCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "languageCode", required: false }] }], euLanguages: [{ type: i0.Input, args: [{ isSignal: true, alias: "euLanguages", required: false }] }], nonEuLanguages: [{ type: i0.Input, args: [{ isSignal: true, alias: "nonEuLanguages", required: false }] }], euColumnsCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "euColumnsCount", required: false }] }], nonEuColumnsCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "nonEuColumnsCount", required: false }] }], isHidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "isHidden", required: false }] }], isPushRight: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPushRight", required: false }] }], isPushLeft: [{ type: i0.Input, args: [{ isSignal: true, alias: "isPushLeft", required: false }] }], isStack: [{ type: i0.Input, args: [{ isSignal: true, alias: "isStack", required: false }] }], isFull: [{ type: i0.Input, args: [{ isSignal: true, alias: "isFull", required: false }] }], rightPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "rightPosition", required: false }] }], leftPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "leftPosition", required: false }] }], languageArrowPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "languageArrowPosition", required: false }] }], languageClosed: [{ type: i0.Output, args: ["languageClosed"] }], languageSelected: [{ type: i0.Output, args: ["languageSelected"] }] } });
590
554
 
555
+ /** Half the arrow's own width, matching ECL's `arrowSize`. */
556
+ const ARROW_SIZE$2 = '0.5rem';
591
557
  /**
592
558
  * This component is used to switch between the languages of the application. Shows the current language, when clicked,
593
559
  * opens a language selector.
@@ -598,15 +564,6 @@ class EclSiteHeaderLanguageComponent extends ECLBaseDirective {
598
564
  this.eclThemeService = inject(EclThemeService);
599
565
  this.config = inject(GLOBAL_CONFIG_TOKEN, { optional: true });
600
566
  this.i18nService = inject(I18nService);
601
- /**
602
- * The language popover, that shows all available languages (configured in the config file of the current site).
603
- */
604
- this.languagePopover = viewChild(EclSiteHeaderLanguagePopoverComponent, /* @ts-ignore */
605
- ...(ngDevMode ? [{ debugName: "languagePopover" }] : /* istanbul ignore next */ []));
606
- /**
607
- * The link to open the popover dialog.
608
- */
609
- this.languageLinkElement = viewChild('languageLink', { ...(ngDevMode ? { debugName: "languageLinkElement" } : /* istanbul ignore next */ {}), read: ElementRef });
610
567
  /**
611
568
  * Thie event is emited, when language link, showing the current language is clicked.
612
569
  */
@@ -615,8 +572,6 @@ class EclSiteHeaderLanguageComponent extends ECLBaseDirective {
615
572
  * Thie event is emited, when user selects a new language from the dropdown.
616
573
  */
617
574
  this.languageSelected = new EventEmitter();
618
- this.MOBILE_BREAKPOINT = 768;
619
- this.LANGUAGE_MAX_COLUMNS = 8;
620
575
  this.isLanguagesDropdownVisible = false;
621
576
  this.languageCode = 'en';
622
577
  /**
@@ -629,11 +584,23 @@ class EclSiteHeaderLanguageComponent extends ECLBaseDirective {
629
584
  this.nonEuLanguages = [];
630
585
  this.euColumnsCount = 1;
631
586
  this.nonEuColumnsCount = 1;
587
+ /**
588
+ * The language popover, that shows all available languages (configured in the config file of the current site).
589
+ */
590
+ this.languagePopover = viewChild(EclSiteHeaderLanguagePopoverComponent, /* @ts-ignore */
591
+ ...(ngDevMode ? [{ debugName: "languagePopover" }] : /* istanbul ignore next */ []));
592
+ /**
593
+ * The link to open the popover dialog.
594
+ */
595
+ this.languageLinkElement = viewChild('languageLink', { ...(ngDevMode ? { debugName: "languageLinkElement" } : /* istanbul ignore next */ {}), read: ElementRef });
596
+ this.MOBILE_BREAKPOINT = 768;
597
+ this.LANGUAGE_MAX_COLUMNS = 8;
598
+ this.RESIZE_DEBOUNCE = 200;
632
599
  this.destroy$ = new Subject();
633
600
  this._languages = [];
634
601
  this.isRtl = false;
635
- this.eclAreaDataService = inject(EclAreaDataService);
636
602
  this.eclRtlService = inject(EclRtlService);
603
+ this.el = inject(ElementRef);
637
604
  this.document = inject(DOCUMENT);
638
605
  this.window = this.document.defaultView; // Window | null
639
606
  }
@@ -644,13 +611,11 @@ class EclSiteHeaderLanguageComponent extends ECLBaseDirective {
644
611
  this.handleRtlChangeState();
645
612
  }
646
613
  /**
647
- * After view is initialized -> calculate popover position and initialize languages, that are configured in the config file
614
+ * After view is initialized -> set up resize repositioning and initialize languages, that are configured in the config file
648
615
  * of the current site.
649
616
  */
650
617
  ngAfterViewInit() {
651
- this.eclAreaDataService.dataSubject$.pipe(takeUntil(this.destroy$)).subscribe(parentHeaderRect => {
652
- this.calculatePopoverPosition(parentHeaderRect.right, parentHeaderRect.left);
653
- });
618
+ this.handleResize();
654
619
  this.handleInitialConfiguredLanguages();
655
620
  }
656
621
  ngOnDestroy() {
@@ -667,18 +632,14 @@ class EclSiteHeaderLanguageComponent extends ECLBaseDirective {
667
632
  onLanguageClick(evt) {
668
633
  this.isLanguagesDropdownVisible = !this.isLanguagesDropdownVisible;
669
634
  if (!this.isLanguagesDropdownVisible) {
670
- setTimeout(() => {
671
- this.isFull = false;
672
- this.isStack = false;
673
- this.isPushRight = false;
674
- this.rightPosition = undefined;
675
- this.leftPosition = undefined;
676
- this.languageArrowPosition = undefined;
677
- });
635
+ setTimeout(() => this.resetPositioning());
678
636
  }
679
637
  // If the dropdown is visible, we set the max-height of the dropdown, so that it can be scrolled.
680
638
  if (this.isLanguagesDropdownVisible) {
681
639
  setTimeout(() => this.languagePopover().setLanguageContentMaxHeight());
640
+ // Position the popover and its arrow after the popover is rendered and reflowed.
641
+ // Matches ECL's updateOverlayPosition call in toggleOverlay.
642
+ requestAnimationFrame(() => this.calculatePopoverPosition());
682
643
  }
683
644
  this.languageClick.next(new EclSiteHeaderLanguageClickEvent());
684
645
  evt.preventDefault();
@@ -710,6 +671,9 @@ class EclSiteHeaderLanguageComponent extends ECLBaseDirective {
710
671
  handleRtlChangeState() {
711
672
  this.eclRtlService.currentRtlState$.pipe(takeUntil(this.destroy$)).subscribe((rtlState) => {
712
673
  this.isRtl = rtlState;
674
+ if (this.isLanguagesDropdownVisible) {
675
+ this.calculatePopoverPosition();
676
+ }
713
677
  });
714
678
  }
715
679
  /**
@@ -721,44 +685,80 @@ class EclSiteHeaderLanguageComponent extends ECLBaseDirective {
721
685
  this.euColumnsCount = Math.ceil(this.euLanguages.length / this.LANGUAGE_MAX_COLUMNS);
722
686
  this.nonEuColumnsCount = Math.ceil(this.nonEuLanguages.length / this.LANGUAGE_MAX_COLUMNS);
723
687
  }
724
- calculatePopoverPosition(parentHeaderRight, parentHeaderLeft) {
725
- setTimeout(() => {
726
- if (this.hasLanguageCodes()) {
727
- const arrowSize = '0.5rem';
728
- const linkRect = this.languageLinkElement().nativeElement.getBoundingClientRect();
729
- const popoverRect = this.languagePopover()?.el.nativeElement.getBoundingClientRect();
730
- const screenWidth = this.window.innerWidth;
731
- const vw = Math.max(document.documentElement.clientWidth || 0, this.window.innerWidth || 0);
732
- this.isFull = false;
733
- this.isStack = false;
734
- this.isPushRight = false;
735
- this.isPushLeft = false;
736
- this.rightPosition = undefined;
737
- this.leftPosition = undefined;
738
- this.languageArrowPosition = undefined;
739
- if (popoverRect?.width > this.parentHeaderWidth) {
740
- this.isStack = true;
741
- if (this.nonEuLanguages.length) {
742
- this.nonEuColumnsCount = Math.max(this.euColumnsCount, this.nonEuColumnsCount);
743
- }
744
- }
745
- if (this.isRtl && popoverRect?.left < 0) {
746
- const arrowPosition = linkRect.right - parentHeaderLeft - linkRect.width / 2;
747
- this.isPushLeft = true;
748
- this.leftPosition = -linkRect.left + parentHeaderLeft;
749
- this.languageArrowPosition = `${arrowPosition}px`;
750
- }
751
- else if (!this.isRtl && popoverRect?.right > screenWidth) {
752
- const arrowPosition = parentHeaderRight - linkRect.right + linkRect.width / 2;
753
- this.isPushRight = true;
754
- this.rightPosition = -parentHeaderRight + linkRect.right;
755
- this.languageArrowPosition = `calc(${arrowPosition}px - ${arrowSize})`;
756
- }
757
- if (vw < this.MOBILE_BREAKPOINT) {
758
- const arrowPosition = popoverRect?.right - linkRect.right + linkRect.width / 2;
759
- this.isFull = true;
760
- this.languageArrowPosition = `calc(${arrowPosition}px - ${arrowSize})`;
761
- }
688
+ /**
689
+ * Clears every positioning flag/offset so a fresh calculation (or a close) starts from a known state.
690
+ */
691
+ resetPositioning() {
692
+ this.isFull = false;
693
+ this.isStack = false;
694
+ this.isPushRight = false;
695
+ this.isPushLeft = false;
696
+ this.rightPosition = undefined;
697
+ this.leftPosition = undefined;
698
+ this.languageArrowPosition = undefined;
699
+ }
700
+ /**
701
+ * Positions the language popover and its arrow, matching ECL's updateOverlayPosition.
702
+ * The container is the site-header top area (ECL's '[data-ecl-site-header-top]'), resolved from
703
+ * the DOM rather than a shared service so the measurement is taken at the right time (on open/resize).
704
+ */
705
+ calculatePopoverPosition() {
706
+ if (!this.isLanguagesDropdownVisible || !this.hasLanguageCodes())
707
+ return;
708
+ const container = this.el.nativeElement.closest('.ecl-site-header__top');
709
+ const languagePopover = this.languagePopover();
710
+ if (!container || !languagePopover)
711
+ return;
712
+ const toggleButtonRect = this.languageLinkElement().nativeElement.getBoundingClientRect();
713
+ const popoverRect = languagePopover.el.nativeElement.getBoundingClientRect();
714
+ const containerRect = container.getBoundingClientRect();
715
+ const screenWidth = this.window.innerWidth;
716
+ const clientWidth = Math.max(this.document.documentElement.clientWidth || 0, this.window.innerWidth || 0);
717
+ this.resetPositioning();
718
+ // Stack the EU / non-EU lists when the popover is wider than the container.
719
+ if (popoverRect.width > containerRect.width) {
720
+ this.isStack = true;
721
+ if (this.nonEuLanguages.length) {
722
+ this.nonEuColumnsCount = Math.max(this.euColumnsCount, this.nonEuColumnsCount);
723
+ }
724
+ }
725
+ // Mobile: the popover is full width. The arrow is anchored from the box's right edge,
726
+ // so the offset is measured against popoverRect.right. Exclusive with push-right/left,
727
+ // matching ECL's updateOverlayPosition (mobile branch returns early).
728
+ if (clientWidth < this.MOBILE_BREAKPOINT) {
729
+ const arrowOffset = popoverRect.right - toggleButtonRect.right + toggleButtonRect.width / 2;
730
+ this.isFull = true;
731
+ this.languageArrowPosition = `calc(${arrowOffset}px - ${ARROW_SIZE$2})`;
732
+ return;
733
+ }
734
+ // RTL: popover overflows the left edge -> push it right against the container's left edge.
735
+ if (this.isRtl && popoverRect.left < 0) {
736
+ const arrowOffset = toggleButtonRect.right - containerRect.left - toggleButtonRect.width / 2;
737
+ this.isPushLeft = true;
738
+ this.leftPosition = -toggleButtonRect.left + containerRect.left;
739
+ this.languageArrowPosition = `${arrowOffset}px`;
740
+ }
741
+ else if (!this.isRtl && popoverRect.right > screenWidth) {
742
+ // LTR: popover overflows the right edge -> push it left against the container's right edge.
743
+ const arrowOffset = containerRect.right - toggleButtonRect.right + toggleButtonRect.width / 2;
744
+ this.isPushRight = true;
745
+ this.rightPosition = -containerRect.right + toggleButtonRect.right;
746
+ this.languageArrowPosition = `calc(${arrowOffset}px - ${ARROW_SIZE$2})`;
747
+ }
748
+ }
749
+ /**
750
+ * On window resize -> reposition the popover, but only while it is open.
751
+ * Debounced for performance, matching ECL's handleResize.
752
+ */
753
+ handleResize() {
754
+ const win = this.window;
755
+ if (!win)
756
+ return;
757
+ fromEvent(win, 'resize')
758
+ .pipe(debounceTime(this.RESIZE_DEBOUNCE), takeUntil(this.destroy$))
759
+ .subscribe(() => {
760
+ if (this.isLanguagesDropdownVisible) {
761
+ this.calculatePopoverPosition();
762
762
  }
763
763
  });
764
764
  }
@@ -790,7 +790,7 @@ class EclSiteHeaderLanguageComponent extends ECLBaseDirective {
790
790
  });
791
791
  }
792
792
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclSiteHeaderLanguageComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
793
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: EclSiteHeaderLanguageComponent, isStandalone: true, selector: "ecl-site-header-language", outputs: { languageClick: "languageClick", languageSelected: "languageSelected" }, host: { listeners: { "eclClickOutside": "onClickOutside()", "document:keydown.escape": "onEscapeKeydownHandler()" }, properties: { "class": "this.cssClasses" } }, viewQueries: [{ propertyName: "languagePopover", first: true, predicate: EclSiteHeaderLanguagePopoverComponent, descendants: true, isSignal: true }, { propertyName: "languageLinkElement", first: true, predicate: ["languageLink"], descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, hostDirectives: [{ directive: i1.ECLClickOutsideDirective, outputs: ["eclClickOutside", "eclClickOutside"] }], ngImport: i0, template: "<a\n href=\"#\"\n #languageLink\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__language-selector\"\n aria-controls=\"language-list-overlay\"\n role=\"button\"\n [attr.aria-label]=\"'ecl.language-list.SELECT-LANGUAGE-EXT' | translate: { currentLang: getLanguageLabel() }\"\n [attr.aria-expanded]=\"isLanguagesDropdownVisible\"\n (click)=\"onLanguageClick($event)\"\n (keydown.space)=\"onLanguageClick($event)\">\n <span class=\"ecl-site-header__language-icon\">\n <ecl-icon icon=\"global\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n </span>\n {{ languageCode | uppercase }}\n</a>\n@if(hasLanguageCodes() && isLanguagesDropdownVisible) {\n<ecl-site-header-language-popover\n #languagePopover\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n id=\"language-list-overlay\"\n [languageCode]=\"languageCode\"\n [euLanguages]=\"euLanguages\"\n [nonEuLanguages]=\"nonEuLanguages\"\n [euColumnsCount]=\"euColumnsCount\"\n [nonEuColumnsCount]=\"nonEuColumnsCount\"\n [isStack]=\"isStack\"\n [isPushRight]=\"isPushRight\"\n [isPushLeft] = \"isPushLeft\"\n [isFull]=\"isFull\"\n [rightPosition]=\"rightPosition\"\n [leftPosition]=\"leftPosition\"\n [languageArrowPosition]=\"languageArrowPosition\"\n (languageSelected)=\"onLanguageSelected($event)\"\n (languageClosed)=\"onLanguageClosed($event)\">\n</ecl-site-header-language-popover>\n}", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i2.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: i2$1.EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "title", "ariaHidden", "focusable", "isFlipHorizontal"] }, { kind: "component", type: EclSiteHeaderLanguagePopoverComponent, selector: "ecl-site-header-language-popover", inputs: ["languageCode", "euLanguages", "nonEuLanguages", "euColumnsCount", "nonEuColumnsCount", "isHidden", "isPushRight", "isPushLeft", "isStack", "isFull", "rightPosition", "leftPosition", "languageArrowPosition"], outputs: ["languageClosed", "languageSelected"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: UpperCasePipe, name: "uppercase" }] }); }
793
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: EclSiteHeaderLanguageComponent, isStandalone: true, selector: "ecl-site-header-language", outputs: { languageClick: "languageClick", languageSelected: "languageSelected" }, host: { listeners: { "eclClickOutside": "onClickOutside()", "document:keydown.escape": "onEscapeKeydownHandler()" }, properties: { "class": "cssClasses" } }, viewQueries: [{ propertyName: "languagePopover", first: true, predicate: EclSiteHeaderLanguagePopoverComponent, descendants: true, isSignal: true }, { propertyName: "languageLinkElement", first: true, predicate: ["languageLink"], descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, hostDirectives: [{ directive: i1.ECLClickOutsideDirective, outputs: ["eclClickOutside", "eclClickOutside"] }], ngImport: i0, template: "<a\n href=\"#\"\n #languageLink\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__language-selector\"\n aria-controls=\"language-list-overlay\"\n role=\"button\"\n [attr.aria-label]=\"'ecl.language-list.SELECT-LANGUAGE-EXT' | translate: { currentLang: getLanguageLabel() }\"\n [attr.aria-expanded]=\"isLanguagesDropdownVisible\"\n (click)=\"onLanguageClick($event)\"\n (keydown.space)=\"onLanguageClick($event)\">\n <span class=\"ecl-site-header__language-icon\">\n <ecl-icon icon=\"global\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n </span>\n {{ languageCode | uppercase }}\n</a>\n@if(hasLanguageCodes() && isLanguagesDropdownVisible) {\n<ecl-site-header-language-popover\n #languagePopover\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n id=\"language-list-overlay\"\n [languageCode]=\"languageCode\"\n [euLanguages]=\"euLanguages\"\n [nonEuLanguages]=\"nonEuLanguages\"\n [euColumnsCount]=\"euColumnsCount\"\n [nonEuColumnsCount]=\"nonEuColumnsCount\"\n [isStack]=\"isStack\"\n [isPushRight]=\"isPushRight\"\n [isPushLeft] = \"isPushLeft\"\n [isFull]=\"isFull\"\n [rightPosition]=\"rightPosition\"\n [leftPosition]=\"leftPosition\"\n [languageArrowPosition]=\"languageArrowPosition\"\n (languageSelected)=\"onLanguageSelected($event)\"\n (languageClosed)=\"onLanguageClosed($event)\">\n</ecl-site-header-language-popover>\n}", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i2.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: i2$1.EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "title", "ariaHidden", "focusable", "isFlipHorizontal"] }, { kind: "component", type: EclSiteHeaderLanguagePopoverComponent, selector: "ecl-site-header-language-popover", inputs: ["languageCode", "euLanguages", "nonEuLanguages", "euColumnsCount", "nonEuColumnsCount", "isHidden", "isPushRight", "isPushLeft", "isStack", "isFull", "rightPosition", "leftPosition", "languageArrowPosition"], outputs: ["languageClosed", "languageSelected"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: UpperCasePipe, name: "uppercase" }] }); }
794
794
  }
795
795
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclSiteHeaderLanguageComponent, decorators: [{
796
796
  type: Component,
@@ -799,22 +799,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
799
799
  directive: ECLClickOutsideDirective,
800
800
  outputs: ['eclClickOutside'],
801
801
  },
802
- ], template: "<a\n href=\"#\"\n #languageLink\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__language-selector\"\n aria-controls=\"language-list-overlay\"\n role=\"button\"\n [attr.aria-label]=\"'ecl.language-list.SELECT-LANGUAGE-EXT' | translate: { currentLang: getLanguageLabel() }\"\n [attr.aria-expanded]=\"isLanguagesDropdownVisible\"\n (click)=\"onLanguageClick($event)\"\n (keydown.space)=\"onLanguageClick($event)\">\n <span class=\"ecl-site-header__language-icon\">\n <ecl-icon icon=\"global\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n </span>\n {{ languageCode | uppercase }}\n</a>\n@if(hasLanguageCodes() && isLanguagesDropdownVisible) {\n<ecl-site-header-language-popover\n #languagePopover\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n id=\"language-list-overlay\"\n [languageCode]=\"languageCode\"\n [euLanguages]=\"euLanguages\"\n [nonEuLanguages]=\"nonEuLanguages\"\n [euColumnsCount]=\"euColumnsCount\"\n [nonEuColumnsCount]=\"nonEuColumnsCount\"\n [isStack]=\"isStack\"\n [isPushRight]=\"isPushRight\"\n [isPushLeft] = \"isPushLeft\"\n [isFull]=\"isFull\"\n [rightPosition]=\"rightPosition\"\n [leftPosition]=\"leftPosition\"\n [languageArrowPosition]=\"languageArrowPosition\"\n (languageSelected)=\"onLanguageSelected($event)\"\n (languageClosed)=\"onLanguageClosed($event)\">\n</ecl-site-header-language-popover>\n}", styles: [":host{display:block}\n"] }]
803
- }], propDecorators: { languagePopover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => EclSiteHeaderLanguagePopoverComponent), { isSignal: true }] }], languageLinkElement: [{ type: i0.ViewChild, args: ['languageLink', { ...{ read: ElementRef }, isSignal: true }] }], languageClick: [{
802
+ ], host: {
803
+ '[class]': 'cssClasses',
804
+ '(eclClickOutside)': 'onClickOutside()',
805
+ '(document:keydown.escape)': 'onEscapeKeydownHandler()',
806
+ }, template: "<a\n href=\"#\"\n #languageLink\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__language-selector\"\n aria-controls=\"language-list-overlay\"\n role=\"button\"\n [attr.aria-label]=\"'ecl.language-list.SELECT-LANGUAGE-EXT' | translate: { currentLang: getLanguageLabel() }\"\n [attr.aria-expanded]=\"isLanguagesDropdownVisible\"\n (click)=\"onLanguageClick($event)\"\n (keydown.space)=\"onLanguageClick($event)\">\n <span class=\"ecl-site-header__language-icon\">\n <ecl-icon icon=\"global\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n </span>\n {{ languageCode | uppercase }}\n</a>\n@if(hasLanguageCodes() && isLanguagesDropdownVisible) {\n<ecl-site-header-language-popover\n #languagePopover\n cdkTrapFocus\n cdkTrapFocusAutoCapture\n id=\"language-list-overlay\"\n [languageCode]=\"languageCode\"\n [euLanguages]=\"euLanguages\"\n [nonEuLanguages]=\"nonEuLanguages\"\n [euColumnsCount]=\"euColumnsCount\"\n [nonEuColumnsCount]=\"nonEuColumnsCount\"\n [isStack]=\"isStack\"\n [isPushRight]=\"isPushRight\"\n [isPushLeft] = \"isPushLeft\"\n [isFull]=\"isFull\"\n [rightPosition]=\"rightPosition\"\n [leftPosition]=\"leftPosition\"\n [languageArrowPosition]=\"languageArrowPosition\"\n (languageSelected)=\"onLanguageSelected($event)\"\n (languageClosed)=\"onLanguageClosed($event)\">\n</ecl-site-header-language-popover>\n}", styles: [":host{display:block}\n"] }]
807
+ }], propDecorators: { languageClick: [{
804
808
  type: Output
805
809
  }], languageSelected: [{
806
810
  type: Output
807
- }], cssClasses: [{
808
- type: HostBinding,
809
- args: ['class']
810
- }], onClickOutside: [{
811
- type: HostListener,
812
- args: ['eclClickOutside']
813
- }], onEscapeKeydownHandler: [{
814
- type: HostListener,
815
- args: ['document:keydown.escape']
816
- }] } });
811
+ }], languagePopover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => EclSiteHeaderLanguagePopoverComponent), { isSignal: true }] }], languageLinkElement: [{ type: i0.ViewChild, args: ['languageLink', { ...{ read: ElementRef }, isSignal: true }] }] } });
817
812
 
813
+ /** Half the arrow's own width, matching ECL's `arrowSize`. */
814
+ const ARROW_SIZE$1 = '0.5rem';
815
+ /** Debounce for the resize recomputation, matching ECL's `handleResize`. */
816
+ const RESIZE_DEBOUNCE$1 = 200;
818
817
  /**
819
818
  * Component for login/logout as part of the harmonised site header. Emits events when user logs in and when user opens the
820
819
  * login dropdown.
@@ -823,22 +822,42 @@ class EclSiteHeaderLoginComponent extends ECLBaseDirective {
823
822
  constructor() {
824
823
  super();
825
824
  this.isLoggedIn = input(false, { ...(ngDevMode ? { debugName: "isLoggedIn" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
826
- this.class = 'ecl-site-header__login-container';
827
- this.loginLinkElement = viewChild('loginLink', { ...(ngDevMode ? { debugName: "loginLinkElement" } : /* istanbul ignore next */ {}), read: ElementRef });
828
825
  this.login = output();
829
826
  this.loginBoxToggle = new EventEmitter();
830
827
  /**
831
- * If login popover is open (true) or closed (false).
828
+ * If login popover is open (true) or closed (false). Kept public because the parent
829
+ * `ecl-site-header` resets it directly when the search box opens.
832
830
  */
833
831
  this.isLoginBoxActive = false;
834
- this.TABLET_BREAKPOINT = 996;
832
+ /**
833
+ * The position of the arrow of the popover, when in mobile (full-width) mode.
834
+ */
835
+ this.loginArrowPosition = signal(undefined, /* @ts-ignore */
836
+ ...(ngDevMode ? [{ debugName: "loginArrowPosition" }] : /* istanbul ignore next */ []));
837
+ /**
838
+ * The login link element from the view, i.e. the login button (the toggle).
839
+ */
840
+ this.loginLinkElement = viewChild('loginLink', { ...(ngDevMode ? { debugName: "loginLinkElement" } : /* istanbul ignore next */ {}), read: ElementRef });
841
+ /**
842
+ * The login box element from the view, i.e. the dropdown the arrow points at.
843
+ */
844
+ this.loginBoxElement = viewChild('loginBox', { ...(ngDevMode ? { debugName: "loginBoxElement" } : /* istanbul ignore next */ {}), read: ElementRef });
835
845
  this.destroy$ = new Subject();
836
- this.eclAreaDataService = inject(EclAreaDataService);
837
846
  this.eclRtlService = inject(EclRtlService);
838
847
  this.document = inject(DOCUMENT);
848
+ this.window = this.document.defaultView;
839
849
  afterNextRender(() => {
840
- this.handleRtlChangeState();
841
- this.handleSiteHeaderAreaChangeEvent();
850
+ // Recompute the arrow only while the box is open.
851
+ this.eclRtlService.currentRtlState$.pipe(debounceTime(50), takeUntil(this.destroy$)).subscribe(() => {
852
+ if (this.isLoginBoxActive)
853
+ this.setLoginArrow();
854
+ });
855
+ if (this.window) {
856
+ fromEvent(this.window, 'resize').pipe(debounceTime(RESIZE_DEBOUNCE$1), takeUntil(this.destroy$)).subscribe(() => {
857
+ if (this.isLoginBoxActive)
858
+ this.setLoginArrow();
859
+ });
860
+ }
842
861
  });
843
862
  }
844
863
  ngOnChanges(changes) {
@@ -854,7 +873,7 @@ class EclSiteHeaderLoginComponent extends ECLBaseDirective {
854
873
  /**
855
874
  * Close the login popover on click outside.
856
875
  */
857
- onClickOutsideMegaMenu() {
876
+ onClickOutside() {
858
877
  this.onLoginBoxClose();
859
878
  }
860
879
  /**
@@ -873,66 +892,56 @@ class EclSiteHeaderLoginComponent extends ECLBaseDirective {
873
892
  const event = new EclSiteHeaderLoginBoxToggleEvent(this.isLoginBoxActive);
874
893
  this.loginBoxToggle.next(event);
875
894
  evt.preventDefault();
895
+ if (this.isLoginBoxActive) {
896
+ // Measure after the '--active' class is applied and the box reflows to full width.
897
+ this.window?.requestAnimationFrame(() => this.setLoginArrow());
898
+ }
876
899
  }
877
900
  onLoginBoxClose() {
878
901
  if (this.isLoginBoxActive) {
879
902
  this.isLoginBoxActive = false;
880
903
  const event = new EclSiteHeaderLoginBoxToggleEvent(this.isLoginBoxActive);
881
904
  this.loginBoxToggle.next(event);
905
+ this.loginArrowPosition.set(undefined);
882
906
  }
883
907
  }
884
- handleRtlChangeState() {
885
- this.eclRtlService.currentRtlState$.pipe(debounceTime(50), takeUntil(this.destroy$)).subscribe(() => {
886
- this.calculateLoginArrowPosition(this.parentHeaderRight);
887
- });
888
- }
889
908
  /**
890
- * On resize -> calculate the popover arrow position, using parent element ecl-header html parameters.
909
+ * Position the dropdown arrow so it points at the toggle button.
910
+ * The arrow only exists on the mobile full-width dropdown, so the calculation is gated on the box
911
+ * spanning (almost) the full viewport width. The offset is relative to the box's own left edge.
912
+ * Mirrors ECL's 'setLoginArrow' in site-header.js.
891
913
  */
892
- handleSiteHeaderAreaChangeEvent() {
893
- this.eclAreaDataService.dataSubject$.pipe(takeUntil(this.destroy$)).subscribe(parentHeaderRect => {
894
- this.parentHeaderRight = parentHeaderRect.right;
895
- this.calculateLoginArrowPosition(this.parentHeaderRight);
896
- });
897
- }
898
- calculateLoginArrowPosition(parentHeaderRight) {
899
- const vw = this.document.documentElement.clientWidth;
900
- const arrowSize = '0.5rem';
901
- const loginLink = this.loginLinkElement()?.nativeElement.getBoundingClientRect();
902
- const arrowPosition = parentHeaderRight - loginLink?.right + loginLink?.width / 2;
903
- if (parentHeaderRight === undefined) {
914
+ setLoginArrow() {
915
+ const loginBoxRect = this.loginBoxElement()?.nativeElement.getBoundingClientRect();
916
+ const toggleButtonRect = this.loginLinkElement()?.nativeElement.getBoundingClientRect();
917
+ if (!loginBoxRect || !toggleButtonRect)
904
918
  return;
919
+ const clientWidth = this.document.documentElement.clientWidth;
920
+ if (loginBoxRect.width >= clientWidth - 1) {
921
+ const arrowOffset = toggleButtonRect.left - loginBoxRect.left + toggleButtonRect.width / 2;
922
+ this.loginArrowPosition.set(`calc(${arrowOffset}px - ${ARROW_SIZE$1})`);
905
923
  }
906
- if (this.isLoginBoxActive && vw < this.TABLET_BREAKPOINT) {
907
- this.loginArrowPosition = `calc(${arrowPosition}px + ${arrowSize})`;
908
- }
909
- else if (this.isLoginBoxActive) {
910
- this.loginArrowPosition = null;
924
+ else {
925
+ this.loginArrowPosition.set(undefined);
911
926
  }
912
927
  }
913
928
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclSiteHeaderLoginComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
914
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: EclSiteHeaderLoginComponent, isStandalone: true, selector: "ecl-site-header-login", inputs: { isLoggedIn: { classPropertyName: "isLoggedIn", publicName: "isLoggedIn", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { login: "login", loginBoxToggle: "loginBoxToggle" }, host: { listeners: { "eclClickOutside": "onClickOutsideMegaMenu()" }, properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "loginLinkElement", first: true, predicate: ["loginLink"], descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, usesOnChanges: true, hostDirectives: [{ directive: i1.ECLBaseDirective }, { directive: i1.ECLClickOutsideDirective, outputs: ["eclClickOutside", "eclClickOutside"] }], ngImport: i0, template: "@if (isLoggedIn()) {\n <a\n #loginLink\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__login-toggle\"\n aria-controls=\"login-box-id\"\n [attr.aria-expanded]=\"isLoginBoxActive\"\n (click)=\"onLoginBoxToggle($event)\">\n <ecl-icon icon=\"logged-in\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.site-header.LOGGED-IN' | translate }}\n </a>\n <div\n id=\"login-box-id\"\n [style]=\"{'--ecl-login-arrow-position': loginArrowPosition}\"\n class=\"{{ getLoginBoxCssClasses() }}\">\n <ng-content></ng-content>\n </div>\n} @else {\n <a\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__login-toggle\"\n [attr.aria-expanded]=\"isLoginBoxActive\"\n (click)=\"onLoginClick($event)\">\n <ecl-icon icon=\"log-in\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.site-header.LOGIN' | translate }}\n </a>\n}\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: i2$1.EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "title", "ariaHidden", "focusable", "isFlipHorizontal"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
929
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: EclSiteHeaderLoginComponent, isStandalone: true, selector: "ecl-site-header-login", inputs: { isLoggedIn: { classPropertyName: "isLoggedIn", publicName: "isLoggedIn", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { login: "login", loginBoxToggle: "loginBoxToggle" }, host: { listeners: { "eclClickOutside": "onClickOutside()" }, classAttribute: "ecl-site-header__login-container" }, viewQueries: [{ propertyName: "loginLinkElement", first: true, predicate: ["loginLink"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "loginBoxElement", first: true, predicate: ["loginBox"], descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, usesOnChanges: true, hostDirectives: [{ directive: i1.ECLClickOutsideDirective, outputs: ["eclClickOutside", "eclClickOutside"] }], ngImport: i0, template: "@if (isLoggedIn()) {\n <a\n #loginLink\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__login-toggle\"\n aria-controls=\"login-box-id\"\n [attr.aria-expanded]=\"isLoginBoxActive\"\n (click)=\"onLoginBoxToggle($event)\">\n <ecl-icon icon=\"logged-in\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.site-header.LOGGED-IN' | translate }}\n </a>\n <div\n #loginBox\n id=\"login-box-id\"\n [style]=\"{'--ecl-login-arrow-position': loginArrowPosition()}\"\n class=\"{{ getLoginBoxCssClasses() }}\">\n <ng-content></ng-content>\n </div>\n} @else {\n <a\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__login-toggle\"\n [attr.aria-expanded]=\"isLoginBoxActive\"\n (click)=\"onLoginClick($event)\">\n <ecl-icon icon=\"log-in\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.site-header.LOGIN' | translate }}\n </a>\n}\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: i2$1.EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "title", "ariaHidden", "focusable", "isFlipHorizontal"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
915
930
  }
916
931
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclSiteHeaderLoginComponent, decorators: [{
917
932
  type: Component,
918
933
  args: [{ selector: 'ecl-site-header-login', imports: [TranslatePipe, ...EUI_ECL_ICON], hostDirectives: [
919
- {
920
- directive: ECLBaseDirective,
921
- },
922
934
  {
923
935
  directive: ECLClickOutsideDirective,
924
936
  outputs: ['eclClickOutside'],
925
937
  },
926
- ], template: "@if (isLoggedIn()) {\n <a\n #loginLink\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__login-toggle\"\n aria-controls=\"login-box-id\"\n [attr.aria-expanded]=\"isLoginBoxActive\"\n (click)=\"onLoginBoxToggle($event)\">\n <ecl-icon icon=\"logged-in\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.site-header.LOGGED-IN' | translate }}\n </a>\n <div\n id=\"login-box-id\"\n [style]=\"{'--ecl-login-arrow-position': loginArrowPosition}\"\n class=\"{{ getLoginBoxCssClasses() }}\">\n <ng-content></ng-content>\n </div>\n} @else {\n <a\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__login-toggle\"\n [attr.aria-expanded]=\"isLoginBoxActive\"\n (click)=\"onLoginClick($event)\">\n <ecl-icon icon=\"log-in\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.site-header.LOGIN' | translate }}\n </a>\n}\n", styles: [":host{display:block}\n"] }]
927
- }], ctorParameters: () => [], propDecorators: { isLoggedIn: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoggedIn", required: false }] }], class: [{
928
- type: HostBinding,
929
- args: ['class']
930
- }], loginLinkElement: [{ type: i0.ViewChild, args: ['loginLink', { ...{ read: ElementRef }, isSignal: true }] }], login: [{ type: i0.Output, args: ["login"] }], loginBoxToggle: [{
938
+ ], host: {
939
+ class: 'ecl-site-header__login-container',
940
+ '(eclClickOutside)': 'onClickOutside()',
941
+ }, template: "@if (isLoggedIn()) {\n <a\n #loginLink\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__login-toggle\"\n aria-controls=\"login-box-id\"\n [attr.aria-expanded]=\"isLoginBoxActive\"\n (click)=\"onLoginBoxToggle($event)\">\n <ecl-icon icon=\"logged-in\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.site-header.LOGGED-IN' | translate }}\n </a>\n <div\n #loginBox\n id=\"login-box-id\"\n [style]=\"{'--ecl-login-arrow-position': loginArrowPosition()}\"\n class=\"{{ getLoginBoxCssClasses() }}\">\n <ng-content></ng-content>\n </div>\n} @else {\n <a\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-button--neutral ecl-site-header__login-toggle\"\n [attr.aria-expanded]=\"isLoginBoxActive\"\n (click)=\"onLoginClick($event)\">\n <ecl-icon icon=\"log-in\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.site-header.LOGIN' | translate }}\n </a>\n}\n", styles: [":host{display:block}\n"] }]
942
+ }], ctorParameters: () => [], propDecorators: { isLoggedIn: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoggedIn", required: false }] }], login: [{ type: i0.Output, args: ["login"] }], loginBoxToggle: [{
931
943
  type: Output
932
- }], onClickOutsideMegaMenu: [{
933
- type: HostListener,
934
- args: ['eclClickOutside']
935
- }] } });
944
+ }], loginLinkElement: [{ type: i0.ViewChild, args: ['loginLink', { ...{ read: ElementRef }, isSignal: true }] }], loginBoxElement: [{ type: i0.ViewChild, args: ['loginBox', { ...{ read: ElementRef }, isSignal: true }] }] } });
936
945
 
937
946
  /**
938
947
  * This directive is used to add specific class for the login description element, within the login dropdown.
@@ -1079,6 +1088,10 @@ const ECL_SITE_HEADER_SEARCH_VALUE_ACCESSOR = {
1079
1088
  const noop = () => {
1080
1089
  /** empty*/
1081
1090
  };
1091
+ /** Half the arrow's own width, matching ECL's `arrowSize`. */
1092
+ const ARROW_SIZE = '0.5rem';
1093
+ /** Debounce for the resize recomputation, matching ECL's `handleResize`. */
1094
+ const RESIZE_DEBOUNCE = 200;
1082
1095
  /**
1083
1096
  * This component builds the search box in the ecl-site-header component. Adds specific style and functionality, emits
1084
1097
  * events on search and search toggle.
@@ -1086,51 +1099,74 @@ const noop = () => {
1086
1099
  class EclSiteHeaderSearchComponent extends ECLBaseDirective {
1087
1100
  constructor() {
1088
1101
  super(...arguments);
1089
- this.class = 'ecl-site-header__search-container';
1090
- /**
1091
- * The default role of the component is 'search', should not be changed.
1092
- */
1093
- this.role = 'search';
1094
1102
  this.searchInputPlaceholder = input(undefined, /* @ts-ignore */
1095
1103
  ...(ngDevMode ? [{ debugName: "searchInputPlaceholder" }] : /* istanbul ignore next */ []));
1096
1104
  this.searchButtonLabel = input(undefined, /* @ts-ignore */
1097
1105
  ...(ngDevMode ? [{ debugName: "searchButtonLabel" }] : /* istanbul ignore next */ []));
1098
- /**
1099
- * The search link element from the view, i.e. the search button.
1100
- */
1101
- this.searchLinkElement = viewChild('searchLink', { ...(ngDevMode ? { debugName: "searchLinkElement" } : /* istanbul ignore next */ {}), read: ElementRef });
1102
1106
  this.searchEvent = output();
1103
1107
  this.searchToggle = new EventEmitter();
1108
+ /**
1109
+ * Whether the search dropdown is open. Kept public because the parent
1110
+ * `ecl-site-header` resets it directly when the login box opens.
1111
+ */
1104
1112
  this.isSearchBoxActive = false;
1113
+ /**
1114
+ * The arrow position of the search dropdown, when in mobile (full-width) mode.
1115
+ */
1116
+ this.searchArrowPosition = signal(undefined, /* @ts-ignore */
1117
+ ...(ngDevMode ? [{ debugName: "searchArrowPosition" }] : /* istanbul ignore next */ []));
1118
+ /**
1119
+ * The search link element from the view, i.e. the search button (the toggle).
1120
+ */
1121
+ this.searchLinkElement = viewChild('searchLink', { ...(ngDevMode ? { debugName: "searchLinkElement" } : /* istanbul ignore next */ {}), read: ElementRef });
1122
+ /**
1123
+ * The search form element from the view, i.e. the dropdown box the arrow points from.
1124
+ */
1125
+ this.searchFormElement = viewChild('searchForm', { ...(ngDevMode ? { debugName: "searchFormElement" } : /* istanbul ignore next */ {}), read: ElementRef });
1105
1126
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1106
1127
  this.onChange = noop;
1107
1128
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1108
1129
  this.onTouched = noop;
1109
1130
  this.destroy$ = new Subject();
1110
- this.eclAreaDataService = inject(EclAreaDataService);
1111
1131
  this.eclRtlService = inject(EclRtlService);
1112
- this.cdr = inject(ChangeDetectorRef);
1113
1132
  this.platformId = inject(PLATFORM_ID);
1114
1133
  this.document = inject(DOCUMENT);
1134
+ this.window = this.document.defaultView; // Window | null
1115
1135
  }
1116
1136
  ngAfterViewInit() {
1117
1137
  if (!isPlatformBrowser(this.platformId))
1118
1138
  return;
1119
- this.handleRtlChangeState();
1120
- this.handleSiteHeaderAreaChangeEvent();
1121
- const el = this.elementRef?.nativeElement ?? null; // if ECLBaseDirective exposes it
1122
- if (!el)
1123
- return;
1124
- this.ro = new ResizeObserver(() => {
1125
- this.calculateSearchFormArrowPosition(this.parentHeaderRight);
1126
- });
1127
- this.ro.observe(el);
1139
+ // Recompute while open on resize (debounced, matching ECL's handleResize).
1140
+ if (this.window) {
1141
+ fromEvent(this.window, 'resize')
1142
+ .pipe(debounceTime(RESIZE_DEBOUNCE), takeUntil(this.destroy$))
1143
+ .subscribe(() => this.setSearchArrow());
1144
+ }
1145
+ // Recompute while open on RTL direction change.
1146
+ this.eclRtlService.currentRtlState$.pipe(debounceTime(50), takeUntil(this.destroy$)).subscribe(() => this.setSearchArrow());
1128
1147
  }
1129
1148
  ngOnDestroy() {
1130
- this.ro?.disconnect();
1131
1149
  this.destroy$.next(true);
1132
1150
  this.destroy$.complete();
1133
1151
  }
1152
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1153
+ writeValue(value) {
1154
+ this.searchInputText = value;
1155
+ }
1156
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1157
+ registerOnChange(fn) {
1158
+ this.onChange = fn;
1159
+ }
1160
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1161
+ registerOnTouched(fn) {
1162
+ this.onTouched = fn;
1163
+ }
1164
+ /**
1165
+ * Close the search dropdown on click outside, matching ECL's `handleClickGlobal`.
1166
+ */
1167
+ onClickOutside() {
1168
+ this.closeSearchBox();
1169
+ }
1134
1170
  onSearch(evt) {
1135
1171
  this.searchEvent.emit(new EclSiteHeaderSearchEvent(evt.keyword));
1136
1172
  this.onChange(evt.keyword);
@@ -1141,6 +1177,11 @@ class EclSiteHeaderSearchComponent extends ECLBaseDirective {
1141
1177
  const event = new EclSiteHeaderSearchToggleEvent(this.isSearchBoxActive);
1142
1178
  this.searchToggle.next(event);
1143
1179
  evt.preventDefault();
1180
+ // Measure after the `--active` class is applied and the box reflows to
1181
+ // full width (matching ECL's toggleSearch -> setSearchArrow order).
1182
+ if (this.isSearchBoxActive) {
1183
+ this.window?.requestAnimationFrame(() => this.setSearchArrow());
1184
+ }
1144
1185
  }
1145
1186
  /**
1146
1187
  *
@@ -1153,56 +1194,80 @@ class EclSiteHeaderSearchComponent extends ECLBaseDirective {
1153
1194
  this.searchInputText = newValue;
1154
1195
  this.onChange(newValue);
1155
1196
  }
1156
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1157
- writeValue(value) {
1158
- this.searchInputText = value;
1159
- }
1160
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1161
- registerOnChange(fn) {
1162
- this.onChange = fn;
1163
- }
1164
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1165
- registerOnTouched(fn) {
1166
- this.onTouched = fn;
1167
- }
1168
- handleRtlChangeState() {
1169
- this.eclRtlService.currentRtlState$.pipe(debounceTime(50), takeUntil(this.destroy$)).subscribe(() => {
1170
- this.calculateSearchFormArrowPosition(this.parentHeaderRight);
1171
- });
1172
- }
1173
- handleSiteHeaderAreaChangeEvent() {
1174
- this.eclAreaDataService.dataSubject$.pipe(takeUntil(this.destroy$)).subscribe(parentHeaderRect => {
1175
- this.parentHeaderRight = parentHeaderRect.right;
1176
- this.calculateSearchFormArrowPosition(this.parentHeaderRight);
1177
- });
1197
+ closeSearchBox() {
1198
+ if (!this.isSearchBoxActive)
1199
+ return;
1200
+ this.isSearchBoxActive = false;
1201
+ this.searchToggle.next(new EclSiteHeaderSearchToggleEvent(this.isSearchBoxActive));
1202
+ this.searchArrowPosition.set(undefined);
1178
1203
  }
1179
- calculateSearchFormArrowPosition(parentHeaderRight) {
1180
- const searchLink = this.searchLinkElement().nativeElement.getBoundingClientRect();
1181
- const viewportWidth = this.document.documentElement.clientWidth;
1182
- const arrowPosition = viewportWidth - searchLink.right + searchLink.width / 2;
1183
- const arrowSize = '0.5rem';
1184
- if (this.isSearchBoxActive || parentHeaderRight !== undefined) {
1185
- this.searchArrowPosition = `calc(${arrowPosition}px + ${arrowSize})`;
1186
- this.cdr.detectChanges();
1204
+ /**
1205
+ * Positions the dropdown arrow so it points at the center of the search toggle button.
1206
+ * Mirrors ECL's `setSearchArrow`: the arrow position is an offset relative to the
1207
+ * search form's own left edge, and it only applies to the mobile full-width dropdown
1208
+ * (`searchFormRect.width >= clientWidth - 1`, the `- 1` absorbing subpixel rounding).
1209
+ */
1210
+ setSearchArrow() {
1211
+ if (!this.isSearchBoxActive)
1212
+ return;
1213
+ const searchFormRect = this.searchFormElement()?.nativeElement.getBoundingClientRect();
1214
+ const toggleButtonRect = this.searchLinkElement()?.nativeElement.getBoundingClientRect();
1215
+ if (!searchFormRect || !toggleButtonRect)
1216
+ return;
1217
+ const clientWidth = this.document.documentElement.clientWidth;
1218
+ if (searchFormRect.width >= clientWidth - 1) {
1219
+ const arrowOffset = toggleButtonRect.left - searchFormRect.left + toggleButtonRect.width / 2;
1220
+ this.searchArrowPosition.set(`calc(${arrowOffset}px - ${ARROW_SIZE})`);
1221
+ }
1222
+ else {
1223
+ this.searchArrowPosition.set(undefined);
1187
1224
  }
1188
1225
  }
1189
1226
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclSiteHeaderSearchComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1190
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.2", type: EclSiteHeaderSearchComponent, isStandalone: true, selector: "ecl-site-header-search", inputs: { searchInputText: { classPropertyName: "searchInputText", publicName: "searchInputText", isSignal: false, isRequired: false, transformFunction: null }, searchInputPlaceholder: { classPropertyName: "searchInputPlaceholder", publicName: "searchInputPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, searchButtonLabel: { classPropertyName: "searchButtonLabel", publicName: "searchButtonLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchEvent: "searchEvent", searchToggle: "searchToggle" }, host: { properties: { "class": "this.class", "attr.role": "this.role" } }, providers: [ECL_SITE_HEADER_SEARCH_VALUE_ACCESSOR], viewQueries: [{ propertyName: "searchLinkElement", first: true, predicate: ["searchLink"], descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<a\n #searchLink\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-site-header__search-toggle ecl-button--neutral\"\n data-ecl-search-toggle=\"true\"\n aria-controls=\"search-form-id\"\n [attr.aria-expanded]=\"isSearchBoxActive\"\n (click)=\"onSearchBoxToggle($event)\">\n <ecl-icon icon=\"search\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.common.SEARCH' | translate }}\n</a>\n\n<ecl-search-form\n [style]=\"{'--ecl-search-arrow-position': searchArrowPosition}\"\n (searchEvent)=\"onSearch($event)\"\n [placeholder]=\"searchInputPlaceholder()\"\n (ngModelChange)=\"onModelChange($event)\"\n [(ngModel)]=\"searchInputText\"\n [searchButtonLabel]=\"searchButtonLabel()\"\n [class]=\"getSearchBoxCssClasses()\">\n</ecl-search-form>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2$2.EclSearchFormComponent, selector: "ecl-search-form", inputs: ["searchInputText", "placeholder", "searchButtonLabel", "searchButtonIcon", "buttonExtraClassses", "inputExtraClassses"], outputs: ["searchInputTextChange", "searchEvent"] }, { kind: "component", type: i2$1.EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "title", "ariaHidden", "focusable", "isFlipHorizontal"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
1227
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.2", type: EclSiteHeaderSearchComponent, isStandalone: true, selector: "ecl-site-header-search", inputs: { searchInputText: { classPropertyName: "searchInputText", publicName: "searchInputText", isSignal: false, isRequired: false, transformFunction: null }, searchInputPlaceholder: { classPropertyName: "searchInputPlaceholder", publicName: "searchInputPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, searchButtonLabel: { classPropertyName: "searchButtonLabel", publicName: "searchButtonLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchEvent: "searchEvent", searchToggle: "searchToggle" }, host: { attributes: { "role": "search" }, listeners: { "eclClickOutside": "onClickOutside()" }, classAttribute: "ecl-site-header__search-container" }, providers: [ECL_SITE_HEADER_SEARCH_VALUE_ACCESSOR], viewQueries: [{ propertyName: "searchLinkElement", first: true, predicate: ["searchLink"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "searchFormElement", first: true, predicate: ["searchForm"], descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, hostDirectives: [{ directive: i1.ECLClickOutsideDirective, outputs: ["eclClickOutside", "eclClickOutside"] }], ngImport: i0, template: "<a\n #searchLink\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-site-header__search-toggle ecl-button--neutral\"\n data-ecl-search-toggle=\"true\"\n aria-controls=\"search-form-id\"\n [attr.aria-expanded]=\"isSearchBoxActive\"\n (click)=\"onSearchBoxToggle($event)\">\n <ecl-icon icon=\"search\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.common.SEARCH' | translate }}\n</a>\n\n<ecl-search-form\n #searchForm\n [style]=\"{'--ecl-search-arrow-position': searchArrowPosition()}\"\n (searchEvent)=\"onSearch($event)\"\n [placeholder]=\"searchInputPlaceholder()\"\n (ngModelChange)=\"onModelChange($event)\"\n [(ngModel)]=\"searchInputText\"\n [searchButtonLabel]=\"searchButtonLabel()\"\n [class]=\"getSearchBoxCssClasses()\">\n</ecl-search-form>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3$2.EclSearchFormComponent, selector: "ecl-search-form", inputs: ["searchInputText", "placeholder", "searchButtonLabel", "searchButtonIcon", "buttonExtraClassses", "inputExtraClassses"], outputs: ["searchInputTextChange", "searchEvent"] }, { kind: "component", type: i2$1.EclIconComponent, selector: "ecl-icon", inputs: ["iconSet", "icon", "size", "color", "transform", "ariaLabelledby", "role", "title", "ariaHidden", "focusable", "isFlipHorizontal"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
1191
1228
  }
1192
1229
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclSiteHeaderSearchComponent, decorators: [{
1193
1230
  type: Component,
1194
- args: [{ selector: 'ecl-site-header-search', imports: [FormsModule, TranslatePipe, ...EUI_ECL_SEARCH_FORM, ...EUI_ECL_ICON], providers: [ECL_SITE_HEADER_SEARCH_VALUE_ACCESSOR], template: "<a\n #searchLink\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-site-header__search-toggle ecl-button--neutral\"\n data-ecl-search-toggle=\"true\"\n aria-controls=\"search-form-id\"\n [attr.aria-expanded]=\"isSearchBoxActive\"\n (click)=\"onSearchBoxToggle($event)\">\n <ecl-icon icon=\"search\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.common.SEARCH' | translate }}\n</a>\n\n<ecl-search-form\n [style]=\"{'--ecl-search-arrow-position': searchArrowPosition}\"\n (searchEvent)=\"onSearch($event)\"\n [placeholder]=\"searchInputPlaceholder()\"\n (ngModelChange)=\"onModelChange($event)\"\n [(ngModel)]=\"searchInputText\"\n [searchButtonLabel]=\"searchButtonLabel()\"\n [class]=\"getSearchBoxCssClasses()\">\n</ecl-search-form>\n", styles: [":host{display:block}\n"] }]
1195
- }], propDecorators: { class: [{
1196
- type: HostBinding,
1197
- args: ['class']
1198
- }], role: [{
1199
- type: HostBinding,
1200
- args: ['attr.role']
1201
- }], searchInputText: [{
1231
+ args: [{ selector: 'ecl-site-header-search', imports: [FormsModule, TranslatePipe, ...EUI_ECL_SEARCH_FORM, ...EUI_ECL_ICON], providers: [ECL_SITE_HEADER_SEARCH_VALUE_ACCESSOR], hostDirectives: [
1232
+ {
1233
+ directive: ECLClickOutsideDirective,
1234
+ outputs: ['eclClickOutside'],
1235
+ },
1236
+ ], host: {
1237
+ class: 'ecl-site-header__search-container',
1238
+ // The default role of the component is 'search', should not be changed.
1239
+ role: 'search',
1240
+ '(eclClickOutside)': 'onClickOutside()',
1241
+ }, template: "<a\n #searchLink\n href=\"#\"\n class=\"ecl-button ecl-button--tertiary ecl-site-header__search-toggle ecl-button--neutral\"\n data-ecl-search-toggle=\"true\"\n aria-controls=\"search-form-id\"\n [attr.aria-expanded]=\"isSearchBoxActive\"\n (click)=\"onSearchBoxToggle($event)\">\n <ecl-icon icon=\"search\" size=\"m\" class=\"ecl-site-header__icon\"></ecl-icon>\n {{ 'ecl.common.SEARCH' | translate }}\n</a>\n\n<ecl-search-form\n #searchForm\n [style]=\"{'--ecl-search-arrow-position': searchArrowPosition()}\"\n (searchEvent)=\"onSearch($event)\"\n [placeholder]=\"searchInputPlaceholder()\"\n (ngModelChange)=\"onModelChange($event)\"\n [(ngModel)]=\"searchInputText\"\n [searchButtonLabel]=\"searchButtonLabel()\"\n [class]=\"getSearchBoxCssClasses()\">\n</ecl-search-form>\n", styles: [":host{display:block}\n"] }]
1242
+ }], propDecorators: { searchInputText: [{
1202
1243
  type: Input
1203
- }], searchInputPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchInputPlaceholder", required: false }] }], searchButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchButtonLabel", required: false }] }], searchLinkElement: [{ type: i0.ViewChild, args: ['searchLink', { ...{ read: ElementRef }, isSignal: true }] }], searchEvent: [{ type: i0.Output, args: ["searchEvent"] }], searchToggle: [{
1244
+ }], searchInputPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchInputPlaceholder", required: false }] }], searchButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchButtonLabel", required: false }] }], searchEvent: [{ type: i0.Output, args: ["searchEvent"] }], searchToggle: [{
1204
1245
  type: Output
1205
- }] } });
1246
+ }], searchLinkElement: [{ type: i0.ViewChild, args: ['searchLink', { ...{ read: ElementRef }, isSignal: true }] }], searchFormElement: [{ type: i0.ViewChild, args: ['searchForm', { ...{ read: ElementRef }, isSignal: true }] }] } });
1247
+
1248
+ /**
1249
+ * This class is used for methods, that serve for communication between the components in ecl-side-header.
1250
+ */
1251
+ class EclAreaDataService {
1252
+ constructor() {
1253
+ this.dataSubject = new Subject();
1254
+ this.dataSubject$ = this.dataSubject.asObservable();
1255
+ }
1256
+ /**
1257
+ * When header is resized, some of it's chidren parameters for positioning on the screen need to be recalculated.
1258
+ * This event publishes the new site header position, so that the chidren can adjust their position accordingly.
1259
+ * @param event
1260
+ */
1261
+ publishEvent(event) {
1262
+ this.dataSubject.next(event);
1263
+ }
1264
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclAreaDataService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1265
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclAreaDataService, providedIn: 'root' }); }
1266
+ }
1267
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: EclAreaDataService, decorators: [{
1268
+ type: Injectable,
1269
+ args: [{ providedIn: 'root' }]
1270
+ }], ctorParameters: () => [] });
1206
1271
 
1207
1272
  /**
1208
1273
  * The Site header offers easily recognisable elements (such as the logo) and the most essential functionality of