@edm-sdui/sdui 1.0.31 → 1.0.33

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 (51) hide show
  1. package/edm-sdui-sdui-1.0.33.tgz +0 -0
  2. package/esm2022/lib/components/uicomponent/button/button.component.mjs +9 -3
  3. package/esm2022/lib/components/uicomponent/column/column.component.mjs +2 -2
  4. package/esm2022/lib/components/uicomponent/image/image.component.mjs +1 -8
  5. package/esm2022/lib/components/uicomponent/label/label.component.mjs +19 -1
  6. package/esm2022/lib/components/uicomponent/row/row.component.mjs +2 -2
  7. package/esm2022/lib/components/uicomponent/tag/tag.component.mjs +137 -10
  8. package/esm2022/lib/components/uicomponent/tags-row/tags-row.component.mjs +84 -0
  9. package/esm2022/lib/core/services/scroll-spy.service.mjs +102 -0
  10. package/esm2022/lib/core/services/ui-action.service.mjs +31 -18
  11. package/esm2022/lib/core/services/uiscreen.service.mjs +3 -2
  12. package/esm2022/lib/core/uicomposition/enums/uicomponent-type.mjs +2 -1
  13. package/esm2022/lib/core/uicomposition/mapping/component-mapping.mjs +2 -1
  14. package/esm2022/lib/core/uicomposition/models/uicomponent.mjs +1 -1
  15. package/esm2022/lib/core/uicomposition/models/uitag.mjs +2 -0
  16. package/esm2022/lib/core/uitheme/enums/uicolor.mjs +10 -1
  17. package/esm2022/lib/core/uitheme/mapping/color-mapping.mjs +10 -1
  18. package/esm2022/lib/core/uitheme/mapping/size-mapping.mjs +9 -9
  19. package/esm2022/lib/directives/uiview.directive.mjs +45 -4
  20. package/esm2022/lib/sdui.module.mjs +4 -1
  21. package/fesm2022/edm-sdui-sdui.mjs +449 -52
  22. package/fesm2022/edm-sdui-sdui.mjs.map +1 -1
  23. package/lib/components/uicomponent/button/button.component.d.ts.map +1 -1
  24. package/lib/components/uicomponent/image/image.component.d.ts.map +1 -1
  25. package/lib/components/uicomponent/label/label.component.d.ts +1 -0
  26. package/lib/components/uicomponent/label/label.component.d.ts.map +1 -1
  27. package/lib/components/uicomponent/tag/tag.component.d.ts +19 -5
  28. package/lib/components/uicomponent/tag/tag.component.d.ts.map +1 -1
  29. package/lib/components/uicomponent/tags-row/tags-row.component.d.ts +27 -0
  30. package/lib/components/uicomponent/tags-row/tags-row.component.d.ts.map +1 -0
  31. package/lib/core/services/scroll-spy.service.d.ts +31 -0
  32. package/lib/core/services/scroll-spy.service.d.ts.map +1 -0
  33. package/lib/core/services/ui-action.service.d.ts +1 -0
  34. package/lib/core/services/ui-action.service.d.ts.map +1 -1
  35. package/lib/core/services/uiscreen.service.d.ts.map +1 -1
  36. package/lib/core/uicomposition/enums/uicomponent-type.d.ts +1 -0
  37. package/lib/core/uicomposition/enums/uicomponent-type.d.ts.map +1 -1
  38. package/lib/core/uicomposition/mapping/component-mapping.d.ts.map +1 -1
  39. package/lib/core/uicomposition/models/uicomponent.d.ts +2 -0
  40. package/lib/core/uicomposition/models/uicomponent.d.ts.map +1 -1
  41. package/lib/core/uicomposition/models/uitag.d.ts +6 -0
  42. package/lib/core/uicomposition/models/uitag.d.ts.map +1 -0
  43. package/lib/core/uitheme/enums/uicolor.d.ts +10 -1
  44. package/lib/core/uitheme/enums/uicolor.d.ts.map +1 -1
  45. package/lib/core/uitheme/mapping/color-mapping.d.ts.map +1 -1
  46. package/lib/directives/uiview.directive.d.ts +6 -0
  47. package/lib/directives/uiview.directive.d.ts.map +1 -1
  48. package/lib/sdui.module.d.ts +16 -15
  49. package/lib/sdui.module.d.ts.map +1 -1
  50. package/package.json +1 -1
  51. package/edm-sdui-sdui-1.0.31.tgz +0 -0
@@ -1,12 +1,12 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Optional, Inject, Injectable, Injector, Input, Component, EventEmitter, Output, createComponent, HostListener, Directive, ViewChild, inject, NgModule, ChangeDetectionStrategy } from '@angular/core';
2
+ import { InjectionToken, Optional, Inject, Injectable, Injector, Input, Component, EventEmitter, Output, createComponent, HostListener, Directive, ViewChild, inject, NgModule, ChangeDetectionStrategy, HostBinding } from '@angular/core';
3
3
  import * as i1$1 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as i1$3 from '@angular/router';
6
6
  import { RouterModule } from '@angular/router';
7
- import { map, BehaviorSubject, finalize, catchError, of } from 'rxjs';
7
+ import { map, BehaviorSubject, finalize, catchError, of, fromEvent, Subject } from 'rxjs';
8
8
  import * as i1 from '@angular/common/http';
9
- import { tap } from 'rxjs/operators';
9
+ import { tap, auditTime, startWith, map as map$1, distinctUntilChanged } from 'rxjs/operators';
10
10
  import * as i1$2 from '@angular/platform-browser';
11
11
 
12
12
  var UIScreenIdentifier;
@@ -43,6 +43,7 @@ var UIComponentType;
43
43
  UIComponentType["PICKER_ITEM"] = "PICKER_ITEM";
44
44
  // tag
45
45
  UIComponentType["TAG"] = "TAG";
46
+ UIComponentType["TAGS_ROW"] = "TAGS_ROW";
46
47
  // profile
47
48
  UIComponentType["PROFILE_BUTTON"] = "PROFILE_BUTTON";
48
49
  // progress bar
@@ -168,7 +169,8 @@ class UIScreenService {
168
169
  ? json.components.map((c) => this.mapToUIComponent(c))
169
170
  : [],
170
171
  element: json.element ? this.mapToUIElement(json.element) : null,
171
- excluded_platforms: json.excluded_platforms
172
+ excluded_platforms: json.excluded_platforms,
173
+ tags: json.tags,
172
174
  };
173
175
  }
