@sapudex/web-components 0.111.0 → 0.114.2

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 (189) hide show
  1. package/.npmrc +1 -2
  2. package/bundle.esm.js +1 -0
  3. package/dist/AccordionItem.d.ts +7 -0
  4. package/dist/AccordionItem.js +6 -2
  5. package/dist/AccordionItem.js.map +1 -1
  6. package/dist/CountrySelector.d.ts +5 -7
  7. package/dist/CountrySelector.js +12 -7
  8. package/dist/CountrySelector.js.map +1 -1
  9. package/dist/Dropdown.d.ts +10 -0
  10. package/dist/Dropdown.js +10 -0
  11. package/dist/Dropdown.js.map +1 -1
  12. package/dist/Footer.d.ts +40 -1
  13. package/dist/Footer.js +151 -1
  14. package/dist/Footer.js.map +1 -1
  15. package/dist/InputGroup.d.ts +75 -0
  16. package/dist/InputGroup.js +101 -0
  17. package/dist/InputGroup.js.map +1 -0
  18. package/dist/MastheadMobileMenu.d.ts +4 -1
  19. package/dist/MastheadMobileMenu.js +10 -3
  20. package/dist/MastheadMobileMenu.js.map +1 -1
  21. package/dist/PhoneNumberField.d.ts +8 -0
  22. package/dist/PhoneNumberField.js +23 -10
  23. package/dist/PhoneNumberField.js.map +1 -1
  24. package/dist/Search.d.ts +58 -2
  25. package/dist/Search.js +159 -12
  26. package/dist/Search.js.map +1 -1
  27. package/dist/SecondaryNavigation.d.ts +5 -1
  28. package/dist/SecondaryNavigation.js +18 -2
  29. package/dist/SecondaryNavigation.js.map +1 -1
  30. package/dist/SelectBox.d.ts +6 -0
  31. package/dist/SelectBox.js +14 -1
  32. package/dist/SelectBox.js.map +1 -1
  33. package/dist/Table.d.ts +5 -5
  34. package/dist/Table.js +5 -5
  35. package/dist/Table.js.map +1 -1
  36. package/dist/Tag.d.ts +7 -1
  37. package/dist/Tag.js +6 -2
  38. package/dist/Tag.js.map +1 -1
  39. package/dist/TextArea.js.map +1 -1
  40. package/dist/assets/{bundle.esm-b7920968.js → bundle.esm-ab45813e.js} +181 -179
  41. package/dist/css/themes/AccordionItem.css +1 -1
  42. package/dist/css/themes/Breadcrumbs.css +1 -1
  43. package/dist/css/themes/CountrySelector.css +1 -1
  44. package/dist/css/themes/DatePicker.css +1 -1
  45. package/dist/css/themes/Dropdown.css +1 -1
  46. package/dist/css/themes/InputGroup.css +1 -0
  47. package/dist/css/themes/MastheadItem.css +1 -1
  48. package/dist/css/themes/MastheadMenuItem.css +1 -1
  49. package/dist/css/themes/MastheadShell.css +1 -1
  50. package/dist/css/themes/PhoneNumberField.css +1 -1
  51. package/dist/css/themes/RatingIndicator.css +1 -1
  52. package/dist/css/themes/Search.css +1 -1
  53. package/dist/css/themes/SearchSuggestions.css +1 -1
  54. package/dist/css/themes/Slider.css +1 -1
  55. package/dist/css/themes/Tag.css +1 -1
  56. package/dist/css/themes/TextField.css +1 -1
  57. package/dist/custom-elements-internal.json +405 -53
  58. package/dist/custom-elements.json +358 -52
  59. package/dist/features/SearchSuggestionsPopover.d.ts +3 -3
  60. package/dist/features/SearchSuggestionsPopover.js +16 -18
  61. package/dist/features/SearchSuggestionsPopover.js.map +1 -1
  62. package/dist/generated/templates/AccordionItemTemplate.lit.js +2 -1
  63. package/dist/generated/templates/AccordionItemTemplate.lit.js.map +1 -1
  64. package/dist/generated/templates/CountrySelectorTemplate.lit.js +1 -1
  65. package/dist/generated/templates/CountrySelectorTemplate.lit.js.map +1 -1
  66. package/dist/generated/templates/FooterTemplate.lit.js +15 -15
  67. package/dist/generated/templates/FooterTemplate.lit.js.map +1 -1
  68. package/dist/generated/templates/InputGroupTemplate.lit.d.ts +4 -0
  69. package/dist/generated/templates/InputGroupTemplate.lit.js +7 -0
  70. package/dist/generated/templates/InputGroupTemplate.lit.js.map +1 -0
  71. package/dist/generated/templates/MastheadMobileMenuTemplate.lit.js +15 -10
  72. package/dist/generated/templates/MastheadMobileMenuTemplate.lit.js.map +1 -1
  73. package/dist/generated/templates/MastheadProfileMenuTemplate.lit.js +1 -1
  74. package/dist/generated/templates/MastheadProfileMenuTemplate.lit.js.map +1 -1
  75. package/dist/generated/templates/SearchSuggestionsTemplate.lit.js +11 -10
  76. package/dist/generated/templates/SearchSuggestionsTemplate.lit.js.map +1 -1
  77. package/dist/generated/templates/SearchTemplate.lit.js +11 -10
  78. package/dist/generated/templates/SearchTemplate.lit.js.map +1 -1
  79. package/dist/generated/templates/SecondaryNavigationTemplate.lit.js +2 -1
  80. package/dist/generated/templates/SecondaryNavigationTemplate.lit.js.map +1 -1
  81. package/dist/generated/themes/AccordionItem.css.js +1 -1
  82. package/dist/generated/themes/AccordionItem.css.js.map +1 -1
  83. package/dist/generated/themes/Breadcrumbs.css.js +1 -1
  84. package/dist/generated/themes/Breadcrumbs.css.js.map +1 -1
  85. package/dist/generated/themes/CountrySelector.css.js +1 -1
  86. package/dist/generated/themes/CountrySelector.css.js.map +1 -1
  87. package/dist/generated/themes/DatePicker.css.js +1 -1
  88. package/dist/generated/themes/DatePicker.css.js.map +1 -1
  89. package/dist/generated/themes/Dropdown.css.js +1 -1
  90. package/dist/generated/themes/Dropdown.css.js.map +1 -1
  91. package/dist/generated/themes/InputGroup.css.d.ts +3 -0
  92. package/dist/generated/themes/InputGroup.css.js +9 -0
  93. package/dist/generated/themes/InputGroup.css.js.map +1 -0
  94. package/dist/generated/themes/MastheadItem.css.js +1 -1
  95. package/dist/generated/themes/MastheadItem.css.js.map +1 -1
  96. package/dist/generated/themes/MastheadMenuItem.css.js +1 -1
  97. package/dist/generated/themes/MastheadMenuItem.css.js.map +1 -1
  98. package/dist/generated/themes/MastheadShell.css.js +1 -1
  99. package/dist/generated/themes/MastheadShell.css.js.map +1 -1
  100. package/dist/generated/themes/PhoneNumberField.css.js +1 -1
  101. package/dist/generated/themes/PhoneNumberField.css.js.map +1 -1
  102. package/dist/generated/themes/RatingIndicator.css.js +1 -1
  103. package/dist/generated/themes/RatingIndicator.css.js.map +1 -1
  104. package/dist/generated/themes/Search.css.js +1 -1
  105. package/dist/generated/themes/Search.css.js.map +1 -1
  106. package/dist/generated/themes/SearchSuggestions.css.js +1 -1
  107. package/dist/generated/themes/SearchSuggestions.css.js.map +1 -1
  108. package/dist/generated/themes/Slider.css.js +1 -1
  109. package/dist/generated/themes/Slider.css.js.map +1 -1
  110. package/dist/generated/themes/Tag.css.js +1 -1
  111. package/dist/generated/themes/Tag.css.js.map +1 -1
  112. package/dist/generated/themes/TextField.css.js +1 -1
  113. package/dist/generated/themes/TextField.css.js.map +1 -1
  114. package/dist/types/callback.d.ts +2 -0
  115. package/dist/types/callback.js +2 -0
  116. package/dist/types/callback.js.map +1 -0
  117. package/dist/utils/debounce.d.ts +2 -2
  118. package/dist/utils/debounce.js.map +1 -1
  119. package/dist/utils/retryUntilSuccessful.d.ts +3 -0
  120. package/dist/utils/retryUntilSuccessful.js +21 -0
  121. package/dist/utils/retryUntilSuccessful.js.map +1 -0
  122. package/dist/vscode.html-custom-data.json +48 -12
  123. package/dist/web-types.json +205 -29
  124. package/package.json +1 -1
  125. package/src/AccordionItem.hbs +12 -1
  126. package/src/AccordionItem.ts +11 -2
  127. package/src/CountrySelector.hbs +1 -2
  128. package/src/CountrySelector.ts +18 -20
  129. package/src/Dropdown.ts +10 -0
  130. package/src/Footer.hbs +154 -91
  131. package/src/Footer.ts +158 -1
  132. package/src/InputGroup.hbs +20 -0
  133. package/src/InputGroup.ts +136 -0
  134. package/src/MastheadMobileMenu.hbs +51 -28
  135. package/src/MastheadMobileMenu.ts +12 -3
  136. package/src/MastheadProfileMenu.hbs +1 -1
  137. package/src/PhoneNumberField.ts +27 -3
  138. package/src/Search.hbs +23 -1
  139. package/src/Search.ts +203 -15
  140. package/src/SearchSuggestions.hbs +46 -48
  141. package/src/SecondaryNavigation.hbs +6 -4
  142. package/src/SecondaryNavigation.ts +23 -3
  143. package/src/SelectBox.ts +22 -0
  144. package/src/Table.ts +7 -7
  145. package/src/Tag.ts +12 -3
  146. package/src/TextArea.ts +1 -1
  147. package/src/features/SearchSuggestionsPopover.ts +18 -20
  148. package/src/generated/templates/AccordionItemTemplate.lit.ts +2 -1
  149. package/src/generated/templates/CountrySelectorTemplate.lit.ts +1 -1
  150. package/src/generated/templates/FooterTemplate.lit.ts +15 -15
  151. package/src/generated/templates/InputGroupTemplate.lit.ts +12 -0
  152. package/src/generated/templates/MastheadMobileMenuTemplate.lit.ts +15 -10
  153. package/src/generated/templates/MastheadProfileMenuTemplate.lit.ts +1 -1
  154. package/src/generated/templates/SearchSuggestionsTemplate.lit.ts +11 -10
  155. package/src/generated/templates/SearchTemplate.lit.ts +10 -9
  156. package/src/generated/templates/SecondaryNavigationTemplate.lit.ts +2 -1
  157. package/src/generated/themes/AccordionItem.css.ts +1 -1
  158. package/src/generated/themes/Breadcrumbs.css.ts +1 -1
  159. package/src/generated/themes/CountrySelector.css.ts +1 -1
  160. package/src/generated/themes/DatePicker.css.ts +1 -1
  161. package/src/generated/themes/Dropdown.css.ts +1 -1
  162. package/src/generated/themes/InputGroup.css.ts +13 -0
  163. package/src/generated/themes/MastheadItem.css.ts +1 -1
  164. package/src/generated/themes/MastheadMenuItem.css.ts +1 -1
  165. package/src/generated/themes/MastheadShell.css.ts +1 -1
  166. package/src/generated/themes/PhoneNumberField.css.ts +1 -1
  167. package/src/generated/themes/RatingIndicator.css.ts +1 -1
  168. package/src/generated/themes/Search.css.ts +1 -1
  169. package/src/generated/themes/SearchSuggestions.css.ts +1 -1
  170. package/src/generated/themes/Slider.css.ts +1 -1
  171. package/src/generated/themes/Tag.css.ts +1 -1
  172. package/src/generated/themes/TextField.css.ts +1 -1
  173. package/src/themes/AccordionItem.css +20 -15
  174. package/src/themes/Breadcrumbs.css +4 -2
  175. package/src/themes/CountrySelector.css +12 -1
  176. package/src/themes/DatePicker.css +1 -1
  177. package/src/themes/Dropdown.css +2 -2
  178. package/src/themes/InputGroup.css +19 -0
  179. package/src/themes/MastheadItem.css +2 -7
  180. package/src/themes/MastheadMenuItem.css +0 -4
  181. package/src/themes/MastheadShell.css +9 -10
  182. package/src/themes/PhoneNumberField.css +13 -3
  183. package/src/themes/Search.css +160 -17
  184. package/src/themes/SearchSuggestions.css +7 -1
  185. package/src/themes/Tag.css +6 -1
  186. package/src/themes/TextField.css +10 -1
  187. package/src/types/callback.ts +3 -0
  188. package/src/utils/debounce.ts +1 -1
  189. package/src/utils/retryUntilSuccessful.ts +23 -0
