@sapudex/web-components 0.114.2 → 0.117.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/bundle.esm.js +3 -0
  2. package/dist/Avatar.d.ts +8 -1
  3. package/dist/Avatar.js +5 -2
  4. package/dist/Avatar.js.map +1 -1
  5. package/dist/CountrySelector.d.ts +1 -0
  6. package/dist/CountrySelector.js +3 -0
  7. package/dist/CountrySelector.js.map +1 -1
  8. package/dist/FilterMenu.d.ts +14 -4
  9. package/dist/FilterMenu.js +46 -7
  10. package/dist/FilterMenu.js.map +1 -1
  11. package/dist/InputGroup.js.map +1 -1
  12. package/dist/List.d.ts +7 -0
  13. package/dist/List.js +78 -18
  14. package/dist/List.js.map +1 -1
  15. package/dist/ListItem.d.ts +0 -1
  16. package/dist/ListItem.js +0 -6
  17. package/dist/ListItem.js.map +1 -1
  18. package/dist/ListItemBase.d.ts +3 -0
  19. package/dist/ListItemBase.js +12 -0
  20. package/dist/ListItemBase.js.map +1 -1
  21. package/dist/PhoneNumberField.js.map +1 -1
  22. package/dist/Search.d.ts +3 -0
  23. package/dist/Search.js +35 -10
  24. package/dist/Search.js.map +1 -1
  25. package/dist/SecondaryNavigation.d.ts +34 -46
  26. package/dist/SecondaryNavigation.js +140 -161
  27. package/dist/SecondaryNavigation.js.map +1 -1
  28. package/dist/SecondaryNavigationItem.d.ts +101 -0
  29. package/dist/SecondaryNavigationItem.js +287 -0
  30. package/dist/SecondaryNavigationItem.js.map +1 -0
  31. package/dist/SecondaryNavigationItemBase.d.ts +68 -0
  32. package/dist/SecondaryNavigationItemBase.js +78 -0
  33. package/dist/SecondaryNavigationItemBase.js.map +1 -0
  34. package/dist/SecondaryNavigationSubItem.d.ts +52 -0
  35. package/dist/SecondaryNavigationSubItem.js +102 -0
  36. package/dist/SecondaryNavigationSubItem.js.map +1 -0
  37. package/dist/SelectBox.d.ts +1 -0
  38. package/dist/SelectBox.js +13 -1
  39. package/dist/SelectBox.js.map +1 -1
  40. package/dist/StatusBadge.d.ts +67 -0
  41. package/dist/StatusBadge.js +104 -0
  42. package/dist/StatusBadge.js.map +1 -0
  43. package/dist/Tab.js +1 -1
  44. package/dist/Tab.js.map +1 -1
  45. package/dist/assets/{bundle.esm-ab45813e.js → bundle.esm-f65ae7da.js} +187 -184
  46. package/dist/assets/messagebundle_en-7249941b.js +1 -0
  47. package/dist/css/themes/Avatar.css +1 -1
  48. package/dist/css/themes/Checkbox.css +1 -1
  49. package/dist/css/themes/CountrySelector.css +1 -1
  50. package/dist/css/themes/Dropdown.css +1 -1
  51. package/dist/css/themes/FilterMenu.css +1 -1
  52. package/dist/css/themes/HeroBanner.css +1 -1
  53. package/dist/css/themes/MediaPlayer.css +1 -1
  54. package/dist/css/themes/PhoneNumberField.css +1 -1
  55. package/dist/css/themes/RatingIndicator.css +1 -1
  56. package/dist/css/themes/Search.css +1 -1
  57. package/dist/css/themes/SecondaryNavigation.css +1 -1
  58. package/dist/css/themes/SecondaryNavigationItem.css +1 -0
  59. package/dist/css/themes/SecondaryNavigationSubItem.css +1 -0
  60. package/dist/css/themes/Slider.css +1 -1
  61. package/dist/css/themes/StatusBadge.css +1 -0
  62. package/dist/custom-elements-internal.json +604 -2
  63. package/dist/custom-elements.json +574 -2
  64. package/dist/generated/assets/i18n/messagebundle_en.json +1 -1
  65. package/dist/generated/i18n/i18n-defaults.d.ts +8 -1
  66. package/dist/generated/i18n/i18n-defaults.js +8 -1
  67. package/dist/generated/i18n/i18n-defaults.js.map +1 -1
  68. package/dist/generated/templates/CountrySelectorTemplate.lit.js +1 -1
  69. package/dist/generated/templates/CountrySelectorTemplate.lit.js.map +1 -1
  70. package/dist/generated/templates/DropdownTemplate.lit.js +1 -1
  71. package/dist/generated/templates/DropdownTemplate.lit.js.map +1 -1
  72. package/dist/generated/templates/FilterMenuTemplate.lit.js +3 -3
  73. package/dist/generated/templates/FilterMenuTemplate.lit.js.map +1 -1
  74. package/dist/generated/templates/HeroBannerTemplate.lit.js +2 -2
  75. package/dist/generated/templates/HeroBannerTemplate.lit.js.map +1 -1
  76. package/dist/generated/templates/ListGroupHeaderTemplate.lit.js +4 -4
  77. package/dist/generated/templates/ListGroupHeaderTemplate.lit.js.map +1 -1
  78. package/dist/generated/templates/ListItemTemplate.lit.js +1 -1
  79. package/dist/generated/templates/ListItemTemplate.lit.js.map +1 -1
  80. package/dist/generated/templates/ListSelectAllTemplate.lit.js +1 -1
  81. package/dist/generated/templates/ListSelectAllTemplate.lit.js.map +1 -1
  82. package/dist/generated/templates/SearchSuggestionsTemplate.lit.js +1 -1
  83. package/dist/generated/templates/SearchSuggestionsTemplate.lit.js.map +1 -1
  84. package/dist/generated/templates/SearchTemplate.lit.js +2 -2
  85. package/dist/generated/templates/SearchTemplate.lit.js.map +1 -1
  86. package/dist/generated/templates/SearchableListBaseTemplate.lit.js +2 -2
  87. package/dist/generated/templates/SearchableListBaseTemplate.lit.js.map +1 -1
  88. package/dist/generated/templates/SecondaryNavigationItemTemplate.lit.d.ts +4 -0
  89. package/dist/generated/templates/SecondaryNavigationItemTemplate.lit.js +11 -0
  90. package/dist/generated/templates/SecondaryNavigationItemTemplate.lit.js.map +1 -0
  91. package/dist/generated/templates/SecondaryNavigationSubItemTemplate.lit.d.ts +4 -0
  92. package/dist/generated/templates/SecondaryNavigationSubItemTemplate.lit.js +9 -0
  93. package/dist/generated/templates/SecondaryNavigationSubItemTemplate.lit.js.map +1 -0
  94. package/dist/generated/templates/SecondaryNavigationTemplate.lit.js +7 -10
  95. package/dist/generated/templates/SecondaryNavigationTemplate.lit.js.map +1 -1
  96. package/dist/generated/templates/SelectBoxTemplate.lit.js +1 -1
  97. package/dist/generated/templates/SelectBoxTemplate.lit.js.map +1 -1
  98. package/dist/generated/templates/StatusBadgeTemplate.lit.d.ts +4 -0
  99. package/dist/generated/templates/StatusBadgeTemplate.lit.js +5 -0
  100. package/dist/generated/templates/StatusBadgeTemplate.lit.js.map +1 -0
  101. package/dist/generated/themes/Avatar.css.js +1 -1
  102. package/dist/generated/themes/Avatar.css.js.map +1 -1
  103. package/dist/generated/themes/Checkbox.css.js +1 -1
  104. package/dist/generated/themes/Checkbox.css.js.map +1 -1
  105. package/dist/generated/themes/CountrySelector.css.js +1 -1
  106. package/dist/generated/themes/CountrySelector.css.js.map +1 -1
  107. package/dist/generated/themes/Dropdown.css.js +1 -1
  108. package/dist/generated/themes/Dropdown.css.js.map +1 -1
  109. package/dist/generated/themes/FilterMenu.css.js +1 -1
  110. package/dist/generated/themes/FilterMenu.css.js.map +1 -1
  111. package/dist/generated/themes/HeroBanner.css.js +1 -1
  112. package/dist/generated/themes/HeroBanner.css.js.map +1 -1
  113. package/dist/generated/themes/MediaPlayer.css.js +1 -1
  114. package/dist/generated/themes/MediaPlayer.css.js.map +1 -1
  115. package/dist/generated/themes/PhoneNumberField.css.js +1 -1
  116. package/dist/generated/themes/PhoneNumberField.css.js.map +1 -1
  117. package/dist/generated/themes/RatingIndicator.css.js +1 -1
  118. package/dist/generated/themes/RatingIndicator.css.js.map +1 -1
  119. package/dist/generated/themes/Search.css.js +1 -1
  120. package/dist/generated/themes/Search.css.js.map +1 -1
  121. package/dist/generated/themes/SecondaryNavigation.css.js +1 -1
  122. package/dist/generated/themes/SecondaryNavigation.css.js.map +1 -1
  123. package/dist/generated/themes/SecondaryNavigationItem.css.d.ts +3 -0
  124. package/dist/generated/themes/SecondaryNavigationItem.css.js +9 -0
  125. package/dist/generated/themes/SecondaryNavigationItem.css.js.map +1 -0
  126. package/dist/generated/themes/SecondaryNavigationSubItem.css.d.ts +3 -0
  127. package/dist/generated/themes/SecondaryNavigationSubItem.css.js +9 -0
  128. package/dist/generated/themes/SecondaryNavigationSubItem.css.js.map +1 -0
  129. package/dist/generated/themes/Slider.css.js +1 -1
  130. package/dist/generated/themes/Slider.css.js.map +1 -1
  131. package/dist/generated/themes/StatusBadge.css.d.ts +3 -0
  132. package/dist/generated/themes/StatusBadge.css.js +9 -0
  133. package/dist/generated/themes/StatusBadge.css.js.map +1 -0
  134. package/dist/i18n/messagebundle.properties +12 -1
  135. package/dist/i18n/messagebundle_en.properties +8 -1
  136. package/dist/vscode.html-custom-data.json +131 -3
  137. package/dist/web-types.json +203 -5
  138. package/package.json +1 -1
  139. package/src/Avatar.ts +12 -3
  140. package/src/CountrySelector.hbs +2 -1
  141. package/src/CountrySelector.ts +4 -1
  142. package/src/Dropdown.hbs +0 -1
  143. package/src/FilterMenu.hbs +5 -1
  144. package/src/FilterMenu.ts +60 -10
  145. package/src/HeroBanner.hbs +24 -21
  146. package/src/InputGroup.ts +6 -5
  147. package/src/List.ts +92 -21
  148. package/src/ListGroupHeader.hbs +9 -5
  149. package/src/ListItem.hbs +2 -1
  150. package/src/ListItem.ts +0 -7
  151. package/src/ListItemBase.ts +14 -0
  152. package/src/ListSelectAll.hbs +1 -0
  153. package/src/PhoneNumberField.ts +1 -1
  154. package/src/Search.hbs +3 -2
  155. package/src/Search.ts +37 -10
  156. package/src/SearchSuggestions.hbs +1 -1
  157. package/src/SearchableListBase.hbs +2 -0
  158. package/src/SecondaryNavigation.hbs +50 -72
  159. package/src/SecondaryNavigation.ts +171 -195
  160. package/src/SecondaryNavigationItem.hbs +63 -0
  161. package/src/SecondaryNavigationItem.ts +358 -0
  162. package/src/SecondaryNavigationItemBase.ts +115 -0
  163. package/src/SecondaryNavigationSubItem.hbs +41 -0
  164. package/src/SecondaryNavigationSubItem.ts +123 -0
  165. package/src/SelectBox.hbs +1 -0
  166. package/src/SelectBox.ts +16 -1
  167. package/src/StatusBadge.hbs +9 -0
  168. package/src/StatusBadge.ts +129 -0
  169. package/src/Tab.ts +1 -1
  170. package/src/generated/i18n/i18n-defaults.ts +2 -2
  171. package/src/generated/templates/CountrySelectorTemplate.lit.ts +1 -1
  172. package/src/generated/templates/DropdownTemplate.lit.ts +1 -1
  173. package/src/generated/templates/FilterMenuTemplate.lit.ts +3 -3
  174. package/src/generated/templates/HeroBannerTemplate.lit.ts +2 -2
  175. package/src/generated/templates/ListGroupHeaderTemplate.lit.ts +4 -4
  176. package/src/generated/templates/ListItemTemplate.lit.ts +1 -1
  177. package/src/generated/templates/ListSelectAllTemplate.lit.ts +1 -1
  178. package/src/generated/templates/SearchSuggestionsTemplate.lit.ts +1 -1
  179. package/src/generated/templates/SearchTemplate.lit.ts +2 -2
  180. package/src/generated/templates/SearchableListBaseTemplate.lit.ts +2 -2
  181. package/src/generated/templates/SecondaryNavigationItemTemplate.lit.ts +16 -0
  182. package/src/generated/templates/SecondaryNavigationSubItemTemplate.lit.ts +14 -0
  183. package/src/generated/templates/SecondaryNavigationTemplate.lit.ts +7 -10
  184. package/src/generated/templates/SelectBoxTemplate.lit.ts +1 -1
  185. package/src/generated/templates/StatusBadgeTemplate.lit.ts +10 -0
  186. package/src/generated/themes/Avatar.css.ts +1 -1
  187. package/src/generated/themes/Checkbox.css.ts +1 -1
  188. package/src/generated/themes/CountrySelector.css.ts +1 -1
  189. package/src/generated/themes/Dropdown.css.ts +1 -1
  190. package/src/generated/themes/FilterMenu.css.ts +1 -1
  191. package/src/generated/themes/HeroBanner.css.ts +1 -1
  192. package/src/generated/themes/MediaPlayer.css.ts +1 -1
  193. package/src/generated/themes/PhoneNumberField.css.ts +1 -1
  194. package/src/generated/themes/RatingIndicator.css.ts +1 -1
  195. package/src/generated/themes/Search.css.ts +1 -1
  196. package/src/generated/themes/SecondaryNavigation.css.ts +1 -1
  197. package/src/generated/themes/SecondaryNavigationItem.css.ts +13 -0
  198. package/src/generated/themes/SecondaryNavigationSubItem.css.ts +13 -0
  199. package/src/generated/themes/Slider.css.ts +1 -1
  200. package/src/generated/themes/StatusBadge.css.ts +13 -0
  201. package/src/i18n/messagebundle.properties +12 -1
  202. package/src/i18n/messagebundle_en.properties +8 -1
  203. package/src/themes/Avatar.css +20 -0
  204. package/src/themes/Checkbox.css +12 -0
  205. package/src/themes/CountrySelector.css +4 -0
  206. package/src/themes/Dropdown.css +2 -0
  207. package/src/themes/FilterMenu.css +10 -0
  208. package/src/themes/HeroBanner.css +42 -6
  209. package/src/themes/MediaPlayer.css +3 -2
  210. package/src/themes/PhoneNumberField.css +4 -0
  211. package/src/themes/Search.css +11 -7
  212. package/src/themes/SecondaryNavigation.css +44 -302
  213. package/src/themes/SecondaryNavigationItem.css +220 -0
  214. package/src/themes/SecondaryNavigationSubItem.css +118 -0
  215. package/src/themes/StatusBadge.css +135 -0
  216. package/dist/assets/messagebundle_en-26cd7a92.js +0 -1
