@sapudex/web-components 2.29.0 → 2.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. package/cypress/specs/FilterMenu.cy.tsx +39 -1
  2. package/cypress/specs/List.cy.tsx +171 -0
  3. package/cypress/specs/ListItem.cy.tsx +22 -26
  4. package/cypress/specs/PromoTile.cy.tsx +10 -0
  5. package/cypress/specs/ReviewItem.cy.tsx +48 -14
  6. package/cypress/specs/SecondaryNavigationDesktop.cy.tsx +12 -12
  7. package/cypress/specs/SelectBox.cy.tsx +76 -0
  8. package/cypress/support/component-imports.instrumented.ts +4 -0
  9. package/cypress/support/component-imports.src.ts +5 -1
  10. package/dist/Avatar.d.ts +1 -0
  11. package/dist/Avatar.js +9 -0
  12. package/dist/Avatar.js.map +1 -1
  13. package/dist/Breadcrumbs.d.ts +0 -4
  14. package/dist/Breadcrumbs.js +7 -16
  15. package/dist/Breadcrumbs.js.map +1 -1
  16. package/dist/BreadcrumbsTemplate.js +1 -1
  17. package/dist/BreadcrumbsTemplate.js.map +1 -1
  18. package/dist/FilterMenu.d.ts +2 -0
  19. package/dist/FilterMenu.js +2 -0
  20. package/dist/FilterMenu.js.map +1 -1
  21. package/dist/ImageGridTickerTemplate.js +2 -1
  22. package/dist/ImageGridTickerTemplate.js.map +1 -1
  23. package/dist/List.d.ts +4 -2
  24. package/dist/List.js +45 -12
  25. package/dist/List.js.map +1 -1
  26. package/dist/ListGroupHeader.d.ts +4 -0
  27. package/dist/ListGroupHeader.js +26 -1
  28. package/dist/ListGroupHeader.js.map +1 -1
  29. package/dist/ListGroupHeaderBase.js +1 -1
  30. package/dist/ListGroupHeaderBase.js.map +1 -1
  31. package/dist/ListItem.js +1 -1
  32. package/dist/ListItem.js.map +1 -1
  33. package/dist/ListItemBase.d.ts +40 -3
  34. package/dist/ListItemBase.js +70 -9
  35. package/dist/ListItemBase.js.map +1 -1
  36. package/dist/MastheadCountrySelector.d.ts +3 -15
  37. package/dist/MastheadCountrySelector.js +28 -72
  38. package/dist/MastheadCountrySelector.js.map +1 -1
  39. package/dist/MastheadItem.d.ts +10 -2
  40. package/dist/MastheadItem.js +26 -15
  41. package/dist/MastheadItem.js.map +1 -1
  42. package/dist/MastheadMenu.d.ts +2 -2
  43. package/dist/MastheadMenu.js +9 -9
  44. package/dist/MastheadMenu.js.map +1 -1
  45. package/dist/MastheadMenuItem.d.ts +7 -0
  46. package/dist/MastheadMenuItem.js +3 -0
  47. package/dist/MastheadMenuItem.js.map +1 -1
  48. package/dist/MastheadMobileMenu.d.ts +2 -12
  49. package/dist/MastheadMobileMenu.js +31 -116
  50. package/dist/MastheadMobileMenu.js.map +1 -1
  51. package/dist/MastheadProfileMenu.js +1 -1
  52. package/dist/MastheadProfileMenu.js.map +1 -1
  53. package/dist/MastheadShell.d.ts +1 -6
  54. package/dist/MastheadShell.js +7 -44
  55. package/dist/MastheadShell.js.map +1 -1
  56. package/dist/Pagination.d.ts +14 -1
  57. package/dist/Pagination.js +40 -7
  58. package/dist/Pagination.js.map +1 -1
  59. package/dist/PromoTile.d.ts +8 -0
  60. package/dist/PromoTile.js +4 -0
  61. package/dist/PromoTile.js.map +1 -1
  62. package/dist/PromoTileTemplate.js +3 -1
  63. package/dist/PromoTileTemplate.js.map +1 -1
  64. package/dist/ReviewItem.d.ts +8 -7
  65. package/dist/ReviewItem.js +35 -36
  66. package/dist/ReviewItem.js.map +1 -1
  67. package/dist/ReviewItemTemplate.js +3 -1
  68. package/dist/ReviewItemTemplate.js.map +1 -1
  69. package/dist/SearchableListBase.d.ts +3 -0
  70. package/dist/SearchableListBase.js +37 -1
  71. package/dist/SearchableListBase.js.map +1 -1
  72. package/dist/SecondaryNavigationItem.js +7 -1
  73. package/dist/SecondaryNavigationItem.js.map +1 -1
  74. package/dist/SelectBase.js +28 -7
  75. package/dist/SelectBase.js.map +1 -1
  76. package/dist/SelectBox.js +0 -1
  77. package/dist/SelectBox.js.map +1 -1
  78. package/dist/TextField.d.ts +1 -1
  79. package/dist/TextField.js.map +1 -1
  80. package/dist/assets/{InputSuggestions-GMbG8xQ2.js → InputSuggestions-i2kFpCfC.js} +1 -1
  81. package/dist/assets/{ListItemStandardExpandableTextTemplate-IyZB_qzJ.js → ListItemStandardExpandableTextTemplate-C1ceDaxu.js} +1 -1
  82. package/dist/assets/{bundle.esm-Dg7j0PXg.js → bundle.esm-DQ3cxywT.js} +216 -216
  83. package/dist/assets/messagebundle_en-DWAgV5VH.js +1 -0
  84. package/dist/css/themes/BreadcrumbsPopover.css +1 -1
  85. package/dist/css/themes/Dropdown.css +1 -1
  86. package/dist/css/themes/FilterMenu.css +1 -1
  87. package/dist/css/themes/ImageGridTicker.css +1 -1
  88. package/dist/css/themes/Link.css +1 -1
  89. package/dist/css/themes/ListGroupHeader.css +1 -1
  90. package/dist/css/themes/ListItem.css +1 -1
  91. package/dist/css/themes/MastheadCountrySelector.css +1 -1
  92. package/dist/css/themes/MastheadItem.css +1 -1
  93. package/dist/css/themes/MastheadProfileMenu.css +1 -1
  94. package/dist/css/themes/MastheadShell.css +1 -1
  95. package/dist/css/themes/Modal.css +1 -1
  96. package/dist/css/themes/RatingIndicator.css +1 -1
  97. package/dist/css/themes/ReviewItem.css +1 -1
  98. package/dist/css/themes/SecondaryNavigation.css +1 -1
  99. package/dist/css/themes/SecondaryNavigationItem.css +1 -1
  100. package/dist/css/themes/SecondaryNavigationSubItem.css +1 -1
  101. package/dist/css/themes/Slider.css +1 -1
  102. package/dist/custom-elements-internal.json +986 -19
  103. package/dist/custom-elements.json +734 -13
  104. package/dist/generated/assets/i18n/messagebundle_en.json +1 -1
  105. package/dist/generated/i18n/i18n-defaults.d.ts +6 -1
  106. package/dist/generated/i18n/i18n-defaults.js +6 -1
  107. package/dist/generated/i18n/i18n-defaults.js.map +1 -1
  108. package/dist/generated/templates/ListGroupHeaderTemplate.lit.js +17 -10
  109. package/dist/generated/templates/ListGroupHeaderTemplate.lit.js.map +1 -1
  110. package/dist/generated/templates/ListItemTemplate.lit.js +32 -34
  111. package/dist/generated/templates/ListItemTemplate.lit.js.map +1 -1
  112. package/dist/generated/templates/MastheadCountrySelectorTemplate.lit.js +3 -3
  113. package/dist/generated/templates/MastheadCountrySelectorTemplate.lit.js.map +1 -1
  114. package/dist/generated/templates/MastheadItemTemplate.lit.js +33 -25
  115. package/dist/generated/templates/MastheadItemTemplate.lit.js.map +1 -1
  116. package/dist/generated/templates/MastheadMenuItemTemplate.lit.js +1 -1
  117. package/dist/generated/templates/MastheadMenuItemTemplate.lit.js.map +1 -1
  118. package/dist/generated/templates/MastheadMobileMenuTemplate.lit.js +5 -5
  119. package/dist/generated/templates/MastheadMobileMenuTemplate.lit.js.map +1 -1
  120. package/dist/generated/templates/MastheadShellTemplate.lit.js +9 -10
  121. package/dist/generated/templates/MastheadShellTemplate.lit.js.map +1 -1
  122. package/dist/generated/templates/SearchableListBaseTemplate.lit.js +1 -1
  123. package/dist/generated/templates/SearchableListBaseTemplate.lit.js.map +1 -1
  124. package/dist/generated/themes/BreadcrumbsPopover.css.d.ts +1 -1
  125. package/dist/generated/themes/BreadcrumbsPopover.css.js +1 -1
  126. package/dist/generated/themes/BreadcrumbsPopover.css.js.map +1 -1
  127. package/dist/generated/themes/Dropdown.css.d.ts +1 -1
  128. package/dist/generated/themes/Dropdown.css.js +1 -1
  129. package/dist/generated/themes/Dropdown.css.js.map +1 -1
  130. package/dist/generated/themes/FilterMenu.css.d.ts +1 -1
  131. package/dist/generated/themes/FilterMenu.css.js +1 -1
  132. package/dist/generated/themes/FilterMenu.css.js.map +1 -1
  133. package/dist/generated/themes/ImageGridTicker.css.d.ts +1 -1
  134. package/dist/generated/themes/ImageGridTicker.css.js +1 -1
  135. package/dist/generated/themes/ImageGridTicker.css.js.map +1 -1
  136. package/dist/generated/themes/Link.css.d.ts +1 -1
  137. package/dist/generated/themes/Link.css.js +1 -1
  138. package/dist/generated/themes/Link.css.js.map +1 -1
  139. package/dist/generated/themes/ListGroupHeader.css.d.ts +1 -1
  140. package/dist/generated/themes/ListGroupHeader.css.js +1 -1
  141. package/dist/generated/themes/ListGroupHeader.css.js.map +1 -1
  142. package/dist/generated/themes/ListItem.css.d.ts +1 -1
  143. package/dist/generated/themes/ListItem.css.js +1 -1
  144. package/dist/generated/themes/ListItem.css.js.map +1 -1
  145. package/dist/generated/themes/MastheadCountrySelector.css.d.ts +1 -1
  146. package/dist/generated/themes/MastheadCountrySelector.css.js +1 -1
  147. package/dist/generated/themes/MastheadCountrySelector.css.js.map +1 -1
  148. package/dist/generated/themes/MastheadItem.css.d.ts +1 -1
  149. package/dist/generated/themes/MastheadItem.css.js +1 -1
  150. package/dist/generated/themes/MastheadItem.css.js.map +1 -1
  151. package/dist/generated/themes/MastheadProfileMenu.css.d.ts +1 -1
  152. package/dist/generated/themes/MastheadProfileMenu.css.js +1 -1
  153. package/dist/generated/themes/MastheadProfileMenu.css.js.map +1 -1
  154. package/dist/generated/themes/MastheadShell.css.d.ts +1 -1
  155. package/dist/generated/themes/MastheadShell.css.js +1 -1
  156. package/dist/generated/themes/MastheadShell.css.js.map +1 -1
  157. package/dist/generated/themes/Modal.css.d.ts +1 -1
  158. package/dist/generated/themes/Modal.css.js +1 -1
  159. package/dist/generated/themes/Modal.css.js.map +1 -1
  160. package/dist/generated/themes/RatingIndicator.css.d.ts +1 -1
  161. package/dist/generated/themes/RatingIndicator.css.js +1 -1
  162. package/dist/generated/themes/RatingIndicator.css.js.map +1 -1
  163. package/dist/generated/themes/ReviewItem.css.d.ts +1 -1
  164. package/dist/generated/themes/ReviewItem.css.js +1 -1
  165. package/dist/generated/themes/ReviewItem.css.js.map +1 -1
  166. package/dist/generated/themes/SecondaryNavigation.css.d.ts +1 -1
  167. package/dist/generated/themes/SecondaryNavigation.css.js +1 -1
  168. package/dist/generated/themes/SecondaryNavigation.css.js.map +1 -1
  169. package/dist/generated/themes/SecondaryNavigationItem.css.d.ts +1 -1
  170. package/dist/generated/themes/SecondaryNavigationItem.css.js +1 -1
  171. package/dist/generated/themes/SecondaryNavigationItem.css.js.map +1 -1
  172. package/dist/generated/themes/SecondaryNavigationSubItem.css.d.ts +1 -1
  173. package/dist/generated/themes/SecondaryNavigationSubItem.css.js +1 -1
  174. package/dist/generated/themes/SecondaryNavigationSubItem.css.js.map +1 -1
  175. package/dist/generated/themes/Slider.css.d.ts +1 -1
  176. package/dist/generated/themes/Slider.css.js +1 -1
  177. package/dist/generated/themes/Slider.css.js.map +1 -1
  178. package/dist/messagebundle.properties +9 -0
  179. package/dist/messagebundle_en.properties +3 -0
  180. package/dist/types/List.d.ts +0 -2
  181. package/dist/types/List.js +0 -2
  182. package/dist/types/List.js.map +1 -1
  183. package/dist/types/SearchableListBase.d.ts +1 -0
  184. package/dist/types/SearchableListBase.js.map +1 -1
  185. package/dist/vscode.html-custom-data.json +144 -85
  186. package/dist/web-types.json +303 -83
  187. package/package.json +2 -1
  188. package/src/Avatar.ts +9 -0
  189. package/src/Breadcrumbs.ts +8 -20
  190. package/src/BreadcrumbsTemplate.tsx +1 -1
  191. package/src/FilterMenu.ts +4 -0
  192. package/src/ImageGridTickerTemplate.tsx +3 -1
  193. package/src/List.ts +51 -14
  194. package/src/ListGroupHeader.hbs +128 -17
  195. package/src/ListGroupHeader.ts +31 -1
  196. package/src/ListGroupHeaderBase.ts +1 -1
  197. package/src/ListItem.hbs +15 -2
  198. package/src/ListItem.ts +1 -1
  199. package/src/ListItemBase.ts +105 -7
  200. package/src/MastheadCountrySelector.hbs +6 -3
  201. package/src/MastheadCountrySelector.ts +31 -85
  202. package/src/MastheadItem.hbs +31 -23
  203. package/src/MastheadItem.ts +28 -18
  204. package/src/MastheadMenu.ts +10 -9
  205. package/src/MastheadMenuItem.hbs +1 -0
  206. package/src/MastheadMenuItem.ts +9 -0
  207. package/src/MastheadMobileMenu.hbs +5 -6
  208. package/src/MastheadMobileMenu.ts +34 -130
  209. package/src/MastheadProfileMenu.ts +1 -1
  210. package/src/MastheadShell.hbs +9 -11
  211. package/src/MastheadShell.ts +8 -50
  212. package/src/Pagination.ts +52 -8
  213. package/src/PromoTile.ts +10 -0
  214. package/src/PromoTileTemplate.tsx +4 -1
  215. package/src/ReviewItem.ts +45 -35
  216. package/src/ReviewItemTemplate.tsx +16 -14
  217. package/src/SearchableListBase.hbs +3 -0
  218. package/src/SearchableListBase.ts +52 -1
  219. package/src/SecondaryNavigationItem.ts +1 -2
  220. package/src/SelectBase.ts +33 -7
  221. package/src/SelectBox.ts +0 -1
  222. package/src/TextField.ts +1 -1
  223. package/src/generated/i18n/i18n-defaults.ts +2 -2
  224. package/src/generated/templates/ListGroupHeaderTemplate.lit.ts +17 -10
  225. package/src/generated/templates/ListItemTemplate.lit.ts +32 -34
  226. package/src/generated/templates/MastheadCountrySelectorTemplate.lit.ts +3 -3
  227. package/src/generated/templates/MastheadItemTemplate.lit.ts +33 -25
  228. package/src/generated/templates/MastheadMenuItemTemplate.lit.ts +1 -1
  229. package/src/generated/templates/MastheadMobileMenuTemplate.lit.ts +5 -5
  230. package/src/generated/templates/MastheadShellTemplate.lit.ts +9 -10
  231. package/src/generated/templates/SearchableListBaseTemplate.lit.ts +1 -1
  232. package/src/generated/themes/BreadcrumbsPopover.css.ts +1 -1
  233. package/src/generated/themes/Dropdown.css.ts +1 -1
  234. package/src/generated/themes/FilterMenu.css.ts +1 -1
  235. package/src/generated/themes/ImageGridTicker.css.ts +1 -1
  236. package/src/generated/themes/Link.css.ts +1 -1
  237. package/src/generated/themes/ListGroupHeader.css.ts +1 -1
  238. package/src/generated/themes/ListItem.css.ts +1 -1
  239. package/src/generated/themes/MastheadCountrySelector.css.ts +1 -1
  240. package/src/generated/themes/MastheadItem.css.ts +1 -1
  241. package/src/generated/themes/MastheadProfileMenu.css.ts +1 -1
  242. package/src/generated/themes/MastheadShell.css.ts +1 -1
  243. package/src/generated/themes/Modal.css.ts +1 -1
  244. package/src/generated/themes/RatingIndicator.css.ts +1 -1
  245. package/src/generated/themes/ReviewItem.css.ts +1 -1
  246. package/src/generated/themes/SecondaryNavigation.css.ts +1 -1
  247. package/src/generated/themes/SecondaryNavigationItem.css.ts +1 -1
  248. package/src/generated/themes/SecondaryNavigationSubItem.css.ts +1 -1
  249. package/src/generated/themes/Slider.css.ts +1 -1
  250. package/src/i18n/messagebundle.properties +9 -0
  251. package/src/i18n/messagebundle_en.properties +3 -0
  252. package/src/themes/BreadcrumbsPopover.css +2 -0
  253. package/src/themes/Dropdown.css +5 -1
  254. package/src/themes/FilterMenu.css +2 -2
  255. package/src/themes/ImageGridTicker.css +2 -26
  256. package/src/themes/Link.css +2 -3
  257. package/src/themes/ListGroupHeader.css +102 -15
  258. package/src/themes/ListItem.css +67 -15
  259. package/src/themes/MastheadCountrySelector.css +3 -1
  260. package/src/themes/MastheadItem.css +88 -3
  261. package/src/themes/MastheadProfileMenu.css +1 -9
  262. package/src/themes/MastheadShell.css +0 -2
  263. package/src/themes/Modal.css +2 -1
  264. package/src/themes/ReviewItem.css +18 -1
  265. package/src/themes/SecondaryNavigation.css +6 -3
  266. package/src/themes/SecondaryNavigationItem.css +11 -10
  267. package/src/themes/SecondaryNavigationSubItem.css +3 -2
  268. package/src/types/List.ts +0 -2
  269. package/src/types/SearchableListBase.ts +1 -0
  270. package/dist/assets/messagebundle_en-DfoXjU7o.js +0 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@sapudex/web-components",