package/src/Search.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import UI5Element, { ChangeInfo } from "@ui5/webcomponents-base/dist/UI5Element.js";
2
2
  import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
3
+ import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
3
4
  import property from "@ui5/webcomponents-base/dist/decorators/property.js";
4
5
  import event from "@ui5/webcomponents-base/dist/decorators/event.js";
5
6
  import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
@@ -16,11 +17,20 @@ import {
16
17
  isDown,
17
18
  isEscape,
18
19
  } from "@ui5/webcomponents-base/dist/Keys.js";
20
+ import List from "./List.js";
21
+ import ListItemBase from "./ListItemBase.js";
22
+ import "@ui5/webcomponents/dist/Icon.js";
19
23
  import "@ui5/webcomponents-icons/dist/decline.js";
20
24
  import "@ui5/webcomponents-icons/dist/search.js";
21
25
  import "@ui5/webcomponents-icons/dist/microphone.js";
26
+ import "@ui5/webcomponents-icons/dist/slim-arrow-down.js";
22
27
  import debounce from "./utils/debounce.js";
23
- import { SUGGESTED_TEXT, RECOMMENDED_TEXT, AVAILABLE_VALUES } from "./generated/i18n/i18n-defaults.js";
28
+ import {
29
+ SUGGESTED_TEXT,
30
+ RECOMMENDED_TEXT,
31
+ AVAILABLE_VALUES,
32
+ NO_MATCHES_FOUND,
33
+ } from "./generated/i18n/i18n-defaults.js";
24
34
  import type SearchInputSuggestion from "./features/SearchSuggestionsPopover.js";