174
176
  mapToUIElement(json) {
@@ -391,6 +393,7 @@ const componentMapping = {
391
393
  [UIComponentType.PICKER_ITEM]: () => Promise.resolve().then(function () { return pickerItem_component; }).then((m) => m.PickerItemComponent),
392
394
  // tag
393
395
  [UIComponentType.TAG]: () => Promise.resolve().then(function () { return tag_component; }).then((m) => m.TagComponent),
396
+ [UIComponentType.TAGS_ROW]: () => Promise.resolve().then(function () { return tagsRow_component; }).then((m) => m.TagsRowComponent),
394
397
  // profile
395
398
  [UIComponentType.PROFILE_BUTTON]: () => Promise.resolve().then(function () { return profileButton_component; }).then((m) => m.ProfileButtonComponent),
396
399
  // progress bar
@@ -556,7 +559,6 @@ class UIActionService {
556
559
  execute(action) {
557
560
  if (!action || !action.type)
558
561
  return;
559
- console.log(action);
560
562
  switch (action.type) {
561
563
  case UIActionType.INTERNAL_URL:
562
564
  if (action.url && isSduiUrl(action.url)) {
@@ -603,29 +605,43 @@ class UIActionService {
603
605
  }
604
606
  }
605
607
  scrollToAnchor(action) {
606
- // Confluence: param = string para uso geral; aqui priorizamos param como id do elemento
607
608
  const raw = action.param || action.url || '';
608
609
  const targetId = String(raw).replace(/^#/, '').trim();
609
- if (!targetId) {
610
- console.warn('[UIActionService] ANCHOR sem destino informado');
610
+ if (!targetId)
611
611
  return;
612
- }
613
612
  const el = document.getElementById(targetId);
614
- if (!el) {
615
- console.warn('[UIActionService] ANCHOR não encontrou elemento com id:', targetId);
613
+ if (!el)
614
+ return;
615
+ const target = el.querySelector('span');
616
+ const container = this.getScrollParent(target);
617
+ const isPage = container === document.documentElement ||
618
+ container === document.body ||
619
+ container === document.scrollingElement;
620
+ const isCanFix = document.querySelector('.tags-row--can-fix');
621
+ const OFFSET_TOP = isCanFix ? 140 : 180;
622
+ if (isPage) {
623
+ const top = target.getBoundingClientRect().top + window.scrollY - OFFSET_TOP;
624
+ window.scrollTo({ top, behavior: 'smooth' });
616
625
  return;
617
626
  }
618
- try {
619
- el.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' });
620
- }
621
- catch {
622
- el.scrollIntoView();
623
- }
624
- // guarda o último anchor acessado (usado pelo app host para restaurar)
625
- try {
626
- sessionStorage.setItem('exploreLastAnchor', targetId);
627
- }
628
- catch { }
627
+ const top = target.getBoundingClientRect().top -
628
+ container.getBoundingClientRect().top +
629
+ container.scrollTop -
630
+ OFFSET_TOP;
631
+ container.scrollTo({ top, behavior: 'smooth' });
632
+ }
633
+ getScrollParent(el) {
634
+ let parent = el.parentElement;
635
+ while (parent) {
636
+ const style = getComputedStyle(parent);
637
+ const overflowY = style.overflowY;
638
+ const canScroll = (overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay') &&
639
+ parent.scrollHeight > parent.clientHeight;
640
+ if (canScroll)
641
+ return parent;
642
+ parent = parent.parentElement;
643
+ }
644
+ return document.scrollingElement || document.documentElement;
629
645
  }
630
646
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UIActionService, deps: [{ token: i1$3.Router }, { token: ModalService }, { token: UIActionHandlersService }], target: i0.ɵɵFactoryTarget.Injectable }); }
631
647
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UIActionService, providedIn: 'root' }); }
@@ -1532,6 +1548,15 @@ var UIColor;
1532
1548
  UIColor["TEXT_CHALLENGE_DISABLED"] = "text_challenge_disabled";
1533
1549
  UIColor["TEXT_CHALLENGE_MAIN"] = "text_challenge_main";
1534
1550
  UIColor["CHALLENGE_WAY"] = "challenge_way";
1551
+ UIColor["AUX_TAG_EXPLORER_AUX"] = "aux_tag_explorer_aux";
1552
+ UIColor["BT_TAG_EXPLORER_OFF"] = "bt_tag_explorer_off";
1553
+ UIColor["BT_TAG_EXPLORER_ON"] = "bt_tag_explorer_on";
1554
+ UIColor["FONT_BT_TAG_EXPLORER_OFF"] = "font_bt_tag_explorer_off";
1555
+ UIColor["TAG_EXPLORER_HIGHLIGHT"] = "tag_explorer_highlight";
1556
+ UIColor["FONT_BT_TAG_EXPLORER_ON"] = "font_bt_tag_explorer_on";
1557
+ UIColor["BT_EXPLORER"] = "bt_explorer";
1558
+ UIColor["BG_EXPLORER"] = "bg_explorer";
1559
+ UIColor["FONT_BT_EXPLORER"] = "font_bt_explorer";
1535
1560
  })(UIColor || (UIColor = {}));
1536
1561
 