4
- "version": "2.29.0",
4
+ "version": "2.31.0",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
7
7
  },
@@ -58,6 +58,7 @@
58
58
  "wdio-chromedriver-service": "^8.1.1",
59
59
  "webdriverio": "^8.16.12"
60
60
  },
61
+ "types": "./dist",
61
62
  "repository": {
62
63
  "type": "git",
63
64
  "url": "https://github.tools.sap/sapudex/digital-design-system",
package/src/Avatar.ts CHANGED
@@ -87,10 +87,17 @@ const UDExToUi5ColorSchemeMap = {
87
87
  * @public
88
88
  */
89
89
  @event("click", { bubbles: true })
90
+ /**
91
+ * Fires when the avatar is clicked.
92
+ *
93
+ * @public
94
+ */
95
+ @event("click-default", { bubbles: true })
90
96
 
91
97
  class UDExAvatar extends UI5Element {
92
98
  eventDetails!: {
93
99
  "click": void,
100
+ "click-default": void,
94
101
  };
95
102
  /**
96
103
  * Defines the displayed initials.
@@ -210,7 +217,9 @@ class UDExAvatar extends UI5Element {
210
217
  e.stopPropagation();
211
218
  if (this.interactive) {
212
219
  this.fireDecoratorEvent("click");
220
+ return;
213
221
  }
222
+ this.fireDecoratorEvent("click-default");
214
223
  }
215
224
 
216
225
  /**
@@ -7,8 +7,6 @@ import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js";
7
7
  import { isTabNext, isTabPrevious, isEscape } from "@ui5/webcomponents-base/dist/Keys.js";
8
8
  import UI5Icon from "@ui5/webcomponents/dist/Icon.js";
9
9
  import type { LinkClickEventDetail } from "@ui5/webcomponents/dist/Link.js";
10
- import NavigationMode from "@ui5/webcomponents-base/dist/types/NavigationMode.js";
11
- import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js";
12
10
  import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js";
13
11
  import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
14
12
  import UI5BreadcrumbsCss from "@ui5/webcomponents/dist/generated/themes/Breadcrumbs.css.js";
@@ -122,7 +120,6 @@ class UDExBreadcrumbs extends UI5Element {
122
120
  static i18nBundle: I18nBundle;
123
121
 
124
122
  _responsivePopover?: UDExDropdown;
125
- _itemNavigation?: ItemNavigation;
126
123
  _shouldFocusFirstVisibleItem!: boolean;
127
124
  _rootClass: string;
128
125
 
@@ -137,7 +134,6 @@ class UDExBreadcrumbs extends UI5Element {
137
134
 
138
135
  onAfterRendering(): void {
139
136
  this._responsivePopover = this._getResponsePopover();
140
- this._initItemNavigation();
141
137
  this._dropdownArrowLink.forcedTabIndex = "0";
142
138
  this._handleOutsideClick();
143
139
 
@@ -164,15 +160,6 @@ class UDExBreadcrumbs extends UI5Element {
164
160
  return items;
165
161
  }
166
162
 
167
- _initItemNavigation(): void {
168
- if (!this._itemNavigation) {
169
- this._itemNavigation = new ItemNavigation(this, {
170
- navigationMode: NavigationMode.Horizontal,
171
- getItemsCallback: () => this._getFocusableItems(),
172
- });
173
- }
174
- }
175
-
176
163
  _getItems(): Array<UDExBreadcrumbsItem> {
177
164
  return this.getSlottedNodes<UDExBreadcrumbsItem>("items");
178
165
  }
@@ -239,12 +226,6 @@ class UDExBreadcrumbs extends UI5Element {
239
226
  }
240
227
  }
241
228
 
242
- _onfocusin(e: FocusEvent): void {
243
- const currentItem = e.target as UDExLink;
244
-
245
- this._itemNavigation?.setCurrentItem(currentItem);
246
- }
247
-
248
229
  _handleKeydown(e: KeyboardEvent): void {
249
230
  const itemIndex = (e.target as HTMLElement).getAttribute("data-index");
250
231
  const isLastItem = itemIndex === (this.items.length - 2).toString();
@@ -256,7 +237,14 @@ class UDExBreadcrumbs extends UI5Element {
256
237
  return;
257
238
  }
258
239
 
259
- if ((isTabNext(e) && isLastItem) || (isTabPrevious(e) && isFirstItem) || isEscape(e)) {
240
+ if (isTabPrevious(e) && isFirstItem) {
241
+ e.preventDefault();
242
+ this._dropdownArrowLink.focus();
243
+ this._toggleDropdown();
244
+ return;
245
+ }
246
+
247
+ if (isEscape(e)) {
260
248
  this._toggleDropdown();
261
249
  }
262
250
  }
@@ -12,7 +12,7 @@ export default function BreadcrumbsTemplate(this: Breadcrumbs) {
12
12
  <nav
13
13
  class={`${this._rootClass} ui5-breadcrumbs-root`}
14
14
  aria-label={this._breadcrumbsAccessibleNameText}>
15
- <ol onFocusIn={this._onfocusin}>
15
+ <ol>
16
16
  <li class={`${this._rootClass}__arrow-wrapper ui5-breadcrumbs-dropdown-arrow-link-wrapper`}>
17
17
  <UDExLink
18
18
  id={`udex-${this._id}-breadcrumbs__opener`}
package/src/FilterMenu.ts CHANGED
@@ -44,6 +44,8 @@ export type initialItemState = {
44
44
  id: string,
45
45
  selected: boolean,
46
46
  indeterminate?: boolean,
47
+ collapsed?: boolean,
48
+ _filtered?: boolean,
47
49
  }
48
50
 
49
51
  type UDExFilterMenuResultClickEventDetail = {
@@ -483,6 +485,8 @@ class UDExFilterMenu extends UDExSearchableListBase {
483
485
  id: item._id,
484
486
  selected: item.selected,
485
487
  indeterminate: item.indeterminate,
488
+ collapsed: item.collapsed,
489
+ _filtered: item._filtered,
486
490
  };
487
491
  const subItemsState = (item as UDExListGroupHeaderBase).getItems().map(subItem => ({
488
492
  id: subItem._id,
@@ -2,6 +2,7 @@ import type ImageGridTicker from "./ImageGridTicker.js";
2
2
  import ImageGridTickerItem from "./ImageGridTickerItem.js";
3
3
  import UDExButton from "./Button.js";
4
4
  import UDExButtonDesign from "./types/ButtonDesign.js";
5
+ import UDExButtonSize from "./types/ButtonSize.js";
5
6
  import playIcon from "@ui5/webcomponents-icons/dist/play.js";
6
7
  import pauseIcon from "@ui5/webcomponents-icons/dist/pause.js";
7
8
 
@@ -17,7 +18,8 @@ export default function ImageGridTickerTemplate(this: ImageGridTicker) {
17
18
  <UDExButton
18
19
  class={`${rootClass}__play-button`}
19
20
  icon={btnIcon}
20
- design={UDExButtonDesign.Invisible}
21
+ size={UDExButtonSize.Large}
22
+ design={UDExButtonDesign.Tertiary}
21
23
  onClick={this._onPlayButtonClick}
22
24
  tooltip={this.playBtnTooltipText}>
23
25
  </UDExButton>
package/src/List.ts CHANGED
@@ -5,7 +5,7 @@ import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
5
5
  import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js";
6
6
  import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
7
7
  import {
8
- isUp, isDown, isHome, isEnd,
8
+ isUp, isDown, isHome, isEnd, isRight, isLeft,
9
9
  } from "@ui5/webcomponents-base/dist/Keys.js";
10
10
  import type UDExListItem from "./ListItem.js";
11
11
  import type { UDExScrollIntoViewOptions } from "./types/List.js";
@@ -180,7 +180,7 @@ class UDExList extends UI5Element {
180
180
  onBeforeRendering(): void {
181
181
  this.prepareListItemsMode();
182
182
  this._focusHandler.resetMatchingItems();
183
- this._focusHandler._focusableListItems = this.getItemsWithoutHeader();
183
+ this._focusHandler._focusableListItems = this.getKeyboardNavigationItems();
184
184
  }
185
185
 
186
186
  handleItemPress(e: CustomEvent): void {
@@ -192,6 +192,15 @@ class UDExList extends UI5Element {
192
192
  if (this.tabNavigationEnabled) {
193
193
  return;
194
194
  }
195
+
196
+ if (isRight(e)) {
197
+ this.handleArrowRight(e);
198
+ }
199
+
200
+ if (isLeft(e)) {
201
+ this.handleArrowLeft(e);
202
+ }
203
+
195
204
  if (isUp(e)) {
196
205
  this.handleUpArrow(e);
197
206
  }
@@ -209,6 +218,22 @@ class UDExList extends UI5Element {
209
218
  }
210
219
  }
211
220
 
221
+ handleArrowRight(e: KeyboardEvent): void {
222
+ const target = e.target as UDExListItemBase;
223
+ if ((target.tagName === "UDEX-LIST-GROUP-HEADER" || target.tagName === "UDEX-LIST-ITEM") && target.hasAttribute("collapsible")) {
224
+ target.collapsed = false;
225
+ this.setCollapsedItems(false, target);
226
+ }
227
+ }
228
+
229
+ handleArrowLeft(e: KeyboardEvent): void {
230
+ const target = e.target as UDExListItemBase;
231
+ if ((target.tagName === "UDEX-LIST-GROUP-HEADER" || target.tagName === "UDEX-LIST-ITEM") && target.hasAttribute("collapsible")) {
232
+ target.collapsed = true;
233
+ this.setCollapsedItems(true, target);
234
+ }
235
+ }
236
+
212
237
  handleUpArrow(e: KeyboardEvent): void {
213
238
  e.preventDefault();
214
239
  const items = this.getKeyboardNavigationItems();
@@ -216,7 +241,7 @@ class UDExList extends UI5Element {
216
241
  const lastItemIndex = items.length - 1;
217
242
  const previousSelectIndex = currentSelectedIndex - 1 < 0 ? lastItemIndex : currentSelectedIndex - 1;
218
243
  const isHeaderItem = items[previousSelectIndex].isGroup;
219
- const nonInteractiveHeader = items[previousSelectIndex].nonInteractive;
244
+ const nonInteractiveHeader = items[previousSelectIndex].nonInteractive && !items[previousSelectIndex].collapsible;
220
245
 
221
246
  if (nonInteractiveHeader && previousSelectIndex === 0) {
222
247
  this.unsetTabIndexByIndex(items, currentSelectedIndex);
@@ -269,7 +294,7 @@ class UDExList extends UI5Element {
269
294
  const currentSelectedIndex = this.getCurrentIndex(items, e.target as UDExListItemBase);
270
295
  const nextSelectIndex = currentSelectedIndex + 1 > items.length - 1 ? 0 : currentSelectedIndex + 1;
271
296
  const isHeaderItem = items[nextSelectIndex].isGroup;
272
- const nonInteractiveHeader = items[nextSelectIndex].nonInteractive;
297
+ const nonInteractiveHeader = items[nextSelectIndex].nonInteractive && !items[nextSelectIndex].collapsible;
273
298
 
274
299
  if (nonInteractiveHeader) {
275
300
  this.unsetTabIndexByIndex(items, currentSelectedIndex);
@@ -312,7 +337,7 @@ class UDExList extends UI5Element {
312
337
  const currentSelectedIndex = this.getCurrentIndex(items, e.target as UDExListItemBase);
313
338
  const firstItem = items[0];
314
339
  const isHeaderItem = firstItem.isGroup;
315
- const nonInteractiveItem = firstItem.nonInteractive;
340
+ const nonInteractiveItem = firstItem.nonInteractive && !firstItem.collapsible;
316
341
 
317
342
  if (nonInteractiveItem) {
318
343
  this.unsetTabIndexByIndex(items, currentSelectedIndex);
@@ -401,7 +426,7 @@ class UDExList extends UI5Element {
401
426
  }
402
427
 
403
428
  focusHeader(item: UDExListItemBase): void {
404
- const header = item.shadowRoot?.querySelector(".udex-list__group-header") as HTMLElement;
429
+ const header = item.shadowRoot?.querySelector(".udex-list__group-header-wrap") as HTMLElement;
405
430
  header.focus();
406
431
  }
407
432
 
@@ -425,17 +450,17 @@ class UDExList extends UI5Element {
425
450
  return this.getItemsFromList().filter(item => item.selected);
426
451
  }
427
452
 
428
- getCurrentIndex(items: Array<UDExListItemBase>, item: UDExListItemBase): number {
453
+ getCurrentIndex(items: Array<UDExListItemBase | HTMLElement>, item: UDExListItemBase | HTMLElement): number {
429
454
  return items.indexOf(item);
430
455
  }
431
456
 
432
- getItemsWithoutHeader(): Array<UDExListItemBase> {
433
- return this.getItemsFromList().filter(item => !item.isGroup);
434
- }
435
-
436
457
  getKeyboardNavigationItems(): Array<UDExListItemBase> {
437
- const items = this.modeMultiSelect ? this.getItemsFromList() : this.getItemsWithoutHeader();
438
- return items.filter(item => !item.disabled);
458
+ return this.getItemsFromList().filter(item => {
459
+ const parent = item.parentElement as UDExListItemBase;
460
+ return !item.disabled
461
+ && (!item.isGroup || item.modeMultiSelect || item.collapsible)
462
+ && !(parent?.isGroup && parent.collapsed);
463
+ });
439
464
  }
440
465
 
441
466
  getItemsFromList(): Array<UDExListItemBase> {
@@ -473,8 +498,9 @@ class UDExList extends UI5Element {
473
498
  const isFirstHeaderMultiMode = isFirstHeader && this.modeMultiSelect && !item.nonInteractive;
474
499
  const isFirstItemGroupSingleOrRadioMode = isFirstItemInGroupList && modeSingleOrRadio;
475
500
  const isFirstItemGroupMultiMode = isFirstItemInGroupList && this.modeMultiSelect && listGroupHeader?.nonInteractive;
501
+ const isCollapsibleHeader = item.isGroup && item.collapsible;
476
502
 
477
- if (isFirstHeaderMultiMode || isFirstItemGroupSingleOrRadioMode || isFirstItemGroupMultiMode || isFirstItem) {
503
+ if (isFirstHeaderMultiMode || isFirstItemGroupSingleOrRadioMode || isFirstItemGroupMultiMode || isFirstItem || isCollapsibleHeader) {
478
504
  return "0";
479
505
  }
480
506
 
@@ -487,6 +513,17 @@ class UDExList extends UI5Element {
487
513
  });
488
514
  }
489
515
 
516
+ setCollapsedItems(collapsed: boolean, target: UDExListItemBase): void {
517
+ const items = target.getSlottedNodes<UDExListItemBase>("items");
518
+ items.forEach(item => {
519
+ if (collapsed) {
520
+ item.setAttribute("collapsed", "");
521
+ } else {
522
+ item.removeAttribute("collapsed");
523
+ }
524
+ });
525
+ }
526
+
490
527
  get isGroupList(): boolean {
491
528
  return this.getItemsFromList().some(item => item.isGroup);
492
529
  }
@@ -3,36 +3,109 @@
3
3
  class="udex-list__group"
4
4
  role="group"
5
5
  aria-labelledby="group-heading">
6
- <div
7
- role="listbox"
8
- class="udex-list__group-list"
9
- name="group"
10
- aria-label="group"
11
- @ui5-item-press="{{getHandleGroupItemsClick}}">
12
- {{#if modeMultiSelectOrRadioGroup}}
13
- {{> multi-or-radio-group-header}}
14
- {{else}}
15
- {{> single-group-header}}
16
- {{/if}}
17
- <slot></slot>
18
- </div>
6
+ {{#if collapsible}}
7
+ <div
8
+ class="udex-list__group-list"
9
+ name="group"
10
+ @ui5-item-press="{{getHandleGroupItemsClick}}">
11
+ {{#if modeMultiSelectOrRadioGroup}}
12
+ {{> multi-or-radio-group-header-collapsible}}
13
+ {{else}}
14
+ {{> single-group-header-collapsible}}
15
+ {{/if}}
16
+ <div id="{{ariaControlsId}}" role="region" class="udex-list__group-list__content">
17
+ <div role="listbox" aria-label="group">
18
+ <slot></slot>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ {{else}}
23
+ <div
24
+ role="listbox"
25
+ class="udex-list__group-list"
26
+ name="group"
27
+ aria-label="group"
28
+ @ui5-item-press="{{getHandleGroupItemsClick}}">
29
+ {{#if modeMultiSelectOrRadioGroup}}
30
+ {{> multi-or-radio-group-header}}
31
+ {{else}}
32
+ {{> single-group-header}}
33
+ {{/if}}
34
+ <slot></slot>
35
+ </div>
36
+ {{/if}}
19
37
  </div>
20
38
 
21
39
  {{#*inline "multi-or-radio-group-header"}}
22
40
  {{#if isNonActiveHeader}}
23
- <header id="group-heading" class="udex-list__inactive-header">
41
+ <header id="group-heading" class="udex-list__inactive-header udex-list__group-header-wrap">
42
+ <div class="udex-list__inactive-header-content">
43
+ <span class="udex-list__header-title">{{label}}</span>
44
+ {{#if supportingText}}
45
+ <span class="udex-list__supporting-text">{{supportingText}}</span>
46
+ {{/if}}
47
+ </div>
48
+ </header>
49
+ {{else}}
50
+ <udex-list-item
51
+ id="group-heading"
52
+ _additional-class-name="{{_additionalClassName}}"
53
+ ?selected="{{selected}}"
54
+ _tab-index="{{_effectiveTabIndex}}"
55
+ ?indeterminate="{{indeterminate}}"
56
+ ?_filtered="{{_filtered}}"
57
+ part="group-item"
58
+ role="none"
59
+ class="{{className}}"
60
+ mode="{{mode}}"
61
+ ?controlled="{{controlled}}"
62
+ supporting-text="{{supportingText}}"
63
+ @click="{{handleHeaderPress}}"
64
+ @keydown="{{handleKeyDownPress}}"
65
+ type="{{type}}"
66
+ label="{{label}}"
67
+ _icon="{{_icon}}"
68
+ size="{{size}}">
69
+ </udex-list-item>
70
+ {{/if}}
71
+ {{/inline}}
72
+
73
+ {{#*inline "multi-or-radio-group-header-collapsible"}}
74
+ {{#if isNonActiveHeader}}
75
+ <header role="button" id="group-heading" class="udex-list__inactive-header udex-list__group-header-wrap " tabindex="{{_effectiveTabIndex}}"
76
+ aria-expanded="{{expanded}}" aria-controls="{{ariaControlsId}}">
77
+ <div class="udex-list__inactive-header-content" >
24
78
  <span class="udex-list__header-title">{{label}}</span>
25
79
  {{#if supportingText}}
26
80
  <span class="udex-list__supporting-text ">{{supportingText}}</span>
27
81
  {{/if}}
82
+ </div>
83
+ <div class="udex-list__group-heading__icon-wrapper">
84
+ <udex-button
85
+ size="Small"
86
+ design="Tertiary"
87
+ class="udex-list__group-heading__icon"
88
+ @click="{{handleCollapseIconClick}}"
89
+ tabindex="-1"
90
+ accessible-name="{{expandButtonAccessibleName}}"
91
+ mode="Interactive"
92
+ icon="slim-arrow-right">
93
+ </udex-button>
94
+ </div>
28
95
  </header>
29
96
  {{else}}
30
97
  <udex-list-item
31
98
  id="group-heading"
99
+ aria-expanded="{{expanded}}"
100
+ aria-controls="{{ariaControlsId}}"
101
+ accessible-role="button"
32
102
  _additional-class-name="{{_additionalClassName}}"
33
103
  ?selected="{{selected}}"
34
104
  _tab-index="{{_effectiveTabIndex}}"
35
105
  ?indeterminate="{{indeterminate}}"
106
+ collapsible={{collapsible}}
107
+ ?collapsed={{collapsed}}
108
+ ?_filtered="{{_filtered}}"
36
109
  part="group-item"
37
110
  role="none"
38
111
  class="{{className}}"
@@ -41,6 +114,7 @@
41
114
  supporting-text="{{supportingText}}"
42
115
  @click="{{handleHeaderPress}}"
43
116
  @keydown="{{handleKeyDownPress}}"
117
+ @accordion-icon-click="{{handleCollapseIconClick}}"
44
118
  type="{{type}}"
45
119
  label="{{label}}"
46
120
  _icon="{{_icon}}"
@@ -50,9 +124,7 @@
50
124
  {{/inline}}
51
125
 
52
126
  {{#*inline "single-group-header"}}
53
- <div class="udex-list__group-content {{sizeClass}}" part="group-item">
54
- {{#if typeNumber}}<span class="udex-list__number">{{numberOfItem}}.</span>{{/if}}
55
- {{#if typeCircle}}<span class="udex-list__circle">&#x2022;</span>{{/if}}
127
+ <div class="udex-list__group-content udex-list__group-header-wrap {{sizeClass}}" part="group-item">
56
128
  {{#if typeIcon}}
57
129
  <ui5-icon
58
130
  class="udex-list__icon"
@@ -70,3 +142,42 @@
70
142
  </div>
71
143
  </div>
72
144
  {{/inline}}
145
+
146
+ {{#*inline "single-group-header-collapsible"}}
147
+ <div class="udex-list__group-content udex-list__group-header-wrap {{sizeClass}}" part="group-item"
148
+ id="{{this._id}}_group-content__focusable"
149
+ role="button"
150
+ tabindex="0"
151
+ @keydown="{{handleKeyDown}}"
152
+ _tab-index="{{_effectiveTabIndex}}"
153
+ aria-expanded="{{expanded}}"
154
+ aria-controls="{{ariaControlsId}}">
155
+ {{#if typeIcon}}
156
+ <ui5-icon
157
+ class="udex-list__icon"
158
+ name="{{_icon}}"
159
+ accessible-role="presentation"
160
+ aria-hidden="true"
161
+ part="icon">
162
+ </ui5-icon>
163
+ {{/if}}
164
+ <div class="udex-list__header">
165
+ <span id="group-heading" class="udex-list__header-title">{{label}}</span>
166
+ {{#if supportingText}}
167
+ <span class="udex-list__supporting-text {{sizeClass}}">{{supportingText}}</span>
168
+ {{/if}}
169
+ </div>
170
+ <div class="udex-list__group-heading__icon-wrapper">
171
+ <udex-button
172
+ size="Small"
173
+ design="Tertiary"
174
+ class="udex-list__group-heading__icon"
175
+ @click="{{handleCollapseIconClick}}"
176
+ tabindex="-1"
177
+ accessible-name="{{expandButtonAccessibleName}}"
178
+ mode="Interactive"
179
+ icon="slim-arrow-right">
180
+ </udex-button>
181
+ </div>
182
+ </div>
183
+ {{/inline}}
@@ -1,12 +1,16 @@
1
1
  import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
2
2
  import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js";
3
3
  import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
4
- import { isEnter, isSpace } from "@ui5/webcomponents-base/dist/Keys.js";
4
+ import {
5
+ isEnter, isLeft, isRight, isSpace,
6
+ } from "@ui5/webcomponents-base/dist/Keys.js";
5
7
  import Icon from "@ui5/webcomponents/dist/Icon.js";
8
+ import "@ui5/webcomponents-icons/dist/slim-arrow-right.js";
6
9
  import UDExListGroupHeaderBase from "./ListGroupHeaderBase.js";
7
10
  import ListGroupHeaderTemplate from "./generated/templates/ListGroupHeaderTemplate.lit.js";
8
11
  import { UDExListItemSize } from "./types/List.js";
9
12
  import type { UDExListItemBaseEvents } from "./ListItemBase.js";
13
+ import type UDExListItemBase from "./ListItemBase.js";
10
14
 
11
15
  // Styles
12
16
  import ListGroupHeaderCss from "./generated/themes/ListGroupHeader.css.js";
@@ -73,6 +77,12 @@ class UDExListGroupHeader extends UDExListGroupHeaderBase {
73
77
  }
74
78
  }
75
79
 
80
+ handleKeyDown(e: KeyboardEvent) {
81
+ if (isRight(e) || isLeft(e)) {
82
+ this.handleCollapseIconClick(e);
83
+ }
84
+ }
85
+
76
86
  fireHeaderPress() {
77
87
  this.fireDecoratorEvent("header-press", {
78
88
  item: this,
@@ -84,6 +94,26 @@ class UDExListGroupHeader extends UDExListGroupHeaderBase {
84
94
  return hasHandle ? this.handleHeaderState() : undefined;
85
95
  }
86
96
 
97
+ setCollapsedItems(): void {
98
+ const items = this.getSlottedNodes<UDExListItemBase>("items");
99
+ items.forEach(item => {
100
+ if (this.collapsed) {
101
+ item.setAttribute("collapsed", "");
102
+ } else {
103
+ item.removeAttribute("collapsed");
104
+ }
105
+ });
106
+ }
107
+
108
+ handleCollapseIconClick(e: MouseEvent | KeyboardEvent) {
109
+ e.stopPropagation();
110
+ e.preventDefault();
111
+ this.setContentHeight();
112
+ this.collapsed = !this.collapsed;
113
+ this.setCollapsedItems();
114
+ this.fireDecoratorEvent("accordion-icon-click", { collapsed: this.collapsed });
115
+ }
116
+
87
117
  get sizeClass(): string {
88
118
  return this.size === UDExListItemSize.Large ? listGroupLargeClass : "";
89
119
  }
@@ -187,7 +187,7 @@ class UDExListGroupHeaderBase extends UDExListItemBase {
187
187
 
188
188
  get className(): string {
189
189
  const controlledClassName = this.controlled ? `${listGroupHeaderClass}_controlled` : "";
190
- return `${listGroupHeaderClass} ${this._additionalClassName} ${controlledClassName}`;
190
+ return `${listGroupHeaderClass} ${this._additionalClassName} ${controlledClassName} ${listGroupHeaderClass}-wrap`;
191
191
  }
192
192
 
193
193
  get listItem(): UDExListItemBase {
package/src/ListItem.hbs CHANGED
@@ -56,8 +56,6 @@
56
56
  <span class="udex-list__flag" style="background-position: {{flagPosition}}"></span>
57
57
  </div>
58
58
  {{/if}}
59
- {{#if typeNumber}}<span class="udex-list__number">{{numberOfItem}}.</span>{{/if}}
60
- {{#if typeCircle}}<span class="udex-list__circle">&#x2022;</span>{{/if}}
61
59
  {{#if typeIcon}}
62
60
  <ui5-icon
63
61
  class="udex-list__icon"
@@ -112,6 +110,21 @@
112
110
  <slot name="secondIcon" @click={{_fireIconClickEvent}}></slot>
113
111
  {{/if}}
114
112
  {{/if}}
113
+ {{#if collapsible}}
114
+ <div class="udex-list__group-heading__icon-wrapper">
115
+ <udex-button
116
+ size="Small"
117
+ design="Tertiary"
118
+ @mousedown="{{handleCollapseIconMouseDown}}"
119
+ @click="{{handleCollapseIconClick}}"
120
+ mode="Interactive"
121
+ tabindex="-1"
122
+ accessible-name="{{expandButtonAccessibleName}}"
123
+ class="udex-list__group-heading__icon"
124
+ icon="slim-arrow-right">
125
+ </udex-button>
126
+ </div>
127
+ {{/if}}
115
128
  </div>
116
129
  <div class="hidden" id="{{this._id}}-invisibleText">{{accessibleListItemName}}</div>
117
130
  <div class="hidden" id="{{this._id}}-invisibleText-describedby">{{itemState}}</div>
package/src/ListItem.ts CHANGED
@@ -277,7 +277,7 @@ class UDExListItem extends UDExListItemBase {
277
277
  }
278
278
 
279
279
  handleKeyDown(e: KeyboardEvent) {
280
- if (this.firstIconElement === e.target || this.secondIconElement === e.target) {
280
+ if (this.firstIconElement === e.target || this.secondIconElement === e.target || (e.target as HTMLElement).classList.contains("udex-list__group-heading__icon")) {
281
281
  return;
282
282
  }
283
283