@@ -6,17 +6,16 @@ import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
6
6
  import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
7
7
  import { isDesktop } from "@ui5/webcomponents-base/dist/Device.js";
8
8
  import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
9
- import UI5Icon from "@ui5/webcomponents/dist/Icon.js";
10
9
  import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
11
- import "@ui5/webcomponents-icons/dist/slim-arrow-down.js";
12
10
  import {
13
11
  isLeft,
14
12
  isRight,
15
- isUp,
16
- isDown,
17
13
  isEscape,
18
14
  } from "@ui5/webcomponents-base/dist/Keys.js";
19
15
  import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
16
+ import UDExSecondaryNavigationItem from "./SecondaryNavigationItem.js";
17
+ import UDExSecondaryNavigationSubItem from "./SecondaryNavigationSubItem.js";
18
+ import UDExSecondaryNavigationItemBase, { NavItem } from "./SecondaryNavigationItemBase.js";
20
19
  import { MORE } from "./generated/i18n/i18n-defaults.js";
21
20
 
22
21
  import SecondaryNavigationTemplate from "./generated/templates/SecondaryNavigationTemplate.lit.js";
@@ -24,29 +23,20 @@ import SecondaryNavigationTemplate from "./generated/templates/SecondaryNavigati
24
23
  // Styles