25
35
 
26
36
  import SearchTemplate from "./generated/templates/SearchTemplate.lit.js";
@@ -29,6 +39,7 @@ import SearchSuggestionsTemplate from "./generated/templates/SearchSuggestionsTe
29
39
  // Styles
30
40
  import SearchCss from "./generated/themes/Search.css.js";
31
41
  import SearchSuggestionsCss from "./generated/themes/SearchSuggestions.css.js";
42
+ import retryUntilSuccessful from "./utils/retryUntilSuccessful.js";
32
43
 
33
44
  const SearchIcon: string = "sap-icon://search";
34
45
 
@@ -65,7 +76,7 @@ export type SuggestionList = {
65
76
 
66
77
  export enum Mode {
67
78
  Standard = "Standard",
68
- HomeSearch = "Home Search",
79
+ HomeSearch = "Home Search"
69
80
  }
70
81
 
71
82
  /**
@@ -96,7 +107,7 @@ export enum Mode {
96
107
  staticAreaTemplate: SearchSuggestionsTemplate,
97
108
  get dependencies() {
98
109
  const Suggestion = getFeature<typeof SearchInputSuggestion>("SearchInputSuggestion");
99
- return ([Popover] as Array<typeof UI5Element>).concat(Suggestion ? Suggestion.dependencies : []);
110
+ return ([Popover] as Array<typeof UI5Element>).concat(Suggestion ? [...Suggestion.dependencies, List] : [List]);
100
111
  },
101
112
  })
102
113
 
@@ -128,6 +139,13 @@ export enum Mode {
128
139
  * @public
129
140
  */
130
141
  @event("dropdown-item-click", { detail: { value: { type: String } } })
142
+ /**
143
+ * Fired event when the user clicks on the intem inside the prefix dropdown.
144
+ *
145
+ * @event sap.ui.webc.web-components.UDExSearch#prefixItemClick
146
+ * @public
147
+ */
148
+ @event("prefix-item-click", { detail: { item: { type: ListItemBase } } })
131
149
  class UDExSearch extends UI5Element {
132
150
  static i18nBundle: any;
133
151
  _labelActiveClassName = "udex-search__label--active";
@@ -225,6 +243,14 @@ class UDExSearch extends UI5Element {
225
243
  @property({ validator: Integer })
226
244
  _searchWidth?: number;
227
245
 
246
+ /**
247
+ * Define the label of the prefix for the dropdown.
248
+ *
249
+ * @private
250
+ */
251
+ @property({ type: String })
252
+ labelPrefix!: string;
253
+
228
254
  /**
229
255
  * Defines display the suggestion popover in the component.
230
256
  *
@@ -251,8 +277,8 @@ class UDExSearch extends UI5Element {
251
277
  * @default "Standard"
252
278
  * @public
253
279
  */
254
- @property({ type: String, defaultValue: "Standard" })
255
- mode!: "Standard" | "Home Search";
280
+ @property({ type: String, defaultValue: Mode.Standard })
281
+ mode!: Mode;
256
282
 
257
283
  /**
258
284
  * Defines open suggestion popover when clicked on the input field.
@@ -281,6 +307,15 @@ class UDExSearch extends UI5Element {
281
307
  @property()
282
308
  accessibleName!: string;
283
309
 
310
+ /**
311
+ * Defines the text if the suggestion list doesn't return results.
312
+ *
313
+ * @default "No matches found."
314
+ * @public
315
+ */
316
+ @property({ type: String, defaultValue: "No matches found." })
317
+ noResultText!: string;
318
+
284
319
  /**
285
320
  * Defines the inner stored class of the label.
286
321
  *
@@ -349,6 +384,36 @@ class UDExSearch extends UI5Element {
349
384
  @property({ type: String })
350
385
  _recommendLabel?: string;
351
386
 
387
+ /**
388
+ * The console warning shown after all unsuccessful attempts of opening SearchSuggestionsPopover component.
389
+ * @default "UdexSearchSuggestionsPopover couldn`t be opened"
390
+ */
391
+ @property({ type: String, defaultValue: "UdexSearchSuggestionsPopover couldn`t be opened" })
392
+ unsuccessfulRetryMessage: string = "UdexSearchSuggestionsPopover couldn`t be opened";
393
+
394
+ /**
395
+ * The delay before retrying to open the SerchSuggestionsPopover component.
396
+ * @default 200
397
+ */
398
+ @property({ type: Number, defaultValue: 200 })
399
+ retryDelay: number = 200;
400
+
401
+ /**
402
+ * The maximum number of attempts for opening the SearchSuggestionsPopover component.
403
+ * @default 5
404
+ */
405
+ @property({ type: Number, defaultValue: 5 })
406
+ maxRetryAttempts: number = 5;
407
+
408
+ /**
409
+ * Defines the prefix dropdown of the Search component.
410
+ *
411
+ * @slot dropdownPrefix
412
+ * @public
413
+ */
414
+ @slot({ type: HTMLElement, "default": true })
415
+ dropdownPrefix!: Array<List>;
416
+
352
417
  constructor() {
353
418
  super();
354
419
  this._handleResizeBound = this._handleResize.bind(this);
@@ -546,6 +611,67 @@ class UDExSearch extends UI5Element {
546
611
  this.fireEvent("dropdown-item-click", { value });
547
612
  }
548
613
 
614
+ handleDropdownClick() {
615
+ const dropdown = this.getPrefixPopover();
616
+
617
+ if (dropdown.opened) {
618
+ this.onClosePrefixPopover();
619
+ } else {
620
+ this.onOpenPrefixPopover();
621
+ }
622
+ }
623
+
624
+ getPrefixWrapper() {
625
+ return this.shadowRoot!.querySelector(".udex-search__prefix") as HTMLElement;
626
+ }
627
+
628
+ getPrefixPopover() {
629
+ return this.shadowRoot!.querySelector<Popover>("[ui5-popover]")!;
630
+ }
631
+
632
+ getPrefixButton() {
633
+ return this.shadowRoot!.querySelector(".udex-search__prefix-button") as HTMLElement;
634
+ }
635
+
636
+ onOpenPrefixPopover() {
637
+ if (this.dropdownPrefix.length) {
638
+ const wrapper = this.getPrefixWrapper();
639
+ const dropdown = this.getPrefixPopover();
640
+ const button = this.getPrefixButton();
641
+
642
+ dropdown.showAt(this.getPrefixButton());
643
+ dropdown.style.width = `${button.offsetWidth + 1}px`;
644
+ button.classList.add("udex-search__prefix-button--active");
645
+ wrapper.classList.add("udex-search__prefix--show-popover");
646
+ this.handleItemClick();
647
+ }
648
+ }
649
+
650
+ private handleItemClick() {
651
+ this.dropdownPrefix[0].addEventListener("item-press", (e: any) => {
652
+ const selectedItemPrefix = e.detail.item as ListItemBase;
653
+ this.labelPrefix = selectedItemPrefix.innerText;
654
+ this.fireEvent("prefix-item-click", { item: selectedItemPrefix });
655
+ this.onClosePrefixPopover();
656
+ });
657
+ }
658
+
659
+ onClosePrefixPopover() {
660
+ const dropdown = this.getPrefixPopover();
661
+
662
+ dropdown.close();
663
+ this.handleAfterClosePrefixPopover();
664
+ }
665
+
666
+ handleAfterClosePrefixPopover() {
667
+ const wrapper = this.getPrefixWrapper();
668
+ const button = this.getPrefixButton();
669
+
670
+ wrapper.classList.remove("udex-search__prefix--show-popover");
671
+ button.classList.remove("udex-search__prefix-button--active");
672
+ this.dropdownPrefix[0].removeEventListener("item-press", () => {});
673
+ }
674
+
549
675
  handleInputClick(): void {
550
676
  if (this.showPopoverWhenClickedIntoInput) {
551
677
  this.onOpenPopover();
@@ -568,8 +694,19 @@ class UDExSearch extends UI5Element {
568
694
  }
569
695
 
570
696
  onOpenPopover(): void {
571
- if (this.showSuggestedPopover && (this.suggestedList?.length || this.recommendedList?.length)) {
572
- this.Suggestion!.open();
697
+ if (this.showSuggestedPopover) {
698
+ if (!this.Suggestion) {
699
+ retryUntilSuccessful(() => this.Suggestion, this.retryDelay, this.maxRetryAttempts, this.unsuccessfulRetryMessage)
700
+ .then(() => {
701
+ this.Suggestion!.open();
702
+ })
703
+ .catch(error => {
704
+ console.warn(error.message);
705
+ });
706
+ } else {
707
+ this.Suggestion.open();
708
+ }
709
+
573
710
  this.handleClassToRoot();
574
711
  this.handleAriaExpanded();
575
712
  }
@@ -601,6 +738,14 @@ class UDExSearch extends UI5Element {
601
738
  this.enableSuggestions();
602
739
  }
603
740
 
741
+ if (this.isHomeSearchWithPrefixMode && this.dropdownPrefix.length) {
742
+ const dropdownItems = Array.from(this.dropdownPrefix[0].children) as Array<ListItemBase>;
743
+ const selectedItemIndex = dropdownItems.findIndex(listItem => listItem.selected);
744
+ const selectedItemPrefix = selectedItemIndex >= 0 ? dropdownItems[selectedItemIndex] : dropdownItems[0];
745
+
746
+ this.labelPrefix = selectedItemPrefix.innerText;
747
+ }
748
+
604
749
  this.showResetButton = !!this.value.length;
605
750
 
606
751
  if (this.value && this.labelActiveClass === "") {
@@ -616,6 +761,14 @@ class UDExSearch extends UI5Element {
616
761
  }
617
762
 
618
763
  this.labelClasses = `udex-search__label ${this.labelActiveClass} ${this.labelAnimationClass}`;
764
+
765
+ if (this.isVoiceButton) {
766
+ this.labelClasses += " udex-search__label-with-voice-icon";
767
+ }
768
+
769
+ if (this.isShowSubmitButton) {
770
+ this.labelClasses += " udex-search__label-with-search-icon";
771
+ }
619
772
  }
620
773
 
621
774
  enableSuggestions() {
@@ -628,7 +781,7 @@ class UDExSearch extends UI5Element {
628
781
  if (Suggestion) {
629
782
  this.Suggestion = new Suggestion(this);
630
783
  } else {
631
- throw new Error("You have to import '@udex/webcomponents/dist/features/SearchInputSuggestions.js' module to use udex-search suggestions");
784
+ throw new Error("You have to import '@udex/webcomponents/dist/features/SearchSuggestionsPopover.js' module to use udex-search suggestions");
632
785
  }
633
786
  }
634
787
 
@@ -636,6 +789,7 @@ class UDExSearch extends UI5Element {
636
789
  if (this.showSuggestedPopover) {
637
790
  this.handleOutsideClick();
638
791
  this.handleOpenSuggestionPopover();
792
+ this.setSearchWidth();
639
793
  }
640
794
  }
641
795
 
@@ -771,7 +925,7 @@ class UDExSearch extends UI5Element {
771
925
 
772
926
  handleKeyDownReset(e: KeyboardEvent) {
773
927
  if (isTabPrevious(e) && this.open) {
774
- this.Suggestion?.handlePrevTabResset(e);
928
+ this.Suggestion?.handlePrevTabReset(e);
775
929
  }
776
930
  }
777
931
 
@@ -823,7 +977,15 @@ class UDExSearch extends UI5Element {
823
977
  }
824
978
 
825
979
  _handleResize() {
826
- this._searchWidth = this.offsetWidth;
980
+ this.setSearchWidth();
981
+ }
982
+
983
+ private setSearchWidth() {
984
+ const searchContainer = (this.shadowRoot?.querySelector(".udex-search__container") as HTMLElement);
985
+
986
+ if (searchContainer.offsetWidth !== this._searchWidth) {
987
+ this._searchWidth = searchContainer.offsetWidth;
988
+ }
827
989
  }
828
990
 
829
991
  get popoverStyles() {
@@ -832,10 +994,24 @@ class UDExSearch extends UI5Element {
832
994
  };
833
995
  }
834
996
 
997
+ get prefixPopoverStyles() {
998
+ return {
999
+ "width": this.getPrefixButton() ? `${this.getPrefixButton().offsetWidth + 1}px` : "",
1000
+ };
1001
+ }
1002
+
835
1003
  get isShowResetButton(): boolean {
836
1004
  return this.showResetButton && !!this.value.length;
837
1005
  }
838
1006
 
1007
+ get noResultMessage(): string {
1008
+ return this.noResultText || UDExSearch.i18nBundle.getText(NO_MATCHES_FOUND) as string;
1009
+ }
1010
+
1011
+ get showNoResultMessage(): boolean {
1012
+ return !this.suggestedList?.length && !this.recommendedList?.length;
1013
+ }
1014
+
839
1015
  get isShowSuggestedList(): boolean {
840
1016
  return !!this.suggestedList?.length;
841
1017
  }
@@ -844,10 +1020,6 @@ class UDExSearch extends UI5Element {
844
1020
  return !!this.recommendedList?.length;
845
1021
  }
846
1022
 
847
- get hasPopoverContent(): boolean {
848
- return !!(this.suggestedList?.length || this.recommendedList?.length);
849
- }
850
-
851
1023
  get isShowSubmitButton(): boolean {
852
1024
  return this.showSubmitButton;
853
1025
  }
@@ -860,12 +1032,28 @@ class UDExSearch extends UI5Element {
860
1032
  return this._recommendLabel;
861
1033
  }
862
1034
 
1035
+ get isShowSearchHomePrefix(): boolean {
1036
+ return this.isHomeSearchWithPrefixMode && !!this.dropdownPrefix.length;
1037
+ }
1038
+
863
1039
  get isHomeSearchMode(): boolean {
864
1040
  return this.mode === Mode.HomeSearch;
865
1041
  }
866
1042
 
1043
+ get isHomeSearchWithPrefixMode(): boolean {
1044
+ return this.mode === Mode.HomeSearch && !!this.dropdownPrefix.length;
1045
+ }
1046
+
1047
+ get classWithPrefix(): string {
1048
+ return this.isHomeSearchWithPrefixMode ? "udex-search-prefix" : "";
1049
+ }
1050
+
867
1051
  get homeSearchPopoverClass(): string {
868
- return this.isHomeSearchMode ? "udex-search-suggestions__root--home" : "";
1052
+ return this.isHomeSearchMode || this.isHomeSearchWithPrefixMode ? "udex-search-suggestions__root--home" : "";
1053
+ }
1054
+
1055
+ get homeSearchWithPrefixPopoverClass(): string {
1056
+ return this.isHomeSearchWithPrefixMode ? "udex-search-suggestions__root--prefix" : "";
869
1057
  }
870
1058
 
871
1059
  get searchButtonActiveClass(): string {
@@ -8,79 +8,77 @@
8
8
  id="suggestions-popover"
9
9
  aria-orientation="vertical"
10
10
  accessible-name="{{suggestionsAccessibleName}}">
11
- {{#if hasPopoverContent}}
11
+ {{#if showNoResultMessage}}
12
+ <span class="udex-search-suggestions__message">{{noResultMessage}}</span>
13
+ {{else}}
12
14
  <div role="tree">
13
15
  {{#if isShowSuggestedList}}
14
- <div class="udex-search-suggestions__block">
16
+ <div class="udex-search-suggestions__block" role="treeitem">
15
17
  {{#if suggestedHeading}}
16
18
  <span class="udex-search-suggestions__heading" id="suggested-heading">{{suggestedHeading}}</span>
17
19
  {{/if}}
18
- <ul class="udex-search-suggestions__list"
20
+ <div class="udex-search-suggestions__list"
19
21
  role="listbox"
20
22
  aria-labelledby="suggested-heading"
21
23
  tabindex="0"
22
24
  @keydown="{{../handleKeyDownPopover}}">
23
25
  {{#each suggestedList}}
24
- <li
25
- class="udex-search-suggestions__item"
26
- role="option"
26
+ <ui5-button
27
27
  id="{{id}}"
28
+ icon="{{icon}}"
29
+ type="Button"
30
+ design="Default"
31
+ class="udex-search-suggestions__item-button"
32
+ title="{{title}}"
33
+ tabindex="-1"
34
+ role="option"
35
+ @click="{{handleSelectItem}}"
28
36
  >
29
- <ui5-button
30
- icon="{{icon}}"
31
- type="Button"
32
- design="Default"
33
- class="udex-search-suggestions__item-button"
34
- title="{{title}}"
35
- tabindex="-1"
36
- @click="{{handleSelectItem}}"
37
- >
38
- {{{text}}}
39
- </ui5-button>
40
- </li>
37
+ {{{text}}}
38
+ </ui5-button>
41
39
  {{/each}}
42
- </ul>
40
+ </div>
43
41
  </div>
44
42
  {{/if}}
45
43
  {{#if isShowRecommendedList}}
46
- <div class="udex-search-suggestions__block">
44
+ <div class="udex-search-suggestions__block" role="treeitem">
47
45
  {{#if recommendedHeading}}
48
46
  <span class="udex-search-suggestions__heading" id="recommended-heading">{{recommendedHeading}}</span>
49
47
  {{/if}}
50
- <ul class="udex-search-suggestions__list"
48
+ <div class="udex-search-suggestions__list"
51
49
  role="listbox"
52
50
  aria-labelledby="recommended-heading"
53
51
  tabindex="0"
54
52
  @keydown="{{../handleKeyDownPopover}}">
55
53
  {{#each recommendedList}}
56
- <li
57
- class="udex-search-suggestions__item"
58
- role="option"
59
- id="{{id}}">
60
- {{#if this.hasCustomIcon}}
61
- <ui5-button
62
- icon="{{icon}}"
63
- type="Button"
64
- design="Default"
65
- class="udex-search-suggestions__item-button"
66
- title="{{title}}"
67
- @click="{{handleSelectItem}}">
68
- {{{text}}}
69
- </ui5-button>
70
- {{else}}
71
- <ui5-button
72
- type="Button"
73
- design="Default"
74
- class="udex-search-suggestions__item-button"
75
- title="{{title}}"
76
- tabindex="-1"
77
- @click="{{handleSelectItem}}">
78
- {{{text}}}
79
- </ui5-button>
80
- {{/if}}
81
- </li>
54
+ {{#if this.hasCustomIcon}}
55
+ <ui5-button
56
+ id="{{id}}"
57
+ icon="{{icon}}"
58
+ type="Button"
59
+ design="Default"
60
+ class="udex-search-suggestions__item-button"
61
+ title="{{title}}"
62
+ tabindex="-1"
63
+ role="option"
64
+ @click="{{handleSelectItem}}">
65
+ {{{text}}}
66
+ </ui5-button>
67
+ {{else}}
68
+ <ui5-button
69
+ id="{{id}}"
70
+ type="Button"
71
+ design="Default"
72
+ class="udex-search-suggestions__item-button"
73
+ title="{{title}}"
74
+ tabindex="-1"
75
+ role="option"
76
+ @click="{{handleSelectItem}}">
77
+ {{{text}}}
78
+ </ui5-button>
79
+ {{/if}}
82
80
  {{/each}}
83
- </ul>
81
+ </div>
84
82
  </div>
85
83
  {{/if}}
86
84
  </div>
@@ -40,7 +40,7 @@
40
40
  {{/if}}
41
41
  </li>
42
42
  {{/each}}
43
- {{#if _overflowItems.length}}
43
+ {{#if _showMoreButton}}
44
44
  <li role="none" class="{{moreClass}} udex-secondary-navigation__link-btn-wrap" ?active="{{moreIsActive}}">
45
45
  <button
46
46
  role="menuitem"
@@ -82,9 +82,11 @@
82
82
  </li>
83
83
  {{/if}}
84
84
  </ul>
85
- <div class="udex-secondary-navigation__buttons">
86
- <slot name="buttons"></slot>
87
- </div>
85
+ {{#if hasButtonsSlot}}
86
+ <div class="udex-secondary-navigation__buttons">
87
+ <slot name="buttons"></slot>
88
+ </div>
89
+ {{/if}}
88
90
  </div>
89
91
  </div>
90
92
  </div>
@@ -1,4 +1,4 @@
1
- import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
1
+ import UI5Element, { ChangeInfo } from "@ui5/webcomponents-base/dist/UI5Element.js";
2
2
  import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
3
3
  import property from "@ui5/webcomponents-base/dist/decorators/property.js";
4
4
  import event from "@ui5/webcomponents-base/dist/decorators/event.js";
@@ -154,6 +154,7 @@ class UDExSecondaryNavigation extends UI5Element {
154
154
  @property({ type: Boolean, noAttribute: true })
155
155
  _mobileBtnExpanded = false;
156
156
 
157
+ _showMoreButton: boolean;
157
158
  _navigationList: Array<NavItem> | undefined;
158
159
  _dropdown!: HTMLElement | null | undefined;
159
160
  _rootHolder!: HTMLElement | null | undefined;
@@ -167,6 +168,7 @@ class UDExSecondaryNavigation extends UI5Element {
167
168
 
168
169
  constructor() {
169
170
  super();
171
+ this._showMoreButton = true;
170
172
  this._boundReflowItems = this.reflowItems.bind(this);
171
173
  }
172
174
 
@@ -186,6 +188,13 @@ class UDExSecondaryNavigation extends UI5Element {
186
188
  ResizeHandler.deregister(this.rootHolder, this._boundReflowItems);
187
189
  }
188
190
 
191
+ onInvalidation(changeInfo: ChangeInfo): void {
192
+ if (changeInfo.name === "navItems") {
193
+ this._navigationList = undefined;
194
+ this.reflowItems();
195
+ }
196
+ }
197
+
189
198
  onAfterRendering(): void {
190
199
  this._rootHolder = this.rootHolder;
191
200
  this._dropdown = this.getDropdown();
@@ -211,14 +220,16 @@ class UDExSecondaryNavigation extends UI5Element {
211
220
 
212
221
  if ((steps.at(-1) || 0) <= availableWidth) {
213
222
  this._navItems.splice(0, Infinity, ...this.navigationList);
223
+ this._showMoreButton = false;
214
224
  this.refreshRendering();
215
225
  return;
216
226
  }
217
227
 
218
228
  // @ts-ignore
219
- const lastVisibleIndex: number = steps.findLastIndex((size: number) => size < (availableWidth - moreButtonWidth - 20));
229
+ const lastVisibleIndex: number = steps.findLastIndex((size: number) => size < (availableWidth - moreButtonWidth - itemsGap));
220
230
  this._navItems.splice(0, Infinity, ...this.navigationList.slice(0, lastVisibleIndex + 1));
221
231
  this._overflowItems.splice(0, Infinity, ...this.navigationList.slice(lastVisibleIndex + 1));
232
+ this._showMoreButton = true;
222
233
  this.refreshRendering();
223
234
  }
224
235
 
@@ -281,7 +292,7 @@ class UDExSecondaryNavigation extends UI5Element {
281
292
  }
282
293
 
283
294
  handleMobileOpen(): void {
284
- this._rootHolder?.classList.toggle(mobileMenuActiveClass);
295
+ this.toggleActiveClass();
285
296
  this._mobileBtnExpanded = !this._mobileBtnExpanded;
286
297
  }
287
298
 
@@ -289,6 +300,10 @@ class UDExSecondaryNavigation extends UI5Element {
289
300
  this._dropdownMoreIsOpen = !this._dropdownMoreIsOpen;
290
301
  }
291
302
 
303
+ toggleActiveClass() {
304
+ this._rootHolder?.classList.toggle(mobileMenuActiveClass);
305
+ }
306
+
292
307
  focusPrevNavItem(e: KeyboardEvent): void {
293
308
  const el = e.target as HTMLElement;
294
309
  const currentItem = el.parentElement as HTMLElement;
@@ -370,6 +385,7 @@ class UDExSecondaryNavigation extends UI5Element {
370
385
  this.navigationList.forEach(item => delete item.active);
371
386
  this.navigationList[clickedIndex].active = true;
372
387
  this.refreshRendering();
388
+ this.toggleActiveClass();
373
389
  }
374
390
  }
375
391
 
@@ -437,6 +453,10 @@ class UDExSecondaryNavigation extends UI5Element {
437
453
  return !!this.getSlottedNodes("breadcrumbs").length;
438
454
  }
439
455
 
456
+ get hasButtonsSlot(): boolean {
457
+ return !!this.getSlottedNodes("buttons").length;
458
+ }
459
+
440
460
  get isDesktopScreen(): boolean {
441
461
  return window.innerWidth > breakpointSizeS;
442
462
  }
package/src/SelectBox.ts CHANGED
@@ -20,6 +20,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
20
20
  import Tokenizer from "@ui5/webcomponents/dist/Tokenizer.js";
21
21
  import Icon from "@ui5/webcomponents/dist/Icon.js";
22
22
  import Token from "@ui5/webcomponents/dist/Token.js";
23
+ import ResizeHandler, { ResizeObserverCallback } from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
23
24
  import UDExDropdown from "./Dropdown.js";
24
25
  import UDExList from "./List.js";
25
26
  import UDExListItem from "./ListItem.js";
@@ -234,6 +235,23 @@ class UDExSelectBox extends UDExSearchableListBase {
234
235
  _singleSelectedOption!: string;
235
236
  _truncatableTag!: UDExTag;
236
237
 
238
+ _handleResizeBound: ResizeObserverCallback;
239
+
240
+ constructor() {
241
+ super();
242
+ this._shouldFilterItems = false;
243
+ this._handleResizeBound = this._handleResize.bind(this);
244
+ this._filteredItems = [];
245
+ }
246
+
247
+ onEnterDOM(): void {
248
+ ResizeHandler.register(this, this._handleResizeBound);
249
+ }
250
+
251
+ onExitDOM(): void {
252
+ ResizeHandler.deregister(this, this._handleResizeBound);
253
+ }
254
+
237
255
  onAfterRendering() {
238
256
  this._tokenizer = this.tokenizer;
239
257
  this._dropdown = this.dropdown;
@@ -253,6 +271,10 @@ class UDExSelectBox extends UDExSearchableListBase {
253
271
  }
254
272
  }
255
273
 
274
+ _handleResize() {
275
+ this._dropdown.style.setProperty("--udex-dropdown-pane-width", `${this.offsetWidth}px`);
276
+ }
277
+
256
278
  handleItemPress(e:CustomEvent) {
257
279
  this.onItemPress(e);
258
280