@sapudex/web-components 2.11.0 → 2.12.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 (131) hide show
  1. package/cypress/fixtures/profile-menu.ts +75 -0
  2. package/cypress/specs/ListItem.cy.tsx +66 -52
  3. package/cypress/specs/MastheadProfileMenu.cy.tsx +174 -0
  4. package/cypress/specs/SelectBox.cy.tsx +134 -66
  5. package/cypress/support/component-imports.instrumented.ts +4 -0
  6. package/cypress/support/component-imports.src.ts +4 -0
  7. package/dist/Button.d.ts +8 -0
  8. package/dist/Button.js +11 -0
  9. package/dist/Button.js.map +1 -1
  10. package/dist/List.d.ts +9 -2
  11. package/dist/List.js +19 -8
  12. package/dist/List.js.map +1 -1
  13. package/dist/ListGroupHeader.d.ts +2 -1
  14. package/dist/ListGroupHeader.js.map +1 -1
  15. package/dist/ListItem.d.ts +12 -1
  16. package/dist/ListItem.js +15 -1
  17. package/dist/ListItem.js.map +1 -1
  18. package/dist/ListItemBase.d.ts +10 -0
  19. package/dist/ListItemBase.js +31 -0
  20. package/dist/ListItemBase.js.map +1 -1
  21. package/dist/ListSelectAll.d.ts +2 -1
  22. package/dist/ListSelectAll.js.map +1 -1
  23. package/dist/MastheadItem.d.ts +2 -0
  24. package/dist/MastheadItem.js +6 -0
  25. package/dist/MastheadItem.js.map +1 -1
  26. package/dist/MastheadProfileMenu.d.ts +67 -3
  27. package/dist/MastheadProfileMenu.js +164 -10
  28. package/dist/MastheadProfileMenu.js.map +1 -1
  29. package/dist/MastheadShell.d.ts +1 -0
  30. package/dist/MastheadShell.js +6 -1
  31. package/dist/MastheadShell.js.map +1 -1
  32. package/dist/SearchableListBase.d.ts +16 -0
  33. package/dist/SearchableListBase.js +31 -1
  34. package/dist/SearchableListBase.js.map +1 -1
  35. package/dist/SelectBox.js +10 -0
  36. package/dist/SelectBox.js.map +1 -1
  37. package/dist/SelectBoxItem.d.ts +29 -0
  38. package/dist/SelectBoxItem.js +26 -0
  39. package/dist/SelectBoxItem.js.map +1 -1
  40. package/dist/StatusBadge.d.ts +1 -7
  41. package/dist/StatusBadge.js +1 -8
  42. package/dist/StatusBadge.js.map +1 -1
  43. package/dist/StepInputTemplate.js +1 -1
  44. package/dist/StepInputTemplate.js.map +1 -1
  45. package/dist/assets/{InputSuggestions-9WQMOg4t.js → InputSuggestions-DtUQULbo.js} +1 -1
  46. package/dist/assets/{ListItemStandardExpandableTextTemplate-BQaMMo_n.js → ListItemStandardExpandableTextTemplate-B62PaSFk.js} +1 -1
  47. package/dist/assets/{bundle.esm-ZNiP-jPI.js → bundle.esm-Ba8g4ech.js} +210 -210
  48. package/dist/assets/messagebundle_en-PmkE-Vht.js +1 -0
  49. package/dist/css/themes/Button.css +1 -1
  50. package/dist/css/themes/ListItem.css +1 -1
  51. package/dist/css/themes/MastheadProfileMenu.css +1 -1
  52. package/dist/css/themes/RatingIndicator.css +1 -1
  53. package/dist/css/themes/Slider.css +1 -1
  54. package/dist/css/themes/StepInput.css +1 -1
  55. package/dist/custom-elements-internal.json +1039 -255
  56. package/dist/custom-elements.json +867 -237
  57. package/dist/generated/assets/i18n/messagebundle_en.json +1 -1
  58. package/dist/generated/i18n/i18n-defaults.d.ts +5 -1
  59. package/dist/generated/i18n/i18n-defaults.js +5 -1
  60. package/dist/generated/i18n/i18n-defaults.js.map +1 -1
  61. package/dist/generated/templates/ListItemTemplate.lit.js +31 -23
  62. package/dist/generated/templates/ListItemTemplate.lit.js.map +1 -1
  63. package/dist/generated/templates/ListTemplate.lit.js +2 -2
  64. package/dist/generated/templates/ListTemplate.lit.js.map +1 -1
  65. package/dist/generated/templates/MastheadProfileMenuTemplate.lit.js +11 -6
  66. package/dist/generated/templates/MastheadProfileMenuTemplate.lit.js.map +1 -1
  67. package/dist/generated/templates/SearchableListBaseTemplate.lit.js +6 -6
  68. package/dist/generated/templates/SearchableListBaseTemplate.lit.js.map +1 -1
  69. package/dist/generated/themes/Button.css.d.ts +1 -1
  70. package/dist/generated/themes/Button.css.js +1 -1
  71. package/dist/generated/themes/Button.css.js.map +1 -1
  72. package/dist/generated/themes/ListItem.css.d.ts +1 -1
  73. package/dist/generated/themes/ListItem.css.js +1 -1
  74. package/dist/generated/themes/ListItem.css.js.map +1 -1
  75. package/dist/generated/themes/MastheadProfileMenu.css.d.ts +1 -1
  76. package/dist/generated/themes/MastheadProfileMenu.css.js +1 -1
  77. package/dist/generated/themes/MastheadProfileMenu.css.js.map +1 -1
  78. package/dist/generated/themes/RatingIndicator.css.d.ts +1 -1
  79. package/dist/generated/themes/RatingIndicator.css.js +1 -1
  80. package/dist/generated/themes/RatingIndicator.css.js.map +1 -1
  81. package/dist/generated/themes/Slider.css.d.ts +1 -1
  82. package/dist/generated/themes/Slider.css.js +1 -1
  83. package/dist/generated/themes/Slider.css.js.map +1 -1
  84. package/dist/generated/themes/StepInput.css.d.ts +1 -1
  85. package/dist/generated/themes/StepInput.css.js +1 -1
  86. package/dist/generated/themes/StepInput.css.js.map +1 -1
  87. package/dist/messagebundle.properties +4 -0
  88. package/dist/messagebundle_en.properties +4 -0
  89. package/dist/types/StatusBadgeValueState.d.ts +8 -0
  90. package/dist/types/StatusBadgeValueState.js +10 -0
  91. package/dist/types/StatusBadgeValueState.js.map +1 -0
  92. package/dist/vscode.html-custom-data.json +83 -16
  93. package/dist/web-types.json +374 -30
  94. package/package.json +1 -1
  95. package/src/Button.ts +10 -0
  96. package/src/List.hbs +0 -2
  97. package/src/List.ts +27 -8
  98. package/src/ListGroupHeader.ts +2 -1
  99. package/src/ListItem.hbs +16 -2
  100. package/src/ListItem.ts +29 -2
  101. package/src/ListItemBase.ts +42 -0
  102. package/src/ListSelectAll.ts +2 -1
  103. package/src/MastheadItem.ts +9 -0
  104. package/src/MastheadProfileMenu.hbs +79 -15
  105. package/src/MastheadProfileMenu.ts +228 -13
  106. package/src/MastheadShell.ts +7 -1
  107. package/src/SearchableListBase.hbs +18 -1
  108. package/src/SearchableListBase.ts +47 -1
  109. package/src/SelectBox.ts +11 -0
  110. package/src/SelectBoxItem.ts +39 -0
  111. package/src/StatusBadge.ts +1 -8
  112. package/src/StepInputTemplate.tsx +1 -1
  113. package/src/generated/i18n/i18n-defaults.ts +2 -2
  114. package/src/generated/templates/ListItemTemplate.lit.ts +31 -23
  115. package/src/generated/templates/ListTemplate.lit.ts +2 -2
  116. package/src/generated/templates/MastheadProfileMenuTemplate.lit.ts +10 -5
  117. package/src/generated/templates/SearchableListBaseTemplate.lit.ts +6 -6
  118. package/src/generated/themes/Button.css.ts +1 -1
  119. package/src/generated/themes/ListItem.css.ts +1 -1
  120. package/src/generated/themes/MastheadProfileMenu.css.ts +1 -1
  121. package/src/generated/themes/RatingIndicator.css.ts +1 -1
  122. package/src/generated/themes/Slider.css.ts +1 -1
  123. package/src/generated/themes/StepInput.css.ts +1 -1
  124. package/src/i18n/messagebundle.properties +4 -0
  125. package/src/i18n/messagebundle_en.properties +4 -0
  126. package/src/themes/Button.css +13 -0
  127. package/src/themes/ListItem.css +4 -9
  128. package/src/themes/MastheadProfileMenu.css +87 -3
  129. package/src/themes/StepInput.css +10 -0
  130. package/src/types/StatusBadgeValueState.ts +9 -0
  131. package/dist/assets/messagebundle_en-DwlTjyni.js +0 -1