1537
1562
  const colorMapping = {
@@ -1662,6 +1687,15 @@ const colorMapping = {
1662
1687
  [UIColor.TEXT_CHALLENGE_DISABLED]: 'var(--text-challenge-disabled)',
1663
1688
  [UIColor.TEXT_CHALLENGE_MAIN]: 'var(--text-challenge-main)',
1664
1689
  [UIColor.CHALLENGE_WAY]: 'var(--challenge-way)',
1690
+ [UIColor.AUX_TAG_EXPLORER_AUX]: 'var(--aux-tag-explorer-aux)',
1691
+ [UIColor.BT_TAG_EXPLORER_OFF]: 'var(--bt-tag-explorer-off)',
1692
+ [UIColor.BT_TAG_EXPLORER_ON]: 'var(--bt-tag-explorer-on)',
1693
+ [UIColor.FONT_BT_TAG_EXPLORER_OFF]: 'var(--font-bt-tag-explorer-off)',
1694
+ [UIColor.TAG_EXPLORER_HIGHLIGHT]: 'var(--tag-explorer-highlight)',
1695
+ [UIColor.FONT_BT_TAG_EXPLORER_ON]: 'var(--font-bt-tag-explorer-on)',
1696
+ [UIColor.BT_EXPLORER]: 'var(--bt-explorer)',
1697
+ [UIColor.BG_EXPLORER]: 'var(--bg-explorer)',
1698
+ [UIColor.FONT_BT_EXPLORER]: 'var(--font-bt-explorer)',
1665
1699
  };
1666
1700
 
1667
1701
  var UIPaddingLevel;
@@ -1873,8 +1907,8 @@ var UISize;
1873
1907
  const sizeMappingHeight = {
1874
1908
  [UISize.THUMB_1]: '56px',
1875
1909
  [UISize.THUMB_2]: '40px',
1876
- [UISize.THUMB_3]: '180px',
1877
- [UISize.THUMB_4]: '327px',
1910
+ [UISize.THUMB_3]: '118px',
1911
+ [UISize.THUMB_4]: '169px',
1878
1912
  [UISize.ASSET_1]: '26px',
1879
1913
  [UISize.ASSET_2]: '16px',
1880
1914
  [UISize.ASSET_3]: '80px',
@@ -1883,14 +1917,14 @@ const sizeMappingHeight = {
1883
1917
  [UISize.ASSET_6]: '20px',
1884
1918
  [UISize.ASSET_7]: '22px',
1885
1919
  [UISize.ASSET_8]: '24px',
1886
- [UISize.CARD_1]: '320px',
1887
- [UISize.CARD_2]: '327px',
1920
+ [UISize.CARD_1]: '201px',
1921
+ [UISize.CARD_2]: '333px',
1888
1922
  };
1889
1923
  const sizeMappingWidth = {
1890
1924
  [UISize.THUMB_1]: '100px',
1891
1925
  [UISize.THUMB_2]: '105px',
1892
- [UISize.THUMB_3]: '320px',
1893
- [UISize.THUMB_4]: '225px',
1926
+ [UISize.THUMB_3]: '210px',
1927
+ [UISize.THUMB_4]: '300px',
1894
1928
  [UISize.ASSET_1]: '26px',
1895
1929
  [UISize.ASSET_2]: '16px',
1896
1930
  [UISize.ASSET_3]: '80px',
@@ -1899,8 +1933,8 @@ const sizeMappingWidth = {
1899
1933
  [UISize.ASSET_6]: '20px',
1900
1934
  [UISize.ASSET_7]: '22px',
1901
1935
  [UISize.ASSET_8]: '24px',
1902
- [UISize.CARD_1]: '320px',
1903
- [UISize.CARD_2]: '464px',
1936
+ [UISize.CARD_1]: '210px',
1937
+ [UISize.CARD_2]: '300px',
1904
1938
  };
1905
1939
 
1906
1940
  class UIViewDirective {
@@ -1911,10 +1945,21 @@ class UIViewDirective {
1911
1945
  this.actionService = actionService;
1912
1946
  this.screenViewModel = screenViewModel;
1913
1947
  this.disableClick = false;
1948
+ this.lastUiView = null;
1949
+ this.wasSmallScreen = this.isSmallScreen();
1950
+ this.currentContainer = UIScreenContainerType.CONTAINED;
1951
+ if (this.screenViewModel) {
1952
+ this.screenViewModel.uiScreen$.subscribe((screen) => {
1953
+ this.currentContainer =
1954
+ screen?.config?.container ?? UIScreenContainerType.CONTAINED;
1955
+ });
1956
+ }
1914
1957
  }
1915
1958
  ngOnChanges(changes) {
1916
1959
  if (this.edmSduiView) {
1960
+ this.lastUiView = this.edmSduiView;
1917
1961
  this.applyStyles(this.edmSduiView);
1962
+ this.wasSmallScreen = this.isSmallScreen();
1918
1963
  }
1919
1964
  }
1920
1965
  applyStyles(uiView) {
@@ -2082,12 +2127,37 @@ class UIViewDirective {
2082
2127
  }
2083
2128
  applySize(size) {
2084
2129
  if (size) {
2085
- const widthValue = sizeMappingWidth[size];
2086
- const heightValue = sizeMappingHeight[size];
2130
+ let widthValue = sizeMappingWidth[size];
2131
+ let heightValue = sizeMappingHeight[size];
2132
+ if (this.isSmallScreen() &&
2133
+ this.currentContainer === UIScreenContainerType.FLUID &&
2134
+ (size === UISize.CARD_1 || size === UISize.CARD_2 || size === UISize.THUMB_3 || size === UISize.THUMB_4)) {
2135
+ widthValue = this.scalePixelValue(widthValue, 1.2);
2136
+ heightValue = this.scalePixelValue(heightValue, 1.2);
2137
+ }
2087
2138
  this.renderer.setStyle(this.elementRef.nativeElement, 'width', widthValue);
2088
2139
  this.renderer.setStyle(this.elementRef.nativeElement, 'height', heightValue);
2089
2140
  }
2090
2141
  }
2142
+ isSmallScreen() {
2143
+ return typeof window !== 'undefined' && window.innerWidth >= 565;
2144
+ }
2145
+ scalePixelValue(value, divisor) {
2146
+ const match = /^(\d+(?:\.\d+)?)px$/.exec(value);
2147
+ if (!match) {
2148
+ return value;
2149
+ }
2150
+ const num = parseFloat(match[1]);
2151
+ const scaled = num * divisor;
2152
+ return `${scaled}px`;
2153
+ }
2154
+ onWindowResize() {
2155
+ const isSmall = this.isSmallScreen();
2156
+ if (this.lastUiView && isSmall !== this.wasSmallScreen) {
2157
+ this.applyStyles(this.lastUiView);
2158
+ this.wasSmallScreen = isSmall;
2159
+ }
2160
+ }
2091
2161
  onClick(event) {
2092
2162
  if (this.disableClick)
2093
2163
  return;
@@ -2097,7 +2167,7 @@ class UIViewDirective {
2097
2167
  }
2098
2168
  }
2099
2169
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UIViewDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1$3.Router }, { token: UIActionService }, { token: UIScreenViewModel, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
2100
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: UIViewDirective, isStandalone: false, selector: "[edmSduiView]", inputs: { edmSduiView: "edmSduiView", disableClick: "disableClick" }, host: { listeners: { "click": "onClick($event)" } }, usesOnChanges: true, ngImport: i0 }); }
2170
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: UIViewDirective, isStandalone: false, selector: "[edmSduiView]", inputs: { edmSduiView: "edmSduiView", disableClick: "disableClick" }, host: { listeners: { "window:resize": "onWindowResize()", "click": "onClick($event)" } }, usesOnChanges: true, ngImport: i0 }); }
2101
2171
  }