25
24
  import SecondaryNavigationCss from "./generated/themes/SecondaryNavigation.css.js";
26
25
 
27
- const mobileMenuActiveClass = "udex-secondary-navigation__root_open";
28
- const rootClass = "udex-secondary-navigation__root";
26
+ const canvasContentFont: string = "16px / 17.6px '72 Brand Variable'";
29
27
  const breakpointSizeS: number = 979;
30
28
 
31
- export enum Target {
32
- _blank = "_blank",
33
- _parent = "_parent",
34
- _self = "_self",
35
- _top = "_top",
36
- }
37
-
38
- export type NavItem = {
39
- path: string;
40
- mobileLinkTitle: string;
41
- target: Target;
42
- title: string;
43
- active?: boolean;
44
- }
45
-
46
29
  export type SecondaryNavigationItemClickDetail = {
47
30
  originalEvent: Event,
48
- clickedItem: HTMLElement;
31
+ clickedItem: UDExSecondaryNavigationItem;
49
32
  clickedIndex: number;
33
+ };
34
+
35
+ export type SecondaryNavigationSubItemClickDetail = {
36
+ originalEvent: Event,
37
+ clickedItem: {
38
+ items: Array<NavItem>
39
+ };
50
40
  }
51
41
 
52
42
  /**
@@ -71,7 +61,7 @@ export type SecondaryNavigationItemClickDetail = {
71
61
  renderer: litRender,
72
62
  styles: SecondaryNavigationCss,
73
63
  template: SecondaryNavigationTemplate,
74
- dependencies: [UI5Icon],
64
+ dependencies: [UDExSecondaryNavigationItem],
75
65
  })
76
66
 
77
67
  /**
@@ -94,6 +84,23 @@ export type SecondaryNavigationItemClickDetail = {
94
84
  },
95
85
  })
96
86
 
87
+ /**
88
+ * Fires when sub item is clicked
89
+ *
90
+ * @allowPreventDefault
91
+ * @public
92
+ */
93
+ @event<SecondaryNavigationSubItemClickDetail>("sub-item-click", {
94
+ detail: {
95
+ originalEvent: {
96
+ type: Event,
97
+ },
98
+ clickedItem: {
99
+ type: HTMLElement,
100
+ },
101
+ },
102
+ })
103
+
97
104
  class UDExSecondaryNavigation extends UI5Element {
98
105
  /**
99
106
  * Defines an aria label for the mobile menu opener
@@ -139,14 +146,23 @@ class UDExSecondaryNavigation extends UI5Element {
139
146
  @property()
140
147
  title!: string;
141
148
 
149
+ /**
150
+ * Defines the href of the title.
151
+ *
152
+ * @default ""
153
+ * @public
154
+ */
155
+ @property()
156
+ titleHref!: string;
157
+
142
158
  @property({ type: Boolean, noAttribute: true })
143
- _dropdownMoreIsOpen!: boolean;
159
+ _selectedMore!: boolean;
144
160
 
145
- @property({ type: HTMLElement, defaultValue: [], noAttribute: true })
161
+ @property({ type: Object, multiple: true, noAttribute: true })
146
162
  _overflowItems!: Array<NavItem>;
147
163
 
148
- @property({ type: HTMLElement, defaultValue: [], noAttribute: true })
149
- _navItems!: Array<NavItem>;
164
+ @property({ type: Object, multiple: true, noAttribute: true })
165
+ _visibleItems!: Array<NavItem>;
150
166
 
151
167
  @property({ type: Boolean, noAttribute: true })
152
168
  _requestRender = false;
@@ -154,10 +170,10 @@ class UDExSecondaryNavigation extends UI5Element {
154
170
  @property({ type: Boolean, noAttribute: true })
155
171
  _mobileBtnExpanded = false;
156
172
 
173
+ _navItems!: Array<NavItem>;
157
174
  _showMoreButton: boolean;
158
- _navigationList: Array<NavItem> | undefined;
159
- _dropdown!: HTMLElement | null | undefined;
160
175
  _rootHolder!: HTMLElement | null | undefined;
176
+ _clickedNavItem!: UDExSecondaryNavigationItem;
161
177
  _boundReflowItems: () => void;
162
178
 
163
179
  static i18nBundle: any;
@@ -177,28 +193,21 @@ class UDExSecondaryNavigation extends UI5Element {
177
193
  this.setAttribute("desktop", "");
178
194
  }
179
195
 
180
- if (this.isDesktopScreen) {
181
- this.reflowItems();
182
- }
183
-
184
- ResizeHandler.register(this.rootHolder, this._boundReflowItems);
196
+ ResizeHandler.register(this, this._boundReflowItems);
185
197
  }
186
198
 
187
199
  onExitDOM(): void {
188
- ResizeHandler.deregister(this.rootHolder, this._boundReflowItems);
200
+ ResizeHandler.deregister(this, this._boundReflowItems);
189
201
  }
190
202
 
191
203
  onInvalidation(changeInfo: ChangeInfo): void {
192
204
  if (changeInfo.name === "navItems") {
193
- this._navigationList = undefined;
194
205
  this.reflowItems();
195
206
  }
196
207
  }
197
208
 
198
209
  onAfterRendering(): void {
199
210
  this._rootHolder = this.rootHolder;
200
- this._dropdown = this.getDropdown();
201
-
202
211
  this.handleOutsideClick();
203
212
  }
204
213
 
@@ -207,173 +216,108 @@ class UDExSecondaryNavigation extends UI5Element {
207
216
  }
208
217
 
209
218
  reflowItems(): void {
210
- const availableWidth = this.rootHolder.offsetWidth - this.heading.offsetWidth - (this.optionalButtons?.offsetWidth || 0);
219
+ const availableWidth = this.rootHolder.offsetWidth - this.heading?.offsetWidth - (this.optionalButtons?.offsetWidth || 0);
211
220
  const moreButtonWidth = this.getMoreButtonWidth();
212
221
  const itemsGap = 20;
213
-
214
- const widths = this.navigationList.map(item => this.getItemWidth(item));
215
-
222
+ const widths = this.parsedItems.map(item => this.getItemWidth(item));
216
223
  const steps: Array<number> = [];
217
- widths.forEach((itemWidth, index) => {
224
+
225
+ widths?.forEach((itemWidth, index) => {
218
226
  steps.push((steps.at(-1) || 0) + itemWidth + (index && itemsGap));
219
227
  });
220
228
 
221
229
  if ((steps.at(-1) || 0) <= availableWidth) {
222
- this._navItems.splice(0, Infinity, ...this.navigationList);
230
+ this._visibleItems.splice(0, Infinity, ...this.parsedItems);
223
231
  this._showMoreButton = false;
224
232
  this.refreshRendering();
225
233
  return;
226
234
  }
227
235
 
228
- // @ts-ignore
229
- const lastVisibleIndex: number = steps.findLastIndex((size: number) => size < (availableWidth - moreButtonWidth - itemsGap));
230
- this._navItems.splice(0, Infinity, ...this.navigationList.slice(0, lastVisibleIndex + 1));
231
- this._overflowItems.splice(0, Infinity, ...this.navigationList.slice(lastVisibleIndex + 1));
232
- this._showMoreButton = true;
233
- this.refreshRendering();
234
- }
235
-
236
- handleKeyDown(e: KeyboardEvent) {
237
- e.stopPropagation();
238
- this.handleLeftArrow(e);
239
- this.handleRightArrow(e);
240
- this.handleEscapeKey(e);
241
- }
242
-
243
- handleEscapeKey(e: KeyboardEvent) {
244
- if (isEscape(e)) {
245
- if (!this.isDesktopScreen) {
246
- this._rootHolder?.classList.remove(mobileMenuActiveClass);
247
- this.getMobileButtonMenu().focus();
248
- } else {
249
- this.onCloseDropdown();
250
- this.getMoreButton().focus();
251
- }
236
+ if (this.parsedItems) {
237
+ // @ts-ignore
238
+ const lastVisibleIndex: number = steps.findLastIndex((size: number) => size < (availableWidth - moreButtonWidth - itemsGap));
239
+ this._visibleItems.splice(0, Infinity, ...this.parsedItems.slice(0, lastVisibleIndex + 1));
240
+ this._overflowItems.splice(0, Infinity, ...this.parsedItems.slice(lastVisibleIndex + 1));
241
+ this._showMoreButton = true;
242
+ this.refreshRendering();
252
243
  }
253
244
  }
254
245
 
255
- handleKeyDownDropdown(e: KeyboardEvent) {
246
+ handleKeyDown(e: KeyboardEvent): void {
256
247
  e.stopPropagation();
257
- this.handleUpArrow(e);
258
- this.handleDownArrow(e);
259
- this.handleEscapeKey(e);
260
- }
261
-
262
- handleLeftArrow(e: KeyboardEvent): void {
263
248
  if (isLeft(e)) {
264
249
  this.focusPrevNavItem(e);
265
250
  }
266
- }
267
-
268
- handleRightArrow(e: KeyboardEvent): void {
269
251
  if (isRight(e)) {
270
252
  this.focusNextNavItem(e);
271
253
  }
272
- }
273
-
274
- handleUpArrow(e: KeyboardEvent): void {
275
- if (isUp(e)) {
276
- this.focusPrevNavItem(e);
277
- }
278
- }
279
-
280
- handleDownArrow(e: KeyboardEvent): void {
281
- if (isDown(e)) {
282
- this.focusNextNavItem(e);
254
+ if (isEscape(e)) {
255
+ (e.target as UDExSecondaryNavigationItem).closeDropdown();
283
256
  }
284
257
  }
285
258
 
286
- handleOutsideClick(): void {
287
- document.addEventListener("click", () => {
288
- if (this._dropdown) {
289
- this.onCloseDropdown();
290
- }
291
- });
292
- }
293
-
294
- handleMobileOpen(): void {
295
- this.toggleActiveClass();
296
- this._mobileBtnExpanded = !this._mobileBtnExpanded;
297
- }
298
-
299
- handleToggleDropdown(): void {
300
- this._dropdownMoreIsOpen = !this._dropdownMoreIsOpen;
301
- }
302
-
303
- toggleActiveClass() {
304
- this._rootHolder?.classList.toggle(mobileMenuActiveClass);
305
- }
306
-
307
259
  focusPrevNavItem(e: KeyboardEvent): void {
308
- const el = e.target as HTMLElement;
309
- const currentItem = el.parentElement as HTMLElement;
310
- const currentSelectedIndex = this.getCurrentIndex(currentItem);
311
- const lastItemIndex = this.navigationItems.length - 1;
260
+ const item = e.target as UDExSecondaryNavigationItem;
261
+ const currentSelectedIndex = this.getCurrentIndex(item);
262
+ const lastItemIndex = this.domNavItems.length - 1;
312
263
  const previousSelectIndex = currentSelectedIndex - 1 < 0 ? lastItemIndex : currentSelectedIndex - 1;
313
- const listItem = this.getListItemByIndex(previousSelectIndex);
314
- listItem?.focus();
264
+ this.domNavItems[previousSelectIndex]?.focus();
315
265
  }
316
266
 
317
267
  focusNextNavItem(e: KeyboardEvent): void {
318
- const el = e.target as HTMLElement;
319
- const currentItem = el.parentElement as HTMLElement;
320
- const currentSelectedIndex = this.getCurrentIndex(currentItem);
321
- const nextSelectIndex = currentSelectedIndex + 1 > this.navigationItems.length - 1 ? 0 : currentSelectedIndex + 1;
322
- const listItem = this.getListItemByIndex(nextSelectIndex);
323
- listItem?.focus();
324
- }
325
-
326
- onCloseDropdown(): void {
327
- this._dropdownMoreIsOpen = false;
268
+ const item = e.target as UDExSecondaryNavigationItem;
269
+ const currentSelectedIndex = this.getCurrentIndex(item);
270
+ const nextSelectIndex = currentSelectedIndex + 1 > this.domNavItems.length - 1 ? 0 : currentSelectedIndex + 1;
271
+ this.domNavItems[nextSelectIndex].focus();
328
272
  }
329
273
 
330
274
  getItemWidth(item: NavItem): number {
331
275
  const canvas = document.createElement("canvas");
332
276
  const context = canvas.getContext("2d")!;
333
- context.font = "16px / 17.6px '72 Brand Variable'";
277
+ context.font = canvasContentFont;
334
278
 
335
279
  return Math.ceil(context.measureText(item.title).width);
336
280
  }
337
281
 
338
- getCurrentIndex(item: HTMLElement): number {
339
- return this.navigationItems.indexOf(item);
340
- }
341
-
342
- getListItemByIndex(index: number): HTMLElement | null {
343
- return this.navigationItems[index].querySelector(".udex-secondary-navigation__link-btn");
344
- }
282
+ getMoreButtonWidth(): number {
283
+ const canvas = document.createElement("canvas");
284
+ const context = canvas.getContext("2d")!;
285
+ context.font = canvasContentFont;
345
286
 
346
- getDropdown(): HTMLElement {
347
- return this.shadowRoot!.querySelector(".udex-secondary-navigation__dropdown")!;
287
+ return Math.ceil(context.measureText(this.moreButtonText).width);
348
288
  }
349
289
 
350
- getMobileButtonMenu(): HTMLElement {
351
- return this.shadowRoot?.querySelector(".udex-secondary-navigation__mobile-opener") as HTMLElement;
290
+ getCurrentIndex(item: UDExSecondaryNavigationItem): number {
291
+ return this.domNavItems.indexOf(item);
352
292
  }
353
293
 
354
- getMoreButton(): HTMLElement {
355
- return this.shadowRoot!.querySelector(".udex-secondary-navigation__list-item_more > button")!;
356
- }
294
+ handleItemClick(e: CustomEvent): void {
295
+ const clickedItem = e.detail.item as UDExSecondaryNavigationItem;
296
+ const prevented = !this.fireEvent("item-click", {
297
+ originalEvent: e,
298
+ clickedItem,
299
+ clickedIndex: this.getCurrentIndex(clickedItem),
300
+ }, true);
357
301
 
358
- getMoreButtonWidth(): number {
359
- const canvas = document.createElement("canvas");
360
- const context = canvas.getContext("2d")!;
361
- context.font = "16px / 17.6px '72 Brand Variable'";
302
+ if (prevented) {
303
+ e.preventDefault();
304
+ return;
305
+ }
362
306
 
363
- return Math.ceil(context.measureText("More").width) + 4 + 16;
364
- }
307
+ this._clickedNavItem = clickedItem;
308
+ this.closePrevDropdown(clickedItem._id);
365
309
 
366
- parseArrayFromString<T>(string: string): T[] {
367
- return string ? JSON.parse(string) as T[] : [];
310
+ if (!clickedItem.hasNestedItems) {
311
+ this.setActiveItem(this.parsedItems, clickedItem);
312
+ }
368
313
  }
369
314
 
370
- handleNavigationClick(e: MouseEvent) {
371
- const target = e.target as HTMLElement;
372
- const clickedIndex = this.domNavItems.indexOf(target);
373
- const prevented = !this.fireEvent("item-click", {
315
+ handleSubItemClick(e: CustomEvent): void {
316
+ const item = e.detail.item as UDExSecondaryNavigationSubItem;
317
+ const { items } = item as NavItem;
318
+ const prevented = !this.fireEvent("sub-item-click", {
374
319
  originalEvent: e,
375
- clickedItem: target,
376
- clickedIndex,
320
+ clickedItem: item,
377
321
  }, true);
378
322
 
379
323
  if (prevented) {
@@ -381,22 +325,64 @@ class UDExSecondaryNavigation extends UI5Element {
381
325
  return;
382
326
  }
383
327
 
384
- if (this.domNavItems.length > 0) {
385
- this.navigationList.forEach(item => delete item.active);
386
- this.navigationList[clickedIndex].active = true;
387
- this.refreshRendering();
388
- this.toggleActiveClass();
328
+ if (this.isMobileScreen && !items) {
329
+ this.mobileNav.closeDropdown();
389
330
  }
331
+
332
+ if (!items) {
333
+ this.setActiveItem(this.parsedItems, item);
334
+ this._clickedNavItem?.closeDropdown();
335
+ }
336
+ }
337
+
338
+ setActiveItem(navItems: Array<NavItem>, clickedItem: UDExSecondaryNavigationItemBase): void {
339
+ const updateNav = (items: Array<NavItem>, { title, path }: UDExSecondaryNavigationItemBase) => {
340
+ items.forEach(item => {
341
+ if (item.title === title && item.path === path) {
342
+ item.active = true;
343
+ return;
344
+ }
345
+ delete item.active;
346
+
347
+ if (item.items) {
348
+ updateNav(item.items, clickedItem);
349
+ }
350
+ });
351
+ };
352
+
353
+ updateNav(navItems, clickedItem);
354
+ this.navItems = JSON.stringify(navItems);
355
+ }
356
+
357
+ handleOutsideClick(): void {
358
+ document.addEventListener("click", (e: MouseEvent) => {
359
+ if (this.isMobileScreen && e.target !== this) {
360
+ this.mobileNav?.closeDropdown();
361
+ return;
362
+ }
363
+
364
+ const isClickedNavItem = e.composedPath().includes(this._clickedNavItem);
365
+ if (this.isDesktopScreen && !isClickedNavItem && this._clickedNavItem) {
366
+ this._clickedNavItem.closeDropdown();
367
+ }
368
+ });
369
+ }
370
+
371
+ closePrevDropdown(clickedItemId: string): void {
372
+ this.domNavItems.forEach(item => {
373
+ if (clickedItemId !== item._id) {
374
+ item.closeDropdown();
375
+ }
376
+ });
390
377
  }
391
378
 
392
- get navigationItems(): Array<HTMLElement> {
393
- return Array.from(this.shadowRoot!.querySelectorAll(".udex-secondary-navigation__link-btn-wrap"));
379
+ parseArrayFromString<T>(string: string): T[] {
380
+ return string ? JSON.parse(string) as T[] : [];
394
381
  }
395
382
 
396
- get domNavItems(): Array<HTMLElement> {
397
- const navigationItemsSelector = ".udex-secondary-navigation__item:not(.udex-secondary-navigation__link-btn-more), .udex-secondary-navigation__dropdown-item";
398
- const domNavItems = this.shadowRoot?.querySelectorAll<HTMLElement>(navigationItemsSelector);
399
- return domNavItems ? Array.from(domNavItems) : [];
383
+ get domNavItems(): Array<UDExSecondaryNavigationItem> {
384
+ const items = this.shadowRoot?.querySelectorAll<UDExSecondaryNavigationItem>("udex-secondary-navigation-item");
385
+ return items ? Array.from(items) : [];
400
386
  }
401
387
 
402
388
  get rootHolder(): HTMLElement {
@@ -407,59 +393,49 @@ class UDExSecondaryNavigation extends UI5Element {
407
393
  return (this.shadowRoot ? this.shadowRoot.querySelector<HTMLElement>(".udex-secondary-navigation__heading") : undefined)!;
408
394
  }
409
395
 
410
- get optionalButtons() {
411
- return this.shadowRoot?.querySelector<HTMLElement>(".udex-secondary-navigation__buttons");
396
+ get mobileNav(): UDExSecondaryNavigationItem {
397
+ return (this.shadowRoot ? this.shadowRoot.querySelector<UDExSecondaryNavigationItem>(".udex-secondary-navigation__mobile-nav") : undefined)!;
412
398
  }
413
399
 
414
- get linksList() {
415
- return this.shadowRoot?.querySelector<HTMLElement>(".udex-secondary-navigation__list");
400
+ get optionalButtons(): HTMLElement | null | undefined {
401
+ return this.shadowRoot?.querySelector<HTMLElement>(".udex-secondary-navigation__buttons");
416
402
  }
417
403
 
418
404
  get moreButtonText(): string {
419
405
  return UDExSecondaryNavigation.i18nBundle.getText(MORE) as string;
420
406
  }
421
407
 
422
- get activeItemText(): string {
423
- const activeItem = this.navigationList.find(item => item.active);
424
- return activeItem ? activeItem?.title : "";
408
+ get parsedItems(): Array<NavItem> {
409
+ return this.parseArrayFromString<NavItem>(this.navItems);
425
410
  }
426
411
 
427
- get moreClass(): string {
428
- const rootClasses = "udex-secondary-navigation__list-item udex-secondary-navigation__list-item_more";
429
- return this._dropdownMoreIsOpen ? `${rootClasses} udex-secondary-navigation__list-item_open` : `${rootClasses}`;
412
+ get visibleItems(): Array<NavItem> {
413
+ return this.isDesktopScreen ? this._visibleItems : this.parsedItems;
430
414
  }
431
415
 
432
- get navigationList(): Array<NavItem> {
433
- if (!this._navigationList) {
434
- this._navigationList = this.parseArrayFromString<NavItem>(this.navItems);
435
- }
436
- return this._navigationList;
437
- }
438
-
439
- get items(): Array<NavItem> {
440
- return this.isDesktopScreen ? this._navItems : this.navigationList;
416
+ get hasBreadcrumbsSlot(): boolean {
417
+ return !!this.getSlottedNodes("breadcrumbs").length && this.isDesktopScreen;
441
418
  }
442
419
 
443
- get moreIsActive(): boolean {
444
- return this._overflowItems.some(item => item.active);
420
+ get hasDesktopButtonsSlot(): boolean {
421
+ return this.hasButtons && this.isDesktopScreen;
445
422
  }
446
423
 
447
- get rootClass(): string {
448
- const centeredClass = this.hasBreadcrumbsSlot ? "" : `${rootClass}_centered`;
449
- return `${rootClass} ${centeredClass}`;
424
+ get hasMobileButtonsSlot(): boolean {
425
+ return this.hasButtons && this.isMobileScreen;
450
426
  }
451
427
 
452
- get hasBreadcrumbsSlot(): boolean {
453
- return !!this.getSlottedNodes("breadcrumbs").length;
454
- }
455
-
456
- get hasButtonsSlot(): boolean {
428
+ get hasButtons(): boolean {
457
429
  return !!this.getSlottedNodes("buttons").length;
458
430
  }
459
431
 
460
432
  get isDesktopScreen(): boolean {
461
433
  return window.innerWidth > breakpointSizeS;
462
434
  }
435
+
436
+ get isMobileScreen(): boolean {
437
+ return window.innerWidth <= breakpointSizeS;
438
+ }
463
439
  }
464
440
 
465
441
  UDExSecondaryNavigation.define();
@@ -0,0 +1,63 @@
1
+ {{#if isLink}}
2
+ <a
3
+ class="udex-secondary-navigation__item"
4
+ role="{{menuItemRole}}"
5
+ ?active="{{isActive}}"
6
+ href="{{path}}"
7
+ target="{{target}}"
8
+ @keydown="{{handleItemLinkKeyDown}}"
9
+ @click="{{onItemClick}}">
10
+ {{label}}
11
+ </a>
12
+ {{else}}
13
+ <button
14
+ class="udex-secondary-navigation__item"
15
+ role="{{itemRole}}"
16
+ ?active="{{isActive}}"
17
+ aria-haspopup="{{hasNestedItems}}"
18
+ aria-expanded="{{isOpen}}"
19
+ aria-label="{{ariaLabel}}"
20
+ @keydown="{{handleItemButtonKeyDown}}"
21
+ @click="{{onItemClick}}">
22
+ <span class="udex-secondary-navigation__item-text-wrap">
23
+ {{label}}
24
+ {{#if _subTitle}}
25
+ <span
26
+ class="udex-secondary-navigation__item-sub-title">
27
+ {{_subTitle}}
28
+ </span>
29
+ {{/if}}
30
+ {{#if hasNestedItems}}
31
+ <ui5-icon
32
+ class="udex-secondary-navigation__item-icon"
33
+ name="slim-arrow-down">
34
+ </ui5-icon>
35
+ {{/if}}
36
+ </span>
37
+ </button>
38
+ {{#if isOpen}}
39
+ <div
40
+ class="udex-secondary-navigation__dropdown"
41
+ @keydown="{{handleSubItemKeyDown}}">
42
+ <ul role="menu"
43
+ class="udex-secondary-navigation__dropdown-list">
44
+ {{#each _processedItems}}
45
+ <li role="none">
46
+ <udex-secondary-navigation-sub-item
47
+ index="{{@index}}"
48
+ @ui5-sub-item-click="{{../onSubItemClick}}"
49
+ @ui5-back-item-click="{{../onBackClick}}"
50
+ is-back="{{this.isBack}}"
51
+ label="{{this.title}}"
52
+ .nestedItems="{{this.items}}"
53
+ path="{{this.path}}"
54
+ target="{{this.target}}"
55
+ ?is-active="{{this.active}}">
56
+ </udex-secondary-navigation-sub-item>
57
+ </li>
58
+ {{/each}}
59
+ </ul>
60
+ <slot></slot>
61
+ </div>
62
+ {{/if}}
63
+ {{/if}}