@@ -6,16 +6,28 @@ 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 i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js";
8
8
  import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
9
- import { LOGOUT } from "./generated/i18n/i18n-defaults.js";
9
+ import {
10
+ LOGOUT, SWITCH_ACCOUNT, BACK, OTHER_IDENTITIES, ADD_OR_REMOVE_ACCOUNT,
11
+ } from "./generated/i18n/i18n-defaults.js";
12
+ import { isEscape } from "@ui5/webcomponents-base/Keys.js";
10
13
  import UDExMastheadMenu from "./MastheadMenu.js";
14
+ import UDExButton from "./Button.js";
15
+ import UDExList from "./List.js";
16
+ import UDExListItem from "./ListItem.js";
17
+ import UDExMastheadMenuItem from "./MastheadMenuItem.js";
11
18
  import MastheadProfileMenuTemplate from "./generated/templates/MastheadProfileMenuTemplate.lit.js";
12
- import type UDExMastheadMenuItem from "./MastheadMenuItem.js";
13
19
  import parseArrayFromString from "./utils/parseArrayFromString.js";
14
20
  import AnalyticsName from "./types/AnalyticsName.js";
15
21
  import type UDExMastheadShell from "./MastheadShell.js";
16
-
22
+ import "@ui5/webcomponents-icons/dist/slim-arrow-right.js";
23
+ import "@ui5/webcomponents-icons/dist/action.js";
24
+ import type { LinkClickEventDetail } from "@ui5/webcomponents/dist/Link.js";
17
25
  // Styles