2102
2172
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UIViewDirective, decorators: [{
2103
2173
  type: Directive,
@@ -2111,6 +2181,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
2111
2181
  type: Input
2112
2182
  }], disableClick: [{
2113
2183
  type: Input
2184
+ }], onWindowResize: [{
2185
+ type: HostListener,
2186
+ args: ['window:resize']
2114
2187
  }], onClick: [{
2115
2188
  type: HostListener,
2116
2189
  args: ['click', ['$event']]
@@ -2236,11 +2309,11 @@ class RowComponent {
2236
2309
  ngOnInit() {
2237
2310
  }
2238
2311
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: RowComponent, deps: [{ token: 'uiComponent' }], target: i0.ɵɵFactoryTarget.Component }); }
2239
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: RowComponent, isStandalone: false, selector: "edm-sdui-row", ngImport: i0, template: "<div\n class=\"row-1\"\n *ngIf=\"uiComponent\"\n [edmSduiView]=\"uiComponent.element\"\n [class.row-fixed]=\"\n uiComponent.element?.size\"\n>\n <edm-sdui-component\n *ngFor=\"let component of uiComponent.components\"\n [uiComponent]=\"component\"\n >\n </edm-sdui-component>\n</div>\n", styles: [":host{display:contents}.row-1{display:flex;flex-direction:row;align-items:center}.row-fixed{flex:0 0 auto;max-width:100%;box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: UIComponentComponent, selector: "edm-sdui-component", inputs: ["uiComponent", "translateLabel"] }, { kind: "directive", type: UIViewDirective, selector: "[edmSduiView]", inputs: ["edmSduiView", "disableClick"] }] }); }
2312
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: RowComponent, isStandalone: false, selector: "edm-sdui-row", ngImport: i0, template: "<div\n class=\"row-1\"\n *ngIf=\"uiComponent\"\n [edmSduiView]=\"uiComponent.element\"\n [class.row-fixed]=\"\n uiComponent.element?.size\"\n>\n <edm-sdui-component\n *ngFor=\"let component of uiComponent.components\"\n [uiComponent]=\"component\"\n >\n </edm-sdui-component>\n</div>\n", styles: [":host{display:contents}.row-1{display:flex;flex-direction:row;align-items:center}.row-fixed{flex:0 0 auto;max-width:100%;box-sizing:border-box}@media (max-width: 565px){.row-fixed{max-width:none;width:auto}.row-fixed>*{flex-shrink:0;min-width:100%}}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: UIComponentComponent, selector: "edm-sdui-component", inputs: ["uiComponent", "translateLabel"] }, { kind: "directive", type: UIViewDirective, selector: "[edmSduiView]", inputs: ["edmSduiView", "disableClick"] }] }); }
2240
2313
  }
2241
2314
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: RowComponent, decorators: [{
2242
2315
  type: Component,
2243
- args: [{ selector: 'edm-sdui-row', standalone: false, template: "<div\n class=\"row-1\"\n *ngIf=\"uiComponent\"\n [edmSduiView]=\"uiComponent.element\"\n [class.row-fixed]=\"\n uiComponent.element?.size\"\n>\n <edm-sdui-component\n *ngFor=\"let component of uiComponent.components\"\n [uiComponent]=\"component\"\n >\n </edm-sdui-component>\n</div>\n", styles: [":host{display:contents}.row-1{display:flex;flex-direction:row;align-items:center}.row-fixed{flex:0 0 auto;max-width:100%;box-sizing:border-box}\n"] }]
2316
+ args: [{ selector: 'edm-sdui-row', standalone: false, template: "<div\n class=\"row-1\"\n *ngIf=\"uiComponent\"\n [edmSduiView]=\"uiComponent.element\"\n [class.row-fixed]=\"\n uiComponent.element?.size\"\n>\n <edm-sdui-component\n *ngFor=\"let component of uiComponent.components\"\n [uiComponent]=\"component\"\n >\n </edm-sdui-component>\n</div>\n", styles: [":host{display:contents}.row-1{display:flex;flex-direction:row;align-items:center}.row-fixed{flex:0 0 auto;max-width:100%;box-sizing:border-box}@media (max-width: 565px){.row-fixed{max-width:none;width:auto}.row-fixed>*{flex-shrink:0;min-width:100%}}\n"] }]
2244
2317
  }], ctorParameters: () => [{ type: undefined, decorators: [{
2245
2318
  type: Inject,
2246
2319
  args: ['uiComponent']
@@ -2259,11 +2332,11 @@ class ColumnComponent {
2259
2332
  // console.debug('column.uiComponent: ', this.uiComponent);
2260
2333
  }
2261
2334
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ColumnComponent, deps: [{ token: 'uiComponent' }], target: i0.ɵɵFactoryTarget.Component }); }
2262
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ColumnComponent, isStandalone: false, selector: "edm-sdui-column", ngImport: i0, template: "<div class=\"column\" *ngIf=\"uiComponent\" [edmSduiView]=\"uiComponent.element\">\n <edm-sdui-component\n *ngFor=\"let child of uiComponent.components\"\n [uiComponent]=\"child\"\n >\n </edm-sdui-component>\n</div>\n", styles: [":host{display:contents}.column{display:flex;flex-direction:column;overflow:clip;flex:0 0 auto}.row-fixed :host .column,:host-context(.row-fixed) .column{flex:1 1 0%;min-width:0}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: UIComponentComponent, selector: "edm-sdui-component", inputs: ["uiComponent", "translateLabel"] }, { kind: "directive", type: UIViewDirective, selector: "[edmSduiView]", inputs: ["edmSduiView", "disableClick"] }] }); }
2335
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ColumnComponent, isStandalone: false, selector: "edm-sdui-column", ngImport: i0, template: "<div class=\"column\" *ngIf=\"uiComponent\" [edmSduiView]=\"uiComponent.element\">\n <edm-sdui-component\n *ngFor=\"let child of uiComponent.components\"\n [uiComponent]=\"child\"\n >\n </edm-sdui-component>\n</div>\n", styles: [":host{display:contents}.column{display:flex;flex-direction:column;overflow:clip;flex:0 0 auto}.row-fixed :host .column,:host-context(.row-fixed) .column{flex:1 1 0%;min-width:0}@media (max-width: 565px){.row-fixed :host .column,:host-context(.row-fixed) .column{flex:1 1 0%;min-width:0;width:100%;max-width:100%}}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: UIComponentComponent, selector: "edm-sdui-component", inputs: ["uiComponent", "translateLabel"] }, { kind: "directive", type: UIViewDirective, selector: "[edmSduiView]", inputs: ["edmSduiView", "disableClick"] }] }); }
2263
2336
  }
2264
2337
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ColumnComponent, decorators: [{
2265
2338
  type: Component,
2266
- args: [{ selector: 'edm-sdui-column', standalone: false, template: "<div class=\"column\" *ngIf=\"uiComponent\" [edmSduiView]=\"uiComponent.element\">\n <edm-sdui-component\n *ngFor=\"let child of uiComponent.components\"\n [uiComponent]=\"child\"\n >\n </edm-sdui-component>\n</div>\n", styles: [":host{display:contents}.column{display:flex;flex-direction:column;overflow:clip;flex:0 0 auto}.row-fixed :host .column,:host-context(.row-fixed) .column{flex:1 1 0%;min-width:0}\n"] }]
2339
+ args: [{ selector: 'edm-sdui-column', standalone: false, template: "<div class=\"column\" *ngIf=\"uiComponent\" [edmSduiView]=\"uiComponent.element\">\n <edm-sdui-component\n *ngFor=\"let child of uiComponent.components\"\n [uiComponent]=\"child\"\n >\n </edm-sdui-component>\n</div>\n", styles: [":host{display:contents}.column{display:flex;flex-direction:column;overflow:clip;flex:0 0 auto}.row-fixed :host .column,:host-context(.row-fixed) .column{flex:1 1 0%;min-width:0}@media (max-width: 565px){.row-fixed :host .column,:host-context(.row-fixed) .column{flex:1 1 0%;min-width:0;width:100%;max-width:100%}}\n"] }]
2267
2340
  }], ctorParameters: () => [{ type: undefined, decorators: [{
2268
2341
  type: Inject,
2269
2342
  args: ['uiComponent']
@@ -2361,6 +2434,7 @@ class LabelComponent {
2361
2434
  }
2362
2435
  }
2363
2436
  applyElement(element) {
2437
+ let resolvedLineHeight = null;
2364
2438
  if (element.textColor) {
2365
2439
  const color = colorMapping[element.textColor];
2366
2440
  this.renderer.setStyle(this.spanElementRef.nativeElement, 'color', color);
@@ -2374,6 +2448,7 @@ class LabelComponent {
2374
2448
  this.renderer.setStyle(this.spanElementRef.nativeElement, 'font-weight', fontWeight);
2375
2449
  this.renderer.setStyle(this.spanElementRef.nativeElement, 'font-size', fontSize);
2376
2450
  this.renderer.setStyle(this.spanElementRef.nativeElement, 'line-height', lineHeight);
2451
+ resolvedLineHeight = lineHeight;
2377
2452
  }
2378
2453
  const normalizedMaxLinesRaw = element.maxLines ?? 1;
2379
2454
  const normalizedMaxLines = Number(normalizedMaxLinesRaw);
@@ -2385,6 +2460,12 @@ class LabelComponent {
2385
2460
  this.renderer.setStyle(this.spanElementRef.nativeElement, 'white-space', 'normal');
2386
2461
  this.renderer.setStyle(this.spanElementRef.nativeElement, 'word-break', 'break-word');
2387
2462
  this.renderer.setStyle(this.spanElementRef.nativeElement, '-webkit-line-clamp', normalizedMaxLines);
2463
+ if (resolvedLineHeight) {
2464
+ const minHeight = this.getMinHeight(resolvedLineHeight, normalizedMaxLines);
2465
+ if (minHeight) {
2466
+ this.renderer.setStyle(this.spanElementRef.nativeElement, 'min-height', minHeight);
2467
+ }
2468
+ }
2388
2469
  }
2389
2470
  if (element.opacity) {
2390
2471
  const opacity = element.opacity;
@@ -2408,6 +2489,16 @@ class LabelComponent {
2408
2489
  }
2409
2490
  }
2410
2491
  }
2492
+ getMinHeight(lineHeight, lines) {
2493
+ if (lines <= 0)
2494
+ return null;
2495
+ const pxMatch = /^(\d+(?:\.\d+)?)px$/.exec(lineHeight);
2496
+ if (pxMatch) {
2497
+ const pxValue = parseFloat(pxMatch[1]) * lines;
2498
+ return `${pxValue}px`;
2499
+ }
2500
+ return `calc(${lineHeight} * ${lines})`;
2501
+ }
2411
2502
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: LabelComponent, deps: [{ token: 'uiComponent' }, { token: i0.Renderer2 }, { token: FontSizeMappingService }], target: i0.ɵɵFactoryTarget.Component }); }
2412
2503
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: LabelComponent, isStandalone: false, selector: "edm-sdui-label", viewQueries: [{ propertyName: "spanElementRef", first: true, predicate: ["spanElement"], descendants: true }], ngImport: i0, template: "<span #spanElement [edmSduiView]=\"uiComponent.element\" *ngIf=\"uiComponent\">{{\n uiComponent.element?.label ?? \"\"\n}}</span>\n", styles: [":host{display:contents}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: UIViewDirective, selector: "[edmSduiView]", inputs: ["edmSduiView", "disableClick"] }] }); }
2413
2504
  }
@@ -2518,18 +2609,23 @@ class ButtonComponent {
2518
2609
  if (element.textStyle) {
2519
2610
  const textStyleMappingFontSize = this.fontSizeMappingService.getMapping();
2520
2611
  const fontSize = textStyleMappingFontSize[element.textStyle];
2612
+ const fontWeight = textStyleMappingFontWeight[element.textStyle];
2613
+ const lineHeight = textStyleMappingLineHeight[element.textStyle];
2614
+ //TODO: Substituir por classe no futuro.
2615
+ this.renderer.setStyle(this.buttonElementRef.nativeElement, 'font-weight', fontWeight);
2521
2616
  this.renderer.setStyle(this.buttonElementRef.nativeElement, 'font-size', fontSize);
2617
+ this.renderer.setStyle(this.buttonElementRef.nativeElement, 'line-height', lineHeight);
2522
2618
  }
2523
2619
  }
2524
2620
  getAssetPath(asset) {
2525
2621
  return assetMapping[asset];
2526
2622
  }
2527
2623
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ButtonComponent, deps: [{ token: 'uiComponent' }, { token: i0.Renderer2 }, { token: FontSizeMappingService }], target: i0.ɵɵFactoryTarget.Component }); }
2528
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ButtonComponent, isStandalone: false, selector: "edm-sdui-button", viewQueries: [{ propertyName: "buttonElementRef", first: true, predicate: ["buttonElement"], descendants: true }], ngImport: i0, template: "<button #buttonElement [edmSduiView]=\"uiComponent.element\" *ngIf=\"uiComponent\">\n <img *ngIf=\"uiComponent.element.asset\" [src]=\"getAssetPath(uiComponent.element.asset)\" alt=\"\">\n {{ uiComponent.element.label }}\n</button>\n", styles: [":host{display:contents}button{border:none;white-space:nowrap;background-color:unset}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: UIViewDirective, selector: "[edmSduiView]", inputs: ["edmSduiView", "disableClick"] }] }); }
2624
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: ButtonComponent, isStandalone: false, selector: "edm-sdui-button", viewQueries: [{ propertyName: "buttonElementRef", first: true, predicate: ["buttonElement"], descendants: true }], ngImport: i0, template: "<button #buttonElement [edmSduiView]=\"uiComponent.element\" *ngIf=\"uiComponent\">\n <img *ngIf=\"uiComponent.element.asset\" [src]=\"getAssetPath(uiComponent.element.asset)\" alt=\"\">\n {{ uiComponent.element.label }}\n</button>\n", styles: [":host{display:contents}button{border:none;white-space:nowrap;background-color:unset;width:fit-content}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: UIViewDirective, selector: "[edmSduiView]", inputs: ["edmSduiView", "disableClick"] }] }); }
2529
2625
  }
2530
2626
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ButtonComponent, decorators: [{
2531
2627
  type: Component,
2532
- args: [{ selector: 'edm-sdui-button', standalone: false, template: "<button #buttonElement [edmSduiView]=\"uiComponent.element\" *ngIf=\"uiComponent\">\n <img *ngIf=\"uiComponent.element.asset\" [src]=\"getAssetPath(uiComponent.element.asset)\" alt=\"\">\n {{ uiComponent.element.label }}\n</button>\n", styles: [":host{display:contents}button{border:none;white-space:nowrap;background-color:unset}\n"] }]
2628
+ args: [{ selector: 'edm-sdui-button', standalone: false, template: "<button #buttonElement [edmSduiView]=\"uiComponent.element\" *ngIf=\"uiComponent\">\n <img *ngIf=\"uiComponent.element.asset\" [src]=\"getAssetPath(uiComponent.element.asset)\" alt=\"\">\n {{ uiComponent.element.label }}\n</button>\n", styles: [":host{display:contents}button{border:none;white-space:nowrap;background-color:unset;width:fit-content}\n"] }]
2533
2629
  }], ctorParameters: () => [{ type: undefined, decorators: [{
2534
2630
  type: Inject,
2535
2631
  args: ['uiComponent']
@@ -2576,12 +2672,6 @@ class ImageComponent {
2576
2672
  else if (element.url) {
2577
2673
  this.renderer.setAttribute(this.imgElementRef.nativeElement, 'src', element.url);
2578
2674
  }
2579
- if (element.size) {
2580
- const height = sizeMappingHeight[element.size];
2581
- const width = sizeMappingWidth[element.size];
2582
- this.renderer.setStyle(this.imgElementRef.nativeElement, 'height', height);
2583
- this.renderer.setStyle(this.imgElementRef.nativeElement, 'width', width);
2584
- }
2585
2675
  if (element.aspect) {
2586
2676
  this.renderer.setStyle(this.imgElementRef.nativeElement, 'object-fit', aspectMapping[element.aspect]);
2587
2677
  }
@@ -2674,24 +2764,168 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
2674
2764
  }]
2675
2765
  }] });
2676
2766
 
2767
+ class ScrollSpyService {
2768
+ observeActiveId(options) {
2769
+ const container = this.resolveContainer(options.container);
2770
+ const anchorSelector = options.anchorSelector ?? '[data-anchor-target]';
2771
+ const throttleMs = options.throttleMs ?? 16;
2772
+ const debug = !!options.debug;
2773
+ const scrollTarget = this.isPageContainer(container) ? window : container;
2774
+ const getOffsetTop = options.getOffsetTop ?? (() => 0);
2775
+ const resolveId = options.resolveId ??
2776
+ ((anchorEl) => anchorEl.closest('[id]')?.id ?? null);
2777
+ return fromEvent(scrollTarget, 'scroll', { passive: true }).pipe(auditTime(throttleMs), startWith(null), tap(() => {
2778
+ if (debug)
2779
+ console.log('[ScrollSpy] event', { scrollTop: container.scrollTop });
2780
+ }), map$1(() => {
2781
+ const anchors = Array.from(container.querySelectorAll(anchorSelector));
2782
+ if (debug)
2783
+ console.log('[ScrollSpy] anchors found', anchors.length);
2784
+ if (!anchors.length)
2785
+ return null;
2786
+ const offsetTop = getOffsetTop({ container });
2787
+ const isPage = this.isPageContainer(container);
2788
+ const containerRect = isPage
2789
+ ? { top: 0, bottom: window.innerHeight }
2790
+ : container.getBoundingClientRect();
2791
+ const topLine = offsetTop;
2792
+ let bestAnchor = null;
2793
+ let bestScore = Number.POSITIVE_INFINITY;
2794
+ for (const a of anchors) {
2795
+ const r = a.getBoundingClientRect();
2796
+ const isVisible = r.bottom > containerRect.top + offsetTop &&
2797
+ r.top < containerRect.bottom;
2798
+ if (!isVisible)
2799
+ continue;
2800
+ const dist = r.top - topLine; // 0 = colado no topo útil
2801
+ // Prefer anchors próximos do topo útil; leve preferência para quem já passou do topo.
2802
+ const score = Math.abs(dist) + (dist > 0 ? 10 : 0);
2803
+ if (debug) {
2804
+ console.log('[ScrollSpy] anchor candidate', {
2805
+ id: a.id || a.closest('[id]')?.id,
2806
+ top: r.top,
2807
+ bottom: r.bottom,
2808
+ dist,
2809
+ score,
2810
+ visible: isVisible,
2811
+ });
2812
+ }
2813
+ if (score < bestScore) {
2814
+ bestScore = score;
2815
+ bestAnchor = a;
2816
+ }
2817
+ }
2818
+ if (!bestAnchor) {
2819
+ if (debug)
2820
+ console.log('[ScrollSpy] no visible anchors, returning null');
2821
+ return null;
2822
+ }
2823
+ const resolved = resolveId(bestAnchor);
2824
+ if (debug)
2825
+ console.log('[ScrollSpy] resolved active id', resolved, 'from', bestAnchor);
2826
+ return resolved;
2827
+ }), distinctUntilChanged());
2828
+ }
2829
+ /** Ajuda: encontra o scroll parent real de um elemento */
2830
+ getScrollParent(el) {
2831
+ let parent = el.parentElement;
2832
+ while (parent) {
2833
+ const style = getComputedStyle(parent);
2834
+ const overflowY = style.overflowY;
2835
+ const canScroll = (overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay') &&
2836
+ parent.scrollHeight > parent.clientHeight;
2837
+ if (canScroll)
2838
+ return parent;
2839
+ parent = parent.parentElement;
2840
+ }
2841
+ return document.scrollingElement || document.documentElement;
2842
+ }
2843
+ isPageContainer(container) {
2844
+ return (container === document.documentElement ||
2845
+ container === document.body ||
2846
+ container === document.scrollingElement);
2847
+ }
2848
+ resolveContainer(container) {
2849
+ if (typeof container !== 'string')
2850
+ return container;
2851
+ const found = document.querySelector(container);
2852
+ if (!found) {
2853
+ throw new Error(`[ScrollSpyService] Container não encontrado: ${container}`);
2854
+ }
2855
+ return found;
2856
+ }
2857
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ScrollSpyService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2858
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ScrollSpyService, providedIn: 'root' }); }
2859
+ }
2860
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ScrollSpyService, decorators: [{
2861
+ type: Injectable,
2862
+ args: [{ providedIn: 'root' }]
2863
+ }] });
2864
+
2677
2865
  class TagComponent {
2678
- constructor(uiComponent, renderer, fontSizeMappingService) {
2866
+ static { this.scrollSpyInitialized = false; }
2867
+ static { this.scrollSpy$ = null; }
2868
+ static { this.scrollSpySub = null; }
2869
+ static { this.scrollSpyInitTries = 0; }
2870
+ static { this.scrollSpyContainer = null; }
2871
+ static { this.activeId = null; }
2872
+ constructor(uiComponent, renderer, fontSizeMappingService, scrollSpy) {
2679
2873
  this.uiComponent = uiComponent;
2680
2874
  this.renderer = renderer;
2681
2875
  this.fontSizeMappingService = fontSizeMappingService;
2876
+ this.scrollSpy = scrollSpy;
2877
+ this.destroy$ = new Subject();
2682
2878
  }
2683
2879
  ngOnInit() {
2684
2880
  }
2685
2881
  ngAfterViewInit() {
2686
2882
  if (this.uiComponent.element) {
2687
2883
  this.applyElement(this.uiComponent.element);
2688
- }
2689
- if (this.uiComponent.element) {
2690
2884
  this.applyLabelElement(this.uiComponent.element);
2885
+ // Map: tag.action.param -> section div id
2886
+ const actionParam = this.uiComponent?.element?.action?.param;
2887
+ if (actionParam != null && this.tagElementRef?.nativeElement) {
2888
+ this.renderer.setAttribute(this.tagElementRef.nativeElement, 'data-tag', String(actionParam));
2889
+ }
2890
+ else {
2891
+ console.warn('[TagComponent] tag without action.param', this.uiComponent?.element);
2892
+ }
2893
+ // Reaplica seleção se este tag corresponde ao ativo atual.
2894
+ this.syncSelectionState();
2895
+ // IMPORTANT: TagComponent renders once per tag.
2896
+ // We initialize the scroll observer only once, but we MUST NOT tie it to the first instance lifecycle,
2897
+ // because the first instance may be destroyed (e.g. rerender) and the subscription would die.
2898
+ this.initScrollSpyOnce();
2691
2899
  }
2692
2900
  }
2693
2901
  applyElement(element) {
2694
2902
  }
2903
+ markSelectedTag(id) {
2904
+ const tags = Array.from(document.querySelectorAll('.tag'));
2905
+ const dataTags = tags.map(t => t.getAttribute('data-tag'));
2906
+ console.log('[TagComponent] markSelectedTag', { id, dataTags });
2907
+ TagComponent.activeId = id;
2908
+ for (const t of tags)
2909
+ t.classList.remove('tag--selected');
2910
+ const active = document.querySelector(`.tag[data-tag="${CSS.escape(id)}"]`);
2911
+ if (!active) {
2912
+ console.warn('[TagComponent] active tag not found for id', id);
2913
+ return;
2914
+ }
2915
+ active.classList.add('tag--selected');
2916
+ console.log('[TagComponent] tag--selected applied to', active);
2917
+ }
2918
+ syncSelectionState() {
2919
+ const dataTag = this.tagElementRef?.nativeElement?.getAttribute('data-tag');
2920
+ if (!dataTag)
2921
+ return;
2922
+ if (TagComponent.activeId && TagComponent.activeId === dataTag) {
2923
+ this.tagElementRef.nativeElement.classList.add('tag--selected');
2924
+ }
2925
+ else {
2926
+ this.tagElementRef.nativeElement.classList.remove('tag--selected');
2927
+ }
2928
+ }
2695
2929
  applyLabelElement(element) {
2696
2930
  if (element.textColor) {
2697
2931
  const color = colorMapping[element.textColor];
@@ -2706,16 +2940,94 @@ class TagComponent {
2706
2940
  }
2707
2941
  this.renderer.setStyle(this.tagElementRef.nativeElement, 'height', sizeMappingHeight[UISize.ASSET_8]);
2708
2942
  }
2709
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TagComponent, deps: [{ token: 'uiComponent' }, { token: i0.Renderer2 }, { token: FontSizeMappingService }], target: i0.ɵɵFactoryTarget.Component }); }
2710
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: TagComponent, isStandalone: false, selector: "edm-sdui-tag", viewQueries: [{ propertyName: "tagElementRef", first: true, predicate: ["tagElement"], descendants: true }, { propertyName: "tagNameElementRef", first: true, predicate: ["tagNameElement"], descendants: true }], ngImport: i0, template: "<div class=\"tag\" #tagElement *ngIf=\"uiComponent\" [edmSduiView]=\"uiComponent.element\">\n <span class=\"tag-name\" #tagNameElement>{{ uiComponent.element?.label ?? '' }}</span>\n</div>", styles: [":host{display:contents}.tag{padding:4px 8px;display:flex;align-items:center}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: UIViewDirective, selector: "[edmSduiView]", inputs: ["edmSduiView", "disableClick"] }] }); }
2943
+ initScrollSpyOnce() {
2944
+ // Already subscribed
2945
+ if (TagComponent.scrollSpySub) {
2946
+ const currentContainer = this.resolveScrollContainer();
2947
+ const stale = !TagComponent.scrollSpyContainer?.isConnected || (currentContainer && TagComponent.scrollSpyContainer !== currentContainer);
2948
+ if (!stale)
2949
+ return;
2950
+ try {
2951
+ TagComponent.scrollSpySub.unsubscribe();
2952
+ }
2953
+ catch { }
2954
+ TagComponent.scrollSpySub = null;
2955
+ TagComponent.scrollSpy$ = null;
2956
+ TagComponent.scrollSpyContainer = null;
2957
+ TagComponent.scrollSpyInitialized = false;
2958
+ }
2959
+ // Ensure container exists; TagComponent can render before the scroll container is in the DOM.
2960
+ const containerExists = !!this.resolveScrollContainer();
2961
+ if (!containerExists) {
2962
+ TagComponent.scrollSpyInitTries++;
2963
+ if (TagComponent.scrollSpyInitTries <= 30) {
2964
+ requestAnimationFrame(() => this.initScrollSpyOnce());
2965
+ }
2966
+ else {
2967
+ console.warn('[TagComponent] ScrollSpy: .scrollable-container not found after retries');
2968
+ }
2969
+ return;
2970
+ }
2971
+ try {
2972
+ TagComponent.scrollSpyInitialized = true;
2973
+ const currentContainer = this.resolveScrollContainer();
2974
+ TagComponent.scrollSpy$ = this.scrollSpy.observeActiveId({
2975
+ container: currentContainer,
2976
+ anchorSelector: '[data-anchor-target], .column[id]',
2977
+ getOffsetTop: () => (document.querySelector('.tags-row--can-fix') ? 140 : 180),
2978
+ resolveId: (anchor) => {
2979
+ const section = anchor.closest('[data-anchor-target]');
2980
+ if (section?.id)
2981
+ return section.id;
2982
+ if (anchor.id)
2983
+ return anchor.id;
2984
+ return anchor.closest('[id]')?.id || null;
2985
+ },
2986
+ debug: false,
2987
+ });
2988
+ TagComponent.scrollSpyContainer = currentContainer;
2989
+ TagComponent.scrollSpySub = TagComponent.scrollSpy$.subscribe({
2990
+ next: (activeId) => {
2991
+ console.log('[TagComponent] ScrollSpy next', activeId);
2992
+ if (!activeId)
2993
+ return;
2994
+ this.markSelectedTag(activeId);
2995
+ },
2996
+ error: (err) => {
2997
+ console.error('[TagComponent] ScrollSpy subscription error', err);
2998
+ },
2999
+ });
3000
+ }
3001
+ catch (e) {
3002
+ console.error('[TagComponent] ScrollSpy init failed', e);
3003
+ }
3004
+ }
3005
+ resolveScrollContainer() {
3006
+ const explicit = document.querySelector('.scrollable-container');
3007
+ if (explicit && explicit.scrollHeight > explicit.clientHeight) {
3008
+ return explicit;
3009
+ }
3010
+ const anchorSample = document.querySelector('.column[id]') ||
3011
+ document.querySelector('[data-anchor-target]');
3012
+ if (anchorSample) {
3013
+ return this.scrollSpy.getScrollParent(anchorSample);
3014
+ }
3015
+ return document.scrollingElement || document.documentElement;
3016
+ }
3017
+ ngOnDestroy() {
3018
+ this.destroy$.next();
3019
+ this.destroy$.complete();
3020
+ }
3021
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TagComponent, deps: [{ token: 'uiComponent' }, { token: i0.Renderer2 }, { token: FontSizeMappingService }, { token: ScrollSpyService }], target: i0.ɵɵFactoryTarget.Component }); }
3022
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: TagComponent, isStandalone: false, selector: "edm-sdui-tag", viewQueries: [{ propertyName: "tagElementRef", first: true, predicate: ["tagElement"], descendants: true }, { propertyName: "tagNameElementRef", first: true, predicate: ["tagNameElement"], descendants: true }], ngImport: i0, template: "<div class=\"tag\" #tagElement *ngIf=\"uiComponent\" [edmSduiView]=\"uiComponent.element\">\n <span class=\"tag-name\" #tagNameElement>{{ uiComponent.element?.label ?? '' }}</span>\n</div>\n", styles: [":host{display:contents}.tag{display:inline-flex;align-items:center;gap:8px;padding:14px 16px;border:.5px solid var(--tag-explorer-aux);cursor:pointer;font-size:16px}.tag--square{border-radius:4px}.tag--rounded{border-radius:999px}.tag--selected{border-color:var(--tag-explorer-highlight);background-color:var(--bt-tag-explorer-on);background-origin:border-box}.tag-name{font-weight:600;color:var(--font-bt-tag-explorer-on);font-size:15px;line-height:17.25px}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: UIViewDirective, selector: "[edmSduiView]", inputs: ["edmSduiView", "disableClick"] }] }); }
2711
3023
  }