18
26
  import MastheadProfileMenuCss from "./generated/themes/MastheadProfileMenu.css.js";
27
+ import UDExStatusBadgeValueState from "./types/StatusBadgeValueState.js";
28
+ import type { ResizeObserverCallback } from "@ui5/webcomponents-base/delegate/ResizeHandler.js";
29
+ import ResizeHandler from "@ui5/webcomponents-base/delegate/ResizeHandler.js";
30
+ import { BreakpointUtils } from "./utils/Breakpoints.js";
19
31
 
20
32
  interface UserData {
21
33
  name?: string,
@@ -25,6 +37,24 @@ interface UserData {
25
37
  avatarInitials?: string
26
38
  }
27
39
 
40
+ interface UserIdentity {
41
+ avatarUrl: string,
42
+ email: string,
43
+ name: string,
44
+ idsUser: string,
45
+ isLogged: boolean,
46
+ }
47
+
48
+ interface ExtendedUserIdentity extends UserIdentity {
49
+ supportingText: string;
50
+ statusBadge: string;
51
+ }
52
+
53
+ type UDExMastheadProfileMenuIdentityClickEventDetail = {
54
+ item: ExtendedUserIdentity;
55
+ analyticsName: AnalyticsName,
56
+ };
57
+
28
58
  type UDExMastheadProfileMenuItemClickEventDetail = {
29
59
  item: UDExMastheadMenuItem,
30
60
  originalEvent: PointerEvent,
@@ -32,6 +62,10 @@ type UDExMastheadProfileMenuItemClickEventDetail = {
32
62
  sourceNode: HTMLElement,
33
63
  }
34
64
 
65
+ type UDExMastheadProfileMenuAddOrRemoveClickEventDetail = {
66
+ analyticsName: AnalyticsName,
67
+ }
68
+
35
69
  /**
36
70
  * @class
37
71
  *
@@ -54,27 +88,59 @@ type UDExMastheadProfileMenuItemClickEventDetail = {
54
88
  renderer: litRender,
55
89
  styles: [UDExMastheadMenu.styles, MastheadProfileMenuCss],
56
90
  template: MastheadProfileMenuTemplate,
57
- dependencies: [UDExMastheadMenu],
91
+ dependencies: [
92
+ UDExMastheadMenuItem,
93
+ UDExMastheadMenu,
94
+ UDExListItem,
95
+ UDExButton,
96
+ UDExList,
97
+ ],
58
98
  })
59
99
 
60
100
  /**
61
101
  * Fired when use click Logout link
62
102
  * @public
63
103
  */
64
- @event("logout", { bubbles: true })
104
+ @event("logout", { cancelable: true, bubbles: true })
65
105
 
66
106
  /**
67
107
  * Fires when profile menu item is clicked
68
108
  *
69
109
  * @public
70
110
  */
71
- @event("profile-item-click", { bubbles: true })
111
+ @event("profile-item-click", { cancelable: true, bubbles: true })
112
+
113
+ /**
114
+ * Fired when use click add or remove account button
115
+ *
116
+ * @public
117
+ */
118
+ @event("add-or-remove-account-click", { cancelable: true, bubbles: true })
119
+
120
+ /**
121
+ * Fires when identity item is clicked
122
+ *
123
+ * @public
124
+ */
125
+ @event("identity-item-click", { cancelable: true, bubbles: true })
72
126
 
73
127
  class UDExMastheadProfileMenu extends UI5Element {
74
128
  eventDetails!: {
75
129
  "logout": UDExMastheadProfileMenuItemClickEventDetail,
76
- "profile-item-click": UDExMastheadProfileMenuItemClickEventDetail
130
+ "profile-item-click": UDExMastheadProfileMenuItemClickEventDetail,
131
+ "add-or-remove-account-click": UDExMastheadProfileMenuAddOrRemoveClickEventDetail,
132
+ "identity-item-click": UDExMastheadProfileMenuIdentityClickEventDetail,
77
133
  };
134
+
135
+ /**
136
+ * Defines the object of user identities
137
+ *
138
+ * @default ""
139
+ * @public
140
+ */
141
+ @property()
142
+ identities!: string;
143
+
78
144
  /**
79
145
  * Defines the object of link values
80
146
  *
@@ -110,6 +176,14 @@ class UDExMastheadProfileMenu extends UI5Element {
110
176
  @property({ type: Boolean })
111
177
  _isMobileMode!: boolean;
112
178
 
179
+ /**
180
+ * Defines the open identities panel state
181
+ *
182
+ * @private
183
+ */
184
+ @property({ type: Boolean })
185
+ _openIdentities: boolean = false;
186
+
113
187
  /**
114
188
  * Placeholder for message strip.
115
189
  *
@@ -122,25 +196,115 @@ class UDExMastheadProfileMenu extends UI5Element {
122
196
  static i18nBundle: I18nBundle;
123
197
 
124
198
  _mastheadShell!: UDExMastheadShell;
199
+ _handleResizeBound: ResizeObserverCallback;
200
+ _shouldFocusBackBtn!: boolean;
201
+ _shouldFocusSwitchBtn!: boolean;
202
+
203
+ constructor() {
204
+ super();
205
+ this._handleResizeBound = this.handleResize.bind(this);
206
+ }
125
207
 
126
208
  onAfterRendering(): void {
127
209
  this._mastheadShell = this.mastheadShell;
210
+ this.updateFocusState(this._shouldFocusBackBtn, this.focusBackBtn.bind(this));
211
+ this.updateFocusState(this._shouldFocusSwitchBtn, this.focusSwitchBtn.bind(this));
212
+ this.setMenuItemsMobileMode();
213
+ }
214
+
215
+ onEnterDOM(): void {
216
+ ResizeHandler.register(this, this._handleResizeBound);
217
+ }
218
+
219
+ onExitDOM(): void {
220
+ ResizeHandler.deregister(this, this._handleResizeBound);
221
+ }
222
+
223
+ handleResize(): void {
224
+ this._isMobileMode = this.isMobile;
225
+
226
+ if (this.profileMenuLinks) {
227
+ this.profileMenuLinks._isMobileMode = this.isMobile;
228
+ }
229
+ }
230
+
231
+ handleSwitcherClick(): void {
232
+ this._openIdentities = !this._openIdentities;
233
+ this._shouldFocusBackBtn = this._openIdentities;
234
+ this._shouldFocusSwitchBtn = !this._openIdentities;
128
235
  }
129
236
 
130
237
  handleUserLogoutItemClick(e: PointerEvent): void {
131
238
  this.fireLogoutItemClick(e);
132
- if (this.shouldCloseMenu) {
239
+ if (this._isMobileMode) {
133
240
  this.closeMenu();
134
241
  }
135
242
  }
136
243
 
137
244
  handleProfileMenuItemClick(e: CustomEvent): void {
138
245
  this.fireMenuItemClick(e);
139
- if (this.shouldCloseMenu) {
246
+ if (this._isMobileMode) {
247
+ this.closeMenu();
248
+ }
249
+ }
250
+
251
+ updateFocusState(shouldFocus: boolean, focusMethod: () => void): void {
252
+ if (shouldFocus) {
253
+ focusMethod();
254
+ if (focusMethod === this.focusBackBtn) {
255
+ this._shouldFocusBackBtn = false;
256
+ } else if (focusMethod === this.focusSwitchBtn) {
257
+ this._shouldFocusSwitchBtn = false;
258
+ }
259
+ }
260
+ }
261
+
262
+ handleKeydown(e: KeyboardEvent): void {
263
+ if (isEscape(e) && this._openIdentities) {
264
+ this.closeIdentitiesPanel();
265
+ }
266
+ }
267
+
268
+ focusSwitchBtn(): void {
269
+ this.focusElement(".udex-masthead-profile-menu__btn-switcher");
270
+ }
271
+
272
+ focusBackBtn(): void {
273
+ this.focusElement(".udex-masthead-profile-menu__btn-back");
274
+ }
275
+
276
+ focusElement(selector: string): void {
277
+ const element = this.shadowRoot?.querySelector<UDExButton>(selector);
278
+ element?.focus();
279
+ }
280
+
281
+ fireEventIdentityItemClick(e: CustomEvent): void {
282
+ const { item } = e.detail;
283
+ const identity = this.identitiesList.find(({ idsUser }) => idsUser === item.id);
284
+ const eventPrevented = !this.fireDecoratorEvent("identity-item-click", {
285
+ item: identity!,
286
+ analyticsName: AnalyticsName.Header,
287
+ });
288
+
289
+ if (eventPrevented) {
290
+ e.preventDefault();
291
+ }
292
+
293
+ if (this._isMobileMode) {
140
294
  this.closeMenu();
141
295
  }
142
296
  }
143
297
 
298
+ fireEventAddOrRemoveAccountClick(e: CustomEvent<LinkClickEventDetail>): void {
299
+ const eventPrevented = !this.fireDecoratorEvent("add-or-remove-account-click", {
300
+ analyticsName: AnalyticsName.Header,
301
+ });
302
+
303
+ if (eventPrevented) {
304
+ e.preventDefault();
305
+ }
306
+ }
307
+
144
308
  fireLogoutItemClick(e: PointerEvent): void {
145
309
  const item = e.target as UDExMastheadMenuItem;
146
310
 
@@ -168,8 +332,14 @@ class UDExMastheadProfileMenu extends UI5Element {
168
332
  this._mastheadShell.mobileBtn?.focus();
169
333
  }
170
334
 
171
- get shouldCloseMenu(): boolean {
172
- return this._mastheadShell && this._mastheadShell.isMobileMenuMode;
335
+ closeIdentitiesPanel(): void {
336
+ this._openIdentities = false;
337
+ }
338
+
339
+ setMenuItemsMobileMode(): void {
340
+ if (this._isMobileMode && this.profileMenuLinks) {
341
+ this.profileMenuLinks._isMobileMode = true;
342
+ }
173
343
  }
174
344
 
175
345
  get linksList(): string {
@@ -178,10 +348,22 @@ class UDExMastheadProfileMenu extends UI5Element {
178
348
  }]) : "";
179
349
  }
180
350
 
351
+ get hasIdentities(): boolean {
352
+ return !!this.identities?.length;
353
+ }
354
+
181
355
  get userData(): UserData {
182
356
  return parseArrayFromString(this.loggedInUser) as UserData;
183
357
  }
184
358
 
359
+ get identitiesList(): Array<ExtendedUserIdentity> {
360
+ return parseArrayFromString<ExtendedUserIdentity>(this.identities).map((identity: UserIdentity) => ({
361
+ ...identity,
362
+ statusBadge: identity.isLogged ? "" : UDExStatusBadgeValueState.Warning,
363
+ supportingText: [identity.name, identity.idsUser].filter(Boolean).join(", "),
364
+ }));
365
+ }
366
+
185
367
  get messageAvailable(): boolean {
186
368
  return !!this.message.length;
187
369
  }
@@ -190,13 +372,46 @@ class UDExMastheadProfileMenu extends UI5Element {
190
372
  return !!this.logoutUrl?.length;
191
373
  }
192
374
 
193
- get logoutText(): string {
194
- return UDExMastheadProfileMenu.i18nBundle.getText(LOGOUT);
375
+ get rootClass(): string {
376
+ const root = "udex-masthead-profile-menu";
377
+ return this._openIdentities ? `${root} ${root}_switcher` : root;
195
378
  }
196
379
 
197
380
  get mastheadShell(): UDExMastheadShell {
198
381
  return document.querySelector<UDExMastheadShell>("[udex-masthead-shell]")!;
199
382
  }
383
+
384
+ get profileMenuLinks(): UDExMastheadMenu | undefined | null {
385
+ return this.shadowRoot?.querySelector<UDExMastheadMenu>("[udex-masthead-menu]");
386
+ }
387
+
388
+ get btnBackText(): string {
389
+ return this._isMobileMode ? this.switcherAccountText : UDExMastheadProfileMenu.i18nBundle.getText(BACK);
390
+ }
391
+
392
+ get listTitleText(): string {
393
+ return `${UDExMastheadProfileMenu.i18nBundle.getText(OTHER_IDENTITIES)} (${this.identitiesList.length})`;
394
+ }
395
+
396
+ get addOrRemoveAccountText(): string {
397
+ return UDExMastheadProfileMenu.i18nBundle.getText(ADD_OR_REMOVE_ACCOUNT);
398
+ }
399
+
400
+ get switcherAccountText(): string {
401
+ return UDExMastheadProfileMenu.i18nBundle.getText(SWITCH_ACCOUNT);
402
+ }
403
+
404
+ get logoutText(): string {
405
+ return UDExMastheadProfileMenu.i18nBundle.getText(LOGOUT);
406
+ }
407
+
408
+ get isAtMostBreakpointSizeM(): boolean {
409
+ return BreakpointUtils.isAtMost("M");
410
+ }
411
+
412
+ get isMobile(): boolean {
413
+ return this.isAtMostBreakpointSizeM || this.mastheadShell?.isMobileMenuMode;
414
+ }
200
415
  }
201
416
 
202
417
  UDExMastheadProfileMenu.define();
@@ -540,6 +540,7 @@ class UDExMastheadShell extends UI5Element {
540
540
 
541
541
  if (this.isMobileMenuMode) {
542
542
  this.setMobileMenuHeight();
543
+ this.setProfileMobileMode();
543
544
  }
544
545
 
545
546
  this._shouldHandleResize = true;
@@ -861,6 +862,12 @@ class UDExMastheadShell extends UI5Element {
861
862
  this.style.setProperty(UDExMastheadVariable.mobileMenuHeight, mobileMenuHeight);
862
863
  }
863
864
 
865
+ setProfileMobileMode(): void {
866
+ if (this.profileMenu) {
867
+ this.profileMenu._isMobileMode = this.isMobileMenuMode;
868
+ }
869
+ }
870
+
864
871
  removeMobileMode(): void {
865
872
  this._isMobileMode = false;
866
873
  this.slottedItems.forEach((item: MastheadSlottedItem) => {
@@ -951,7 +958,6 @@ class UDExMastheadShell extends UI5Element {
951
958
  this.profileMenu,
952
959
  this.cartItem,
953
960
  this.supportItem,
954
- this.profileMenu,
955
961
  this.profileMenuLinks,
956
962
  this.countrySelectorItem,
957
963
  this.countrySelectorMenu,
@@ -30,6 +30,7 @@
30
30
  role="{{roleForGroupList}}"
31
31
  accessible-role="{{accessibleRoleForList}}"
32
32
  class="udex-filter-menu__list"
33
+ ?tab-navigation-enabled="{{tabNavigationEnabled}}"
33
34
  ?controlled="{{isControlled}}"
34
35
  mode="{{mode}}">
35
36
  {{#each _filteredItems}}
@@ -43,7 +44,9 @@
43
44
  supporting-text="{{this.item.supportingText}}"
44
45
  ?disabled="{{this.item.disabled}}"
45
46
  ?selected="{{this.item.selected}}"
46
- ?indeterminate="{{this.item.indeterminate}}">
47
+ ?indeterminate="{{this.item.indeterminate}}"
48
+ @ui5-first-icon-click="{{../fireFirstIconClickEvent}}"
49
+ @ui5-second-icon-click="{{../fireSecondIconClickEvent}}">
47
50
  {{#each this.groupItems}}
48
51
  <udex-list-item
49
52
  role="{{../listItemRole}}"
@@ -51,7 +54,11 @@
51
54
  data-token-id="{{this._id}}"
52
55
  ?controlled="{{this.controlled}}"
53
56
  mode="{{this.mode}}"
57
+ @ui5-first-icon-click="{{../fireFirstIconClickEvent}}"
58
+ @ui5-second-icon-click="{{../fireSecondIconClickEvent}}"
54
59
  supporting-text="{{this.supportingText}}"
60
+ additional-text="{{this.additionalText}}"
61
+ additional-text-state="{{this.additionalTextState}}"
55
62
  ?divider="{{this.divider}}"
56
63
  ?disabled="{{this.disabled}}"
57
64
  ?selected="{{this.selected}}"
@@ -72,6 +79,8 @@
72
79
  ?controlled="{{this.item.controlled}}"
73
80
  ?disabled="{{this.item.disabled}}"
74
81
  ?selected="{{this.item.selected}}"
82
+ @ui5-first-icon-click="{{../fireFirstIconClickEvent}}"
83
+ @ui5-second-icon-click="{{../fireSecondIconClickEvent}}"
75
84
  ?indeterminate="{{this.item.indeterminate}}">
76
85
  {{#each this.groupItems}}
77
86
  <udex-list-item
@@ -80,6 +89,10 @@
80
89
  ?controlled="{{this.controlled}}"
81
90
  mode="{{this.mode}}"
82
91
  supporting-text="{{this.supportingText}}"
92
+ additional-text="{{this.additionalText}}"
93
+ additional-text-state="{{this.additionalTextState}}"
94
+ @ui5-first-icon-click="{{../fireFirstIconClickEvent}}"
95
+ @ui5-second-icon-click="{{../fireSecondIconClickEvent}}"
83
96
  ?divider="{{this.divider}}"
84
97
  ?disabled="{{this.disabled}}"
85
98
  ?selected="{{this.selected}}"
@@ -92,8 +105,12 @@
92
105
  {{else}}
93
106
  <udex-list-item
94
107
  role="none"
108
+ @ui5-first-icon-click="{{../fireFirstIconClickEvent}}"
109
+ @ui5-second-icon-click="{{../fireSecondIconClickEvent}}"
95
110
  data-token-id="{{this.item._id}}"
96
111
  supporting-text="{{this.item.supportingText}}"
112
+ additional-text="{{this.item.additionalText}}"
113
+ additional-text-state="{{this.item.additionalTextState}}"
97
114
  ?disabled="{{this.item.disabled}}"
98
115
  ?controlled="{{this.controlled}}"
99
116
  ?divider="{{this.divider}}"
@@ -36,6 +36,13 @@ export type UDExSearchableListBaseEvents = {
36
36
  "submit-search": UDExSearchableListBaseSubmitSearchEventDetail,
37
37
  "reset-search": void,
38
38
  "change-search": UDExSearchableListBaseChangeSearchEventDetail,
39
+ "first-icon-click": UDExSelectBoxIconClickEventDetail,
40
+ "second-icon-click": UDExSelectBoxIconClickEventDetail,
41
+ }
42
+
43
+ type UDExSelectBoxIconClickEventDetail = {
44
+ originalEvent: PointerEvent,
45
+ item: UDExItemFromList,
39
46
  }
40
47
 
41
48
  /**
@@ -85,8 +92,31 @@ export type UDExSearchableListBaseEvents = {
85
92
  */
86
93
  @event("change-search", { bubbles: true })
87
94
 
95
+ /**
96
+ * Fired event when the user clicks on the first icon.
97
+ *
98
+ * @public
99
+ */
100
+ @event("first-icon-click", { bubbles: true })
101
+
102
+ /**
103
+ * Fired event when the user clicks on the second icon.
104
+ *
105
+ * @public
106
+ */
107
+ @event("second-icon-click", { bubbles: true })
108
+
88
109
  class UDExSearchableListBase extends UI5Element {
89
110
  eventDetails!: UDExSearchableListBaseEvents;
111
+ /**
112
+ * Enables tab navigation for the list.
113
+ *
114
+ * @default ""
115
+ * @public
116
+ */
117
+ @property({ type: Boolean })
118
+ tabNavigationEnabled?: boolean;
119
+
90
120
  /**
91
121
  * Allows control over the height.
92
122
  * @public
@@ -215,7 +245,7 @@ class UDExSearchableListBase extends UI5Element {
215
245
  }
216
246
 
217
247
  onItemPress(e:CustomEvent) {
218
- const dropdownItemId: string = e.detail.item.getAttribute("data-token-id");
248
+ const dropdownItemId: string = this.getDataTokenId(e);
219
249
  this.handleDropdownItemPress(dropdownItemId);
220
250
  this.fireSelectionChange(dropdownItemId);
221
251
  }
@@ -458,6 +488,22 @@ class UDExSearchableListBase extends UI5Element {
458
488
  }
459
489
  }
460
490
 
491
+ fireFirstIconClickEvent(e: CustomEvent): void {
492
+ this._fireIconClickEvent("first-icon-click", e);
493
+ }
494
+
495
+ fireSecondIconClickEvent(e: CustomEvent): void {
496
+ this._fireIconClickEvent("second-icon-click", e);
497
+ }
498
+
499
+ private _fireIconClickEvent(eventName: "first-icon-click" | "second-icon-click", e: CustomEvent): void {
500
+ const id = this.getDataTokenId(e);
501
+ this.fireDecoratorEvent(eventName, {
502
+ originalEvent: e.detail.originalEvent,
503
+ item: this.getItemFromList(id),
504
+ });
505
+ }
506
+
461
507
  getFlattenItemsArray(array: Array<UDExProcessedItem>): (UDExProcessedItem | UDExListItemBase)[] {
462
508
  return array.flatMap(item => {
463
509
  if (item.isGroup) {
package/src/SelectBox.ts CHANGED
@@ -123,6 +123,13 @@ type UDExSelectBoxRemoveEventDetail = {
123
123
  */
124
124
  @event("show-more", { bubbles: true })
125
125
 
126
+ /**
127
+ * Fired before the dropdown pane is opened.
128
+ *
129
+ * @public
130
+ */
131
+ @event("before-open", { bubbles: true })
132
+
126
133
  class UDExSelectBox extends UDExSearchableListBase {
127
134
  eventDetails!: {
128
135
  "remove": UDExSelectBoxRemoveEventDetail,
@@ -480,6 +487,10 @@ class UDExSelectBox extends UDExSearchableListBase {
480
487
  }
481
488
 
482
489
  handleKeyDownDropdown(e: KeyboardEvent) {
490
+ if (this.tabNavigationEnabled) {
491
+ return;
492
+ }
493
+
483
494
  const isTabPrevPress = isTabPrevious(e) && !this._search;
484
495
  const isTabNextPress = isTabNext(e);
485
496
  const isEscapePress = isEscape(e);
@@ -2,6 +2,9 @@ import customElement from "@ui5/webcomponents-base/dist/decorators/customElement
2
2
  import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
3
3
  import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
4
4
  import UDExListItemBase from "./ListItemBase.js";
5
+ import property from "@ui5/webcomponents-base/decorators/property.js";
6
+ import { UDExAdditionalTextState } from "./types/List.js";
7
+ import UDExButton from "./Button.js";
5
8
 
6
9
  /**
7
10
  * @class
@@ -25,9 +28,45 @@ import UDExListItemBase from "./ListItemBase.js";
25
28
  @customElement({
26
29
  tag: "udex-select-box-item",
27
30
  renderer: litRender,
31
+ dependencies: [UDExButton],
28
32
  })
29
33
 
30
34
  class UDExSelectBoxItem extends UDExListItemBase {
35
+ /**
36
+ * Defines the additionalText, displayed at the end of the list item.
37
+ *
38
+ * @public
39
+ */
40
+ @property({ type: String })
41
+ additionalText?: string;
42
+
43
+ /**
44
+ * Defines the state of the additionalText.
45
+ *
46
+ * @default "None"
47
+ * @public
48
+ */
49
+ @property()
50
+ additionalTextState: `${UDExAdditionalTextState}` = UDExAdditionalTextState.None;
51
+
52
+ /**
53
+ * Slot for first icon.
54
+ *
55
+ * @slot
56
+ * @public
57
+ */
58
+ @slot({ type: UDExButton })
59
+ firstIcon!: Array<UDExButton>;
60
+
61
+ /**
62
+ * Slot for second icon.
63
+ *
64
+ * @slot
65
+ * @public
66
+ */
67
+ @slot({ type: UDExButton })
68
+ secondIcon!: Array<UDExButton>;
69
+
31
70
  /**
32
71
  * Slot for item content.
33
72
  *
@@ -10,6 +10,7 @@ import "@ui5/webcomponents-icons/dist/edit.js";
10
10
  import "@ui5/webcomponents-icons/dist/information.js";
11
11
  import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js";
12
12
  import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
13
+ import UDExStatusBadgeValueState from "./types/StatusBadgeValueState.js";
13
14
  import {
14
15
  STATUS_BADGE_TEXT,
15
16
  STATUS_BADGE_EDIT_TITLE,
@@ -40,14 +41,6 @@ export enum BadgeSize {
40
41
  XL = "XL",
41
42
  }
42
43
 
43
- export enum UDExStatusBadgeValueState {
44
- Warning = "Warning",
45
- Error = "Error",
46
- Success = "Success",
47
- Information = "Information",
48
- Edit = "Edit"
49
- }
50
-
51
44
  /**
52
45
  * @class
53
46
  *
@@ -56,6 +56,6 @@ export default function StepInputTemplate(this: UDExStepInput) {
56
56
  ></UDExControlButton>
57
57
  </>)
58
58
  }
59
-
59
+ <div class="hidden" aria-live="polite">{this._valuePrecisioned}</div>
60
60
  </div>);
61
61
  }