2712
3024
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TagComponent, decorators: [{
2713
3025
  type: Component,
2714
- args: [{ standalone: false, selector: 'edm-sdui-tag', template: "<div class=\"tag\" #tagElement *ngIf=\"uiComponent\" [edmSduiView]=\"uiComponent.element\">\n <span class=\"tag-name\" #tagNameElement>{{ uiComponent.element?.label ?? '' }}</span>\n</div>", styles: [":host{display:contents}.tag{padding:4px 8px;display:flex;align-items:center}\n"] }]
3026
+ args: [{ standalone: false, selector: 'edm-sdui-tag', template: "<div class=\"tag\" #tagElement *ngIf=\"uiComponent\" [edmSduiView]=\"uiComponent.element\">\n <span class=\"tag-name\" #tagNameElement>{{ uiComponent.element?.label ?? '' }}</span>\n</div>\n", styles: [":host{display:contents}.tag{display:inline-flex;align-items:center;gap:8px;padding:14px 16px;border:.5px solid var(--tag-explorer-aux);cursor:pointer;font-size:16px}.tag--square{border-radius:4px}.tag--rounded{border-radius:999px}.tag--selected{border-color:var(--tag-explorer-highlight);background-color:var(--bt-tag-explorer-on);background-origin:border-box}.tag-name{font-weight:600;color:var(--font-bt-tag-explorer-on);font-size:15px;line-height:17.25px}\n"] }]
2715
3027
  }], ctorParameters: () => [{ type: undefined, decorators: [{
2716
3028
  type: Inject,
2717
3029
  args: ['uiComponent']
2718
- }] }, { type: i0.Renderer2 }, { type: FontSizeMappingService }], propDecorators: { tagElementRef: [{
3030
+ }] }, { type: i0.Renderer2 }, { type: FontSizeMappingService }, { type: ScrollSpyService }], propDecorators: { tagElementRef: [{
2719
3031
  type: ViewChild,
2720
3032
  args: ['tagElement']
2721
3033
  }], tagNameElementRef: [{
@@ -3419,6 +3731,89 @@ var progressBar_component = /*#__PURE__*/Object.freeze({
3419
3731
  ProgressBarComponent: ProgressBarComponent
3420
3732
  });
3421
3733
 
3734
+ class TagsRowComponent {
3735
+ constructor(uiComponent, injector, hostRef, cdr) {
3736
+ this.uiComponent = uiComponent;
3737
+ this.injector = injector;
3738
+ this.hostRef = hostRef;
3739
+ this.cdr = cdr;
3740
+ this.isFixed = false;
3741
+ this.canFix = false;
3742
+ this.tagComponent = TagComponent;
3743
+ }
3744
+ get tags() {
3745
+ return this.uiComponent.tags ?? [];
3746
+ }
3747
+ trackByLabel(index, tag) {
3748
+ return tag.label ?? index;
3749
+ }
3750
+ createInjector(tag) {
3751
+ const component = {
3752
+ type: UIComponentType.TAG,
3753
+ element: tag,
3754
+ };
3755
+ return Injector.create({
3756
+ providers: [{ provide: 'uiComponent', useValue: component }],
3757
+ parent: this.injector,
3758
+ });
3759
+ }
3760
+ ngAfterViewInit() {
3761
+ requestAnimationFrame(() => {
3762
+ this.updateFixedState();
3763
+ this.cdr.detectChanges();
3764
+ });
3765
+ }
3766
+ onWindowScroll() {
3767
+ this.updateFixedState();
3768
+ }
3769
+ updateFixedState() {
3770
+ const offset = this.getStickyOffset();
3771
+ const rect = this.hostRef.nativeElement.getBoundingClientRect();
3772
+ if (!this.initialTop) {
3773
+ this.initialTop = rect.top + window.scrollY;
3774
+ }
3775
+ if (!this.hostMinHeight) {
3776
+ this.hostMinHeight = rect.height;
3777
+ }
3778
+ const shouldFix = window.scrollY + offset >= (this.initialTop ?? 0);
3779
+ this.canFix = shouldFix;
3780
+ this.isFixed = shouldFix;
3781
+ }
3782
+ getStickyOffset() {
3783
+ const variable = getComputedStyle(document.documentElement).getPropertyValue('--sdui-sticky-offset');
3784
+ const parsed = parseInt(variable || '', 10);
3785
+ if (!isNaN(parsed))
3786
+ return parsed;
3787
+ return 72; // fallback to navbar height
3788
+ }
3789
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TagsRowComponent, deps: [{ token: 'uiComponent' }, { token: i0.Injector }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
3790
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: TagsRowComponent, isStandalone: false, selector: "edm-sdui-tags-row", host: { listeners: { "window:scroll": "onWindowScroll()" }, properties: { "class.tags-row--fixed": "this.isFixed", "class.tags-row--can-fix": "this.canFix", "style.min-height.px": "this.hostMinHeight" } }, ngImport: i0, template: "<div class=\"tags-row\" [class.tags-row-fixed]=\"isFixed\" *ngIf=\"uiComponent\" [edmSduiView]=\"uiComponent.element\">\n <ng-container *ngFor=\"let tag of tags; trackBy: trackByLabel\">\n <ng-container\n *ngComponentOutlet=\"tagComponent; injector: createInjector(tag)\"\n ></ng-container>\n </ng-container>\n</div>\n", styles: [":host{display:block;width:100%;box-sizing:border-box;padding:0 var(--sdui-header-padding, 12px);margin-top:var(--sdui-header-margin-top, 12px)}.tags-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:6px 0;background-color:inherit;justify-content:flex-start;box-sizing:border-box;width:100%}:host.tags-row--fixed{position:fixed;top:53px;left:35px;right:0;z-index:120;box-sizing:border-box}:host.tags-row--fixed .tags-row{padding:6px 0}.tags-row-fixed{width:100%;height:60px}:host.tags-row--can-fix{background:var(--bg);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);box-shadow:0 4px 16px #0003}\n"], dependencies: [{ kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: UIViewDirective, selector: "[edmSduiView]", inputs: ["edmSduiView", "disableClick"] }] }); }
3791
+ }
3792
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TagsRowComponent, decorators: [{
3793
+ type: Component,
3794
+ args: [{ selector: 'edm-sdui-tags-row', standalone: false, template: "<div class=\"tags-row\" [class.tags-row-fixed]=\"isFixed\" *ngIf=\"uiComponent\" [edmSduiView]=\"uiComponent.element\">\n <ng-container *ngFor=\"let tag of tags; trackBy: trackByLabel\">\n <ng-container\n *ngComponentOutlet=\"tagComponent; injector: createInjector(tag)\"\n ></ng-container>\n </ng-container>\n</div>\n", styles: [":host{display:block;width:100%;box-sizing:border-box;padding:0 var(--sdui-header-padding, 12px);margin-top:var(--sdui-header-margin-top, 12px)}.tags-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:6px 0;background-color:inherit;justify-content:flex-start;box-sizing:border-box;width:100%}:host.tags-row--fixed{position:fixed;top:53px;left:35px;right:0;z-index:120;box-sizing:border-box}:host.tags-row--fixed .tags-row{padding:6px 0}.tags-row-fixed{width:100%;height:60px}:host.tags-row--can-fix{background:var(--bg);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);box-shadow:0 4px 16px #0003}\n"] }]
3795
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
3796
+ type: Inject,
3797
+ args: ['uiComponent']
3798
+ }] }, { type: i0.Injector }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { isFixed: [{
3799
+ type: HostBinding,
3800
+ args: ['class.tags-row--fixed']
3801
+ }], canFix: [{
3802
+ type: HostBinding,
3803
+ args: ['class.tags-row--can-fix']
3804
+ }], hostMinHeight: [{
3805
+ type: HostBinding,
3806
+ args: ['style.min-height.px']
3807
+ }], onWindowScroll: [{
3808
+ type: HostListener,
3809
+ args: ['window:scroll']
3810
+ }] } });
3811
+
3812
+ var tagsRow_component = /*#__PURE__*/Object.freeze({
3813
+ __proto__: null,
3814
+ TagsRowComponent: TagsRowComponent
3815
+ });
3816
+
3422
3817
  class SduiModule {
3423
3818
  static forRoot(config) {
3424
3819
  return {
@@ -3458,6 +3853,7 @@ class SduiModule {
3458
3853
  ButtonComponent,
3459
3854
  ImageComponent,
3460
3855
  TagComponent,
3856
+ TagsRowComponent,
3461
3857
  SearchBarComponent,
3462
3858
  SearchBarDismissComponent,
3463
3859
  MediaTypeComponent,
@@ -3497,6 +3893,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
3497
3893
  ButtonComponent,
3498
3894
  ImageComponent,
3499
3895
  TagComponent,
3896
+ TagsRowComponent,
3500
3897
  SearchBarComponent,
3501
3898
  SearchBarDismissComponent,
3502
3899
  MediaTypeComponent,