@watermarkinsights/ripple 3.12.0 → 3.13.0-9

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 (176) hide show
  1. package/dist/cjs/{chartFunctions-44ae2eee.js → chartFunctions-34fdd3ce.js} +1 -1
  2. package/dist/cjs/{functions-1a67b971.js → functions-120449cf.js} +245 -32
  3. package/dist/cjs/{global-122fc638.js → global-1d1d0ab3.js} +7 -5
  4. package/dist/cjs/loader.cjs.js +2 -2
  5. package/dist/cjs/priv-chart-popover.cjs.entry.js +1 -1
  6. package/dist/cjs/priv-datepicker.cjs.entry.js +1 -1
  7. package/dist/cjs/ripple.cjs.js +2 -2
  8. package/dist/cjs/wm-action-menu_2.cjs.entry.js +1 -1
  9. package/dist/cjs/wm-button.cjs.entry.js +50 -38
  10. package/dist/cjs/wm-chart.cjs.entry.js +2 -2
  11. package/dist/cjs/wm-datepicker.cjs.entry.js +1 -1
  12. package/dist/cjs/wm-input.cjs.entry.js +1 -1
  13. package/dist/cjs/wm-modal-footer.cjs.entry.js +1 -1
  14. package/dist/cjs/wm-modal-header.cjs.entry.js +1 -1
  15. package/dist/cjs/wm-modal.cjs.entry.js +1 -1
  16. package/dist/cjs/wm-navigation_3.cjs.entry.js +1 -1
  17. package/dist/cjs/wm-navigator.cjs.entry.js +1 -1
  18. package/dist/cjs/wm-network-uploader.cjs.entry.js +6 -4
  19. package/dist/cjs/wm-option_2.cjs.entry.js +345 -122
  20. package/dist/cjs/wm-pagination.cjs.entry.js +1 -1
  21. package/dist/cjs/wm-progress-indicator_3.cjs.entry.js +2 -2
  22. package/dist/cjs/wm-search.cjs.entry.js +1 -1
  23. package/dist/cjs/wm-snackbar.cjs.entry.js +1 -1
  24. package/dist/cjs/wm-tab-item_3.cjs.entry.js +1 -1
  25. package/dist/cjs/wm-tag-input.cjs.entry.js +1 -1
  26. package/dist/cjs/wm-timepicker.cjs.entry.js +1 -1
  27. package/dist/cjs/wm-toggletip.cjs.entry.js +4 -4
  28. package/dist/cjs/wm-uploader.cjs.entry.js +9 -11
  29. package/dist/collection/components/wm-button/wm-button.css +1 -0
  30. package/dist/collection/components/wm-button/wm-button.js +50 -40
  31. package/dist/collection/components/wm-modal/wm-modal-footer.js +1 -1
  32. package/dist/collection/components/wm-option/wm-option.css +12 -0
  33. package/dist/collection/components/wm-option/wm-option.js +34 -29
  34. package/dist/collection/components/wm-select/wm-select.css +76 -23
  35. package/dist/collection/components/wm-select/wm-select.js +385 -125
  36. package/dist/collection/components/wm-toggletip/wm-toggletip.js +5 -5
  37. package/dist/collection/components/wm-uploader/wm-network-uploader/wm-network-uploader.css +0 -3
  38. package/dist/collection/components/wm-uploader/wm-network-uploader/wm-network-uploader.js +4 -2
  39. package/dist/collection/components/wm-uploader/wm-uploader.css +1 -5
  40. package/dist/collection/components/wm-uploader/wm-uploader.js +7 -9
  41. package/dist/collection/global/__mocks__/functions.js +9 -0
  42. package/dist/collection/global/functions.js +1 -28
  43. package/dist/collection/global/global.js +6 -4
  44. package/dist/esm/{chartFunctions-8fa800a6.js → chartFunctions-20f05eb5.js} +1 -1
  45. package/dist/esm/{functions-61c7bb1f.js → functions-036af8dc.js} +245 -32
  46. package/dist/esm/{global-5902ef31.js → global-590c515d.js} +7 -5
  47. package/dist/esm/loader.js +2 -2
  48. package/dist/esm/priv-chart-popover.entry.js +1 -1
  49. package/dist/esm/priv-datepicker.entry.js +1 -1
  50. package/dist/esm/ripple.js +2 -2
  51. package/dist/esm/wm-action-menu_2.entry.js +1 -1
  52. package/dist/esm/wm-button.entry.js +51 -39
  53. package/dist/esm/wm-chart.entry.js +2 -2
  54. package/dist/esm/wm-datepicker.entry.js +1 -1
  55. package/dist/esm/wm-input.entry.js +1 -1
  56. package/dist/esm/wm-modal-footer.entry.js +1 -1
  57. package/dist/esm/wm-modal-header.entry.js +1 -1
  58. package/dist/esm/wm-modal.entry.js +1 -1
  59. package/dist/esm/wm-navigation_3.entry.js +1 -1
  60. package/dist/esm/wm-navigator.entry.js +1 -1
  61. package/dist/esm/wm-network-uploader.entry.js +6 -4
  62. package/dist/esm/wm-option_2.entry.js +345 -122
  63. package/dist/esm/wm-pagination.entry.js +1 -1
  64. package/dist/esm/wm-progress-indicator_3.entry.js +2 -2
  65. package/dist/esm/wm-search.entry.js +1 -1
  66. package/dist/esm/wm-snackbar.entry.js +1 -1
  67. package/dist/esm/wm-tab-item_3.entry.js +1 -1
  68. package/dist/esm/wm-tag-input.entry.js +1 -1
  69. package/dist/esm/wm-timepicker.entry.js +1 -1
  70. package/dist/esm/wm-toggletip.entry.js +4 -4
  71. package/dist/esm/wm-uploader.entry.js +9 -11
  72. package/dist/esm-es5/{chartFunctions-8fa800a6.js → chartFunctions-20f05eb5.js} +1 -1
  73. package/dist/esm-es5/{functions-61c7bb1f.js → functions-036af8dc.js} +2 -2
  74. package/dist/esm-es5/global-590c515d.js +1 -0
  75. package/dist/esm-es5/loader.js +1 -1
  76. package/dist/esm-es5/priv-chart-popover.entry.js +1 -1
  77. package/dist/esm-es5/priv-datepicker.entry.js +1 -1
  78. package/dist/esm-es5/ripple.js +1 -1
  79. package/dist/esm-es5/wm-action-menu_2.entry.js +1 -1
  80. package/dist/esm-es5/wm-button.entry.js +1 -1
  81. package/dist/esm-es5/wm-chart.entry.js +1 -1
  82. package/dist/esm-es5/wm-datepicker.entry.js +1 -1
  83. package/dist/esm-es5/wm-input.entry.js +1 -1
  84. package/dist/esm-es5/wm-modal-footer.entry.js +1 -1
  85. package/dist/esm-es5/wm-modal-header.entry.js +1 -1
  86. package/dist/esm-es5/wm-modal.entry.js +1 -1
  87. package/dist/esm-es5/wm-navigation_3.entry.js +1 -1
  88. package/dist/esm-es5/wm-navigator.entry.js +1 -1
  89. package/dist/esm-es5/wm-network-uploader.entry.js +1 -1
  90. package/dist/esm-es5/wm-option_2.entry.js +1 -1
  91. package/dist/esm-es5/wm-pagination.entry.js +1 -1
  92. package/dist/esm-es5/wm-progress-indicator_3.entry.js +1 -1
  93. package/dist/esm-es5/wm-search.entry.js +1 -1
  94. package/dist/esm-es5/wm-snackbar.entry.js +1 -1
  95. package/dist/esm-es5/wm-tab-item_3.entry.js +1 -1
  96. package/dist/esm-es5/wm-tag-input.entry.js +1 -1
  97. package/dist/esm-es5/wm-timepicker.entry.js +1 -1
  98. package/dist/esm-es5/wm-toggletip.entry.js +1 -1
  99. package/dist/esm-es5/wm-uploader.entry.js +1 -1
  100. package/dist/ripple/{p-28bf6a2e.system.js → p-04d8b674.system.js} +1 -1
  101. package/dist/ripple/{p-d3ed8b65.system.entry.js → p-04e44b30.system.entry.js} +1 -1
  102. package/dist/ripple/{p-fdc4a599.system.entry.js → p-0556279c.system.entry.js} +1 -1
  103. package/dist/ripple/{p-1242752c.system.entry.js → p-06adbeb9.system.entry.js} +1 -1
  104. package/dist/ripple/{p-42aa51fe.system.entry.js → p-0e9ccc6f.system.entry.js} +1 -1
  105. package/dist/ripple/{p-520b0f54.entry.js → p-17ceb8c1.entry.js} +1 -1
  106. package/dist/ripple/{p-8caae464.entry.js → p-1887286e.entry.js} +1 -1
  107. package/dist/ripple/{p-c873b490.system.entry.js → p-1ccd994d.system.entry.js} +1 -1
  108. package/dist/ripple/p-1d795f42.entry.js +1 -0
  109. package/dist/ripple/p-2996bfe6.entry.js +1 -0
  110. package/dist/ripple/{p-30745db6.entry.js → p-2f860b24.entry.js} +1 -1
  111. package/dist/ripple/p-3489b502.js +1 -0
  112. package/dist/ripple/{p-cd4fda75.entry.js → p-3680b55d.entry.js} +1 -1
  113. package/dist/ripple/p-3745c620.system.js +1 -0
  114. package/dist/ripple/{p-f12a510f.entry.js → p-3a1d6fc4.entry.js} +1 -1
  115. package/dist/ripple/p-42337590.entry.js +1 -0
  116. package/dist/ripple/{p-68155230.system.entry.js → p-49fd7ede.system.entry.js} +1 -1
  117. package/dist/ripple/{p-8aa9f811.js → p-4ecd3430.js} +1 -1
  118. package/dist/ripple/{p-5471864e.system.entry.js → p-62eac2d6.system.entry.js} +1 -1
  119. package/dist/ripple/{p-5e041c35.entry.js → p-6aa6a818.entry.js} +1 -1
  120. package/dist/ripple/{p-487f7419.system.entry.js → p-6bf5cbf4.system.entry.js} +1 -1
  121. package/dist/ripple/{p-e180001c.system.entry.js → p-7173b0a7.system.entry.js} +1 -1
  122. package/dist/ripple/p-726c979a.system.js +15 -0
  123. package/dist/ripple/{p-eacd33cc.system.entry.js → p-752da0fb.system.entry.js} +1 -1
  124. package/dist/ripple/{p-f36b74bf.entry.js → p-7ae1a630.entry.js} +1 -1
  125. package/dist/ripple/{p-8d347cd5.entry.js → p-7ecbf258.entry.js} +1 -1
  126. package/dist/ripple/{p-75ef731b.system.entry.js → p-7ef6a7cf.system.entry.js} +1 -1
  127. package/dist/ripple/p-8612829b.system.entry.js +1 -0
  128. package/dist/ripple/{p-398b2486.system.entry.js → p-895f5ec5.system.entry.js} +1 -1
  129. package/dist/ripple/{p-d3603def.entry.js → p-8de546e8.entry.js} +1 -1
  130. package/dist/ripple/{p-35cfcf9f.entry.js → p-93dee724.entry.js} +1 -1
  131. package/dist/ripple/{p-0f33461d.entry.js → p-97c2b06f.entry.js} +1 -1
  132. package/dist/ripple/{p-9f12284b.system.entry.js → p-995ba16f.system.entry.js} +1 -1
  133. package/dist/ripple/p-9c92c93f.entry.js +1 -0
  134. package/dist/ripple/p-9e09d7a1.entry.js +1 -0
  135. package/dist/ripple/{p-f0656464.entry.js → p-a04ba6c8.entry.js} +1 -1
  136. package/dist/ripple/{p-44035b02.system.entry.js → p-af3ce4fc.system.entry.js} +1 -1
  137. package/dist/ripple/p-bbcafbd6.system.entry.js +1 -0
  138. package/dist/ripple/{p-eee347b4.system.entry.js → p-c1443a0e.system.entry.js} +1 -1
  139. package/dist/ripple/{p-212aac05.system.entry.js → p-ca383a43.system.entry.js} +1 -1
  140. package/dist/ripple/{p-ca2fbd1b.system.js → p-cc247ee1.system.js} +1 -1
  141. package/dist/ripple/{p-73d66b0a.system.entry.js → p-cd3d74d1.system.entry.js} +1 -1
  142. package/dist/ripple/p-d1ac96e1.system.entry.js +1 -0
  143. package/dist/ripple/{p-3f1d8211.system.entry.js → p-d48c56c7.system.entry.js} +1 -1
  144. package/dist/ripple/{p-15b1c11b.js → p-de3367ee.js} +2 -2
  145. package/dist/ripple/{p-e748e22b.entry.js → p-e083fca6.entry.js} +1 -1
  146. package/dist/ripple/{p-3e6498ea.system.entry.js → p-e4439bc3.system.entry.js} +1 -1
  147. package/dist/ripple/{p-e49b9a96.entry.js → p-e524d462.entry.js} +1 -1
  148. package/dist/ripple/{p-92226595.entry.js → p-e8d39f68.entry.js} +1 -1
  149. package/dist/ripple/{p-00fa3d4b.entry.js → p-ed91be1a.entry.js} +1 -1
  150. package/dist/ripple/{p-d81a4e7c.system.entry.js → p-f23b3986.system.entry.js} +1 -1
  151. package/dist/ripple/{p-e75e75e0.entry.js → p-fda61e7e.entry.js} +1 -1
  152. package/dist/ripple/p-fe952112.entry.js +1 -0
  153. package/dist/ripple/ripple.esm.js +1 -1
  154. package/dist/ripple/ripple.js +1 -1
  155. package/dist/types/components/wm-button/wm-button.d.ts +4 -4
  156. package/dist/types/components/wm-option/wm-option.d.ts +5 -2
  157. package/dist/types/components/wm-select/wm-select.d.ts +39 -12
  158. package/dist/types/components/wm-toggletip/wm-toggletip.d.ts +2 -2
  159. package/dist/types/components.d.ts +10 -6
  160. package/dist/types/global/__mocks__/functions.d.ts +1 -0
  161. package/dist/types/global/functions.d.ts +2 -2
  162. package/dist/types/global/interfaces.d.ts +1 -1
  163. package/package.json +1 -1
  164. package/dist/esm-es5/global-5902ef31.js +0 -1
  165. package/dist/ripple/p-1b058a44.entry.js +0 -1
  166. package/dist/ripple/p-2077203e.system.js +0 -1
  167. package/dist/ripple/p-379b125b.entry.js +0 -1
  168. package/dist/ripple/p-49bf0b81.js +0 -1
  169. package/dist/ripple/p-584fef7f.system.entry.js +0 -1
  170. package/dist/ripple/p-72eb5064.system.entry.js +0 -1
  171. package/dist/ripple/p-76ca7498.system.js +0 -15
  172. package/dist/ripple/p-9fe64cec.entry.js +0 -1
  173. package/dist/ripple/p-a82d37d8.entry.js +0 -1
  174. package/dist/ripple/p-ac2485a6.system.entry.js +0 -1
  175. package/dist/ripple/p-ba168596.entry.js +0 -1
  176. package/dist/ripple/p-ed657559.entry.js +0 -1
@@ -1,6 +1,6 @@
1
1
  import { h, Component, Element, Event, Listen, Prop, State, Watch, Host } from "@stencil/core";
2
2
  import { forceUpdate } from "@stencil/core";
3
- import { generateId, getTextDir, shouldOpenUp, intl } from "../../global/functions";
3
+ import { generateId, getTextDir, shouldOpenUp, intl, debounce } from "../../global/functions";
4
4
  export class Select {
5
5
  constructor() {
6
6
  this.disabled = false;
@@ -9,11 +9,17 @@ export class Select {
9
9
  this.requiredField = false;
10
10
  this.errorMessage = "";
11
11
  this.multiple = false;
12
+ this.search = false;
12
13
  this.placeholder = intl.formatMessage({
13
14
  id: "select.multiPlaceholder",
14
15
  defaultMessage: "Make a selection",
15
16
  description: "Placeholder text. Use imperative",
16
17
  });
18
+ this.searchPlaceholder = intl.formatMessage({
19
+ id: "select.searchPlaceholder",
20
+ defaultMessage: "Search",
21
+ description: "Placeholder text. Use imperative",
22
+ });
17
23
  this.allSelectedMessage = intl.formatMessage({
18
24
  id: "select.allSelected",
19
25
  defaultMessage: "All selected",
@@ -25,21 +31,68 @@ export class Select {
25
31
  });
26
32
  this.isTabbing = false;
27
33
  this.isExpanded = false;
34
+ this.announcement = "";
28
35
  this.keysSoFar = "";
29
36
  this.searchIndex = 0;
30
37
  this.keyClear = null;
31
38
  this.openUp = false;
39
+ //////////////////////////////////////
40
+ //////////////////////////////////////
32
41
  // for multiselect button text
33
42
  this.overflowCount = 0;
34
- this.displayedItems = [];
35
- this.allSelected = false;
43
+ this.displayedOptions = [];
44
+ this.debouncedSearch = debounce(() => {
45
+ this.wmSelectSearchChanged.emit({ searchTerm: this.searchTerm });
46
+ if (this.filteredOptions.length) {
47
+ this.announce(this.resultsFoundMessage);
48
+ }
49
+ else {
50
+ this.announce(this.noResultsFoundMessage);
51
+ }
52
+ }, 150);
36
53
  }
37
- get childItems() {
54
+ get childOptions() {
38
55
  return Array.from(this.el.querySelectorAll("wm-option"));
39
56
  }
40
- get selectedItems() {
57
+ get duplicateOptions() {
58
+ return Array.from(this.el.shadowRoot.querySelectorAll("wm-option"));
59
+ }
60
+ get allOptionEls() {
61
+ // this includes both slotted wm-options and internally created wm-options
62
+ return this.duplicateOptions.concat(this.childOptions);
63
+ }
64
+ get visibleOptionEls() {
65
+ return this.allOptionEls.filter((option) => !option.classList.contains("hidden") && !option.classList.contains("filtered-out"));
66
+ }
67
+ //////////////////////////////////////
68
+ // for search variants
69
+ get searchTerm() {
70
+ return this.searchFieldEl ? this.searchFieldEl.value : "";
71
+ }
72
+ get filteredOptions() {
73
+ return this.childOptions.filter((option) => { var _a; return (_a = option.textContent) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(this.searchTerm); });
74
+ }
75
+ get selectedOptions() {
41
76
  return Array.from(this.el.querySelectorAll("wm-option")).filter((x) => x.selected);
42
77
  }
78
+ get allSelected() {
79
+ return this.childOptions.filter((option) => option.selected).length === this.childOptions.length;
80
+ }
81
+ //////////////////////////////////////
82
+ get resultsFoundMessage() {
83
+ return intl.formatMessage({
84
+ id: "select.searchResultsFound",
85
+ defaultMessage: "{numResults, plural, one {1 option found} other {# options found}}",
86
+ description: "The message read by the screen reader, indicating how many results a search returned",
87
+ }, { numResults: this.filteredOptions.length });
88
+ }
89
+ get noResultsFoundMessage() {
90
+ return intl.formatMessage({
91
+ id: "select.noSearchResults",
92
+ defaultMessage: "No results found. Please try your search again.",
93
+ description: "The message displayed when no options pass the search filter",
94
+ });
95
+ }
43
96
  toggleTabbingOn() {
44
97
  this.isTabbing = true;
45
98
  }
@@ -48,14 +101,11 @@ export class Select {
48
101
  }
49
102
  handleOptionSelection(ev) {
50
103
  if (!this.multiple) {
51
- // ensure only one option is selected at a time
52
- this.childItems
53
- // remove selected on any other option
54
- .filter((option) => option != ev.target && !!option.selected)
55
- .map((option) => (option.selected = false));
56
- }
57
- this.focusItem(ev.target);
58
- this.selectItem(ev.target);
104
+ // ensure only one option is selected at a time, unselect all other options
105
+ this.childOptions.forEach((option) => (option.selected = option === ev.detail));
106
+ }
107
+ this.focusOption(ev.detail);
108
+ this.selectOption(ev.detail);
59
109
  if (!this.multiple) {
60
110
  this.close();
61
111
  }
@@ -65,28 +115,24 @@ export class Select {
65
115
  this.close();
66
116
  }
67
117
  handleChildUp(ev) {
68
- this.moveUp(ev.target);
118
+ this.moveUp(ev.detail);
69
119
  }
70
120
  handleChildDown(ev) {
71
- this.moveDown(ev.target);
72
- }
73
- moveToFirstItem() {
74
- this.focusItem(this.childItems[0]);
121
+ this.moveDown(ev.detail);
75
122
  }
76
- moveToLastItem() {
77
- this.focusItem(this.childItems[this.childItems.length - 1]);
123
+ moveToFirstOption() {
124
+ this.focusOption(this.visibleOptionEls[0]);
78
125
  }
79
- handleTabKey() {
80
- this.close(false);
126
+ moveToLastOption() {
127
+ this.focusOption(this.visibleOptionEls[this.visibleOptionEls.length - 1]);
81
128
  }
82
129
  closePopupOnEscape() {
83
130
  this.close();
84
131
  }
85
132
  handleOptionBlur(ev) {
86
- const toElOrChild = ev.detail.relatedTarget === this.el || this.el.contains(ev.detail.relatedTarget);
87
133
  // if the Option is blurred to something other than the component emit a blur event with the appropriate relatedTarget
88
134
  // keeps our component's blur events accurate, and closes when focusing browser address bar
89
- if (!toElOrChild) {
135
+ if (!this.isElOrChild(ev.detail.relatedTarget)) {
90
136
  const event = new CustomEvent("blur");
91
137
  // @ts-ignore
92
138
  event.relatedTarget = ev.detail.relatedTarget;
@@ -94,18 +140,23 @@ export class Select {
94
140
  }
95
141
  }
96
142
  handleClick(ev) {
97
- const isElOrChild = ev.target === this.el || this.el.contains(ev.target);
98
- if (!isElOrChild && this.isExpanded) {
143
+ if (!this.isElOrChild(ev.target)) {
99
144
  this.close();
100
145
  }
101
146
  }
102
147
  handleButtonBlur(ev) {
103
- const toElOrChild = ev.relatedTarget === this.el || this.el.contains(ev.relatedTarget);
104
- if (toElOrChild) {
148
+ if (this.isElOrChild(ev.relatedTarget)) {
105
149
  // do not emit a blur event when opening the dropdown and focusing the Options
106
150
  ev.stopPropagation();
107
151
  }
108
152
  }
153
+ handleSearchFieldBlur(ev) {
154
+ this.searchFieldWrapperEl.classList.remove("focus");
155
+ if (this.isElOrChild(ev.relatedTarget)) {
156
+ // do not emit a blur event when moving from searchfield to options
157
+ ev.stopPropagation();
158
+ }
159
+ }
109
160
  handleKey(ev) {
110
161
  switch (ev.key) {
111
162
  case "ArrowDown":
@@ -135,137 +186,236 @@ export class Select {
135
186
  if (document.body.classList.contains("wmcl-user-is-tabbing")) {
136
187
  this.toggleTabbingOn();
137
188
  }
189
+ // set initial selections
190
+ if (this.selectedOptions.length > 0) {
191
+ this.selectedOptions.forEach((x) => {
192
+ this.displayedOptions.push(x);
193
+ });
194
+ // single Select only, pre-select if no default option from dev
195
+ }
196
+ else if (!this.multiple) {
197
+ this.selectOption(this.allOptionEls[0]);
198
+ }
138
199
  }
139
200
  componentDidLoad() {
140
201
  this.wmSelectDidLoad.emit();
141
- if (!this.childItems.length) {
142
- throw new Error("wm-select should have wm-option elements as children.");
143
- }
144
- if (this.multiple && this.childItems.filter((x) => x.subinfo).length > 0) {
202
+ if (this.multiple && this.allOptionEls.filter((x) => x.subinfo).length > 0) {
145
203
  throw new Error("wm-select with the multiple prop cannot have subinfo options");
146
204
  }
147
205
  if (this.multiple && !this.placeholder) {
148
206
  throw new Error("wm-select with the multiple prop needs to also use the placeholder prop.");
149
207
  }
150
- // set initial selections / button text
151
- if (this.selectedItems.length > 0) {
152
- this.selectedItems.forEach((x) => this.displayedItems.push(x));
153
- this.setButtonText();
154
- // single Select only, pre-select if no default option from dev
155
- }
156
- else if (!this.multiple) {
157
- this.selectItem(this.childItems[0]);
158
- }
159
- this.optionsEl.classList.add("hidden");
208
+ this.dropdownEl.classList.add("hidden");
160
209
  forceUpdate(this.el);
161
210
  // Dev can overwrite the max-height rule set in the Sass file
162
211
  if (this.maxHeight) {
163
- this.optionsEl.style.maxHeight = this.maxHeight;
212
+ this.dropdownEl.style.maxHeight = this.maxHeight;
213
+ }
214
+ const mutationObserver = new MutationObserver(() => this.handleSelectedMutation());
215
+ mutationObserver.observe(this.el, {
216
+ attributes: true,
217
+ attributeFilter: ["selected"],
218
+ subtree: true,
219
+ });
220
+ if (this.multiple) {
221
+ this.updateOptionVisibility();
222
+ }
223
+ this.setButtonText();
224
+ }
225
+ componentWillUpdate() {
226
+ if (this.multiple) {
227
+ // find last visible duplicate option and apply .last class
228
+ const visibleDuplicateOptions = this.visibleOptionEls.filter((option) => option.classList.contains("duplicate"));
229
+ visibleDuplicateOptions.forEach((option, idx) => {
230
+ if (idx === visibleDuplicateOptions.length - 1) {
231
+ option.classList.add("last");
232
+ }
233
+ else {
234
+ option.classList.remove("last");
235
+ }
236
+ });
164
237
  }
165
238
  }
239
+ handleSelectedMutation() {
240
+ // dispatch change event after selected options change
241
+ // mutation observer prevents emitting event when an already selected option is selected again
242
+ const event = new CustomEvent("change");
243
+ // @ts-ignore
244
+ this.el.dispatchEvent(event);
245
+ }
166
246
  moveUp(el) {
167
- const prevEl = el.previousElementSibling;
247
+ const prevEl = this.visibleOptionEls[this.visibleOptionEls.indexOf(el) - 1];
168
248
  if (prevEl) {
169
249
  // scroll option to top of dropdown if partially obscured / out of view
170
- if (prevEl.getBoundingClientRect().top < this.optionsEl.getBoundingClientRect().top) {
171
- this.optionsEl.scrollTop =
172
- prevEl.getBoundingClientRect().top - this.optionsEl.getBoundingClientRect().top + this.optionsEl.scrollTop;
250
+ if (prevEl.getBoundingClientRect().top < this.dropdownEl.getBoundingClientRect().top) {
251
+ this.scrollOptionToTop(prevEl);
173
252
  }
174
- this.focusItem(prevEl);
253
+ this.focusOption(prevEl);
254
+ }
255
+ else if (this.search) {
256
+ // if top of list and search variant, focus search field
257
+ this.searchFieldEl.focus();
175
258
  }
176
259
  else {
177
- this.focusItem(this.childItems[this.childItems.length - 1]);
260
+ // if top of list, focus last element
261
+ this.focusOption(this.visibleOptionEls[this.visibleOptionEls.length - 1]);
178
262
  }
179
263
  }
180
264
  moveDown(el) {
181
- const nextEl = el.nextElementSibling;
182
- if (nextEl && nextEl.tagName !== "INPUT") {
265
+ const nextEl = this.visibleOptionEls[this.visibleOptionEls.indexOf(el) + 1];
266
+ if (nextEl) {
183
267
  // scroll option to bottom of dropdown if partially obscured / out of view
184
- if (nextEl.getBoundingClientRect().bottom > this.optionsEl.getBoundingClientRect().bottom) {
185
- this.optionsEl.scrollTop =
186
- nextEl.getBoundingClientRect().bottom -
187
- this.optionsEl.getBoundingClientRect().top +
188
- this.optionsEl.scrollTop -
189
- this.optionsEl.offsetHeight;
268
+ if (nextEl.getBoundingClientRect().bottom > this.dropdownEl.getBoundingClientRect().bottom) {
269
+ this.scrollOptionToBottom(nextEl);
190
270
  }
191
- this.focusItem(nextEl);
271
+ this.focusOption(nextEl);
192
272
  }
193
273
  else {
194
- this.focusItem(this.childItems[0]);
274
+ // if end of list, focus first option in all variants
275
+ this.focusOption(this.visibleOptionEls[0]);
195
276
  }
196
277
  }
197
- open(itemToSelect) {
278
+ scrollOptionToTop(option) {
279
+ this.dropdownEl.scrollTop =
280
+ option.getBoundingClientRect().top - this.dropdownEl.getBoundingClientRect().top + this.dropdownEl.scrollTop;
281
+ }
282
+ scrollOptionToBottom(option) {
283
+ this.dropdownEl.scrollTop =
284
+ option.getBoundingClientRect().bottom -
285
+ this.dropdownEl.getBoundingClientRect().top +
286
+ this.dropdownEl.scrollTop -
287
+ this.dropdownEl.offsetHeight;
288
+ }
289
+ open(optionToSelect) {
198
290
  if (!this.disabled) {
199
291
  const elHeight = this.el.clientHeight;
200
292
  const buttonHeight = this.buttonEl.clientHeight;
201
- this.openUp = shouldOpenUp(this.el, this.optionsEl,
293
+ this.openUp = shouldOpenUp(this.el, this.dropdownEl,
202
294
  // when opening up, dropdown covers both label and button
203
295
  elHeight,
204
296
  // when opening down, dropdown covers only the button
205
297
  buttonHeight);
206
298
  this.isExpanded = true;
207
- this.optionsEl.classList.remove("hidden");
299
+ this.dropdownEl.classList.remove("hidden");
208
300
  window.requestAnimationFrame(() => {
209
- if (this.selectedItems.length > 0) {
210
- if (itemToSelect === "next") {
211
- this.moveDown(this.selectedItems[this.selectedItems.length - 1]);
212
- }
213
- else if (itemToSelect === "previous") {
214
- this.moveUp(this.selectedItems[0]);
215
- }
216
- else {
217
- this.focusItem(this.selectedItems[0]);
218
- }
219
- }
220
- else {
221
- this.focusItem(this.childItems[0]);
301
+ switch (optionToSelect) {
302
+ case "next":
303
+ // search variant focuses search field
304
+ // all others focus option "after" last selected option (this can be the first option)
305
+ if (this.search) {
306
+ this.searchFieldEl.focus();
307
+ this.dropdownEl.scrollTop = 0;
308
+ }
309
+ else {
310
+ this.moveDown(this.visibleOptionEls.filter((x) => x.selected).slice(-1)[0]);
311
+ }
312
+ break;
313
+ case "previous":
314
+ // search variant focuses last option
315
+ // all others focus option "above" first selected option (this can be the last option)
316
+ if (this.search) {
317
+ this.focusOption(this.visibleOptionEls[this.visibleOptionEls.length - 1]);
318
+ }
319
+ else {
320
+ this.moveUp(this.visibleOptionEls.filter((x) => x.selected)[0]);
321
+ }
322
+ break;
323
+ default:
324
+ // search variant focuses search field
325
+ // all others focus the selected option
326
+ // if no option is selected (empty multiselect), focuses first option
327
+ if (this.search) {
328
+ this.searchFieldEl.focus();
329
+ this.dropdownEl.scrollTop = 0;
330
+ }
331
+ else if (this.selectedOptions.length > 0) {
332
+ this.focusOption(this.visibleOptionEls.filter((x) => x.selected)[0]);
333
+ }
334
+ else {
335
+ this.focusOption(this.visibleOptionEls[0]);
336
+ }
337
+ break;
222
338
  }
223
339
  });
224
340
  }
225
341
  }
226
342
  close(returnFocus = true) {
227
- this.isExpanded = false;
228
- this.childItems.map((i) => (i.focused = false));
229
- window.setTimeout(() => {
230
- this.optionsEl.classList.add("hidden");
231
- // Returns focus to button after popup closes (no need if user is tabbing)
232
- // Delay is necessary for screenreader to get new expanded state before focus
233
- // window.requestAnimationFrame is probably enough, but since we are already using setTimeout it may as well be here
234
- // also UX wise, it makes sense for the button to only be focused after the animation is complete
235
- if (returnFocus) {
236
- this.el.focus();
343
+ if (this.isExpanded) {
344
+ this.isExpanded = false;
345
+ this.allOptionEls.map((i) => (i.focused = false));
346
+ window.setTimeout(() => {
347
+ this.dropdownEl.classList.add("hidden");
348
+ if (this.multiple) {
349
+ this.updateOptionVisibility();
350
+ }
351
+ // clear search field, reset filtered / bolded state of wm-options
352
+ if (this.search) {
353
+ this.searchFieldEl.value = "";
354
+ this.wmSelectSearchChanged.emit({ searchTerm: this.searchTerm });
355
+ }
356
+ // Returns focus to button after popup closes (no need if user is tabbing)
357
+ // Delay is necessary for screenreader to get new expanded state before focus
358
+ // window.requestAnimationFrame is probably enough, but since we are already using setTimeout it may as well be here
359
+ // also UX wise, it makes sense for the button to only be focused after the animation is complete
360
+ if (returnFocus) {
361
+ this.el.focus();
362
+ }
363
+ }, 150);
364
+ }
365
+ }
366
+ updateOptionVisibility() {
367
+ // this runs for search multiselects, where selected options are rendered at the top of the dropdown list
368
+ // slotted wm-options are hidden if selected, and duplicate wm-options are made visible if selected
369
+ this.childOptions.forEach((option, idx) => {
370
+ const duplicateOption = this.duplicateOptions[idx];
371
+ if (option.selected) {
372
+ option.classList.add("hidden");
373
+ duplicateOption.classList.remove("hidden");
237
374
  }
238
- }, 150);
375
+ else {
376
+ option.classList.remove("hidden");
377
+ duplicateOption.classList.add("hidden");
378
+ }
379
+ });
239
380
  }
240
- focusItem(item) {
241
- this.childItems.forEach((i) => (i.focused = i === item));
381
+ focusOption(option) {
382
+ this.allOptionEls.forEach((i) => (i.focused = i === option));
383
+ option.focus();
242
384
  }
243
- selectItem(item) {
244
- if (this.multiple) {
245
- item.selected = !item.selected;
385
+ selectOption(option) {
386
+ // this function does not necessarily change an options selected property to true
387
+ // in cases of multiselect, it toggles the selected property
388
+ if (option.classList.contains("duplicate")) {
389
+ // if clicking on a duplicate option, toggle selected property of real one, then rerender
390
+ const correspondingOption = this.findCorrespondingOption(option);
391
+ correspondingOption.selected = !correspondingOption.selected;
392
+ forceUpdate(this.el);
393
+ }
394
+ else if (this.multiple) {
395
+ option.selected = !option.selected;
246
396
  }
247
397
  else {
248
- this.childItems.forEach((i) => (i.selected = i === item));
398
+ this.allOptionEls.forEach((x) => (x.selected = x === option));
249
399
  }
250
400
  this.setButtonText();
251
401
  }
252
- findAndFocusItem(ev) {
402
+ findAndFocusOption(ev) {
253
403
  const character = ev.detail.toUpperCase();
254
404
  if (!this.keysSoFar) {
255
- for (var i = 0; i < this.childItems.length; i++) {
256
- if (this.childItems[i].focused) {
405
+ for (var i = 0; i < this.allOptionEls.length; i++) {
406
+ if (this.allOptionEls[i].focused) {
257
407
  this.searchIndex = i;
258
408
  }
259
409
  }
260
410
  }
261
411
  this.keysSoFar += character;
262
412
  this.clearKeysSoFarAfterDelay();
263
- var nextMatch = this.findMatchInRange(this.childItems, this.searchIndex + 1, this.childItems.length);
413
+ var nextMatch = this.findMatchInRange(this.allOptionEls, this.searchIndex + 1, this.allOptionEls.length);
264
414
  if (!nextMatch) {
265
- nextMatch = this.findMatchInRange(this.childItems, 0, this.searchIndex);
415
+ nextMatch = this.findMatchInRange(this.allOptionEls, 0, this.searchIndex);
266
416
  }
267
417
  if (nextMatch) {
268
- this.focusItem(nextMatch);
418
+ this.focusOption(nextMatch);
269
419
  }
270
420
  }
271
421
  clearKeysSoFarAfterDelay() {
@@ -279,8 +429,8 @@ export class Select {
279
429
  }.bind(this), 500);
280
430
  }
281
431
  findMatchInRange(list, startIndex, endIndex) {
282
- // Find the first item starting with the keysSoFar substring, searching in
283
- // the specified range of items
432
+ // Find the first option starting with the keysSoFar substring, searching in
433
+ // the specified range of options
284
434
  for (var n = startIndex; n < endIndex; n++) {
285
435
  var label = list[n].textContent;
286
436
  if (label && label.toUpperCase().indexOf(this.keysSoFar) === 0) {
@@ -289,6 +439,19 @@ export class Select {
289
439
  }
290
440
  return null;
291
441
  }
442
+ findCorrespondingOption(el) {
443
+ // if duplicate, returns the child wm-option
444
+ // if child wm-option, returns duplicate
445
+ const isDuplicate = el.classList.contains("duplicate");
446
+ return isDuplicate
447
+ ? this.childOptions[this.duplicateOptions.indexOf(el)]
448
+ : this.duplicateOptions[this.childOptions.indexOf(el)];
449
+ }
450
+ isElOrChild(el) {
451
+ var _a;
452
+ // determines whether or not the element is the component, a child of the component, or exists within the component's shadowroot
453
+ return el === this.el || this.el.contains(el) || ((_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.contains(el));
454
+ }
292
455
  exposeErrors() {
293
456
  // When the error changes, a new id is set for the error container and the button's aria-describedby attribute is updated accordingly. This is to make sure the screen reader announces teh updated errors in Firefox. See this longstanding bug: https://bugzilla.mozilla.org/show_bug.cgi?id=493683
294
457
  const newId = generateId();
@@ -306,9 +469,30 @@ export class Select {
306
469
  this.wmComponentBlurred.emit(); // deprecated
307
470
  }
308
471
  }
472
+ handleSearchFieldKeyDown(ev) {
473
+ switch (ev.key) {
474
+ case "ArrowDown":
475
+ ev.preventDefault();
476
+ if (this.visibleOptionEls.length) {
477
+ this.focusOption(this.visibleOptionEls[0]);
478
+ }
479
+ break;
480
+ case "ArrowUp":
481
+ ev.preventDefault();
482
+ if (this.visibleOptionEls.length) {
483
+ this.focusOption(this.visibleOptionEls[this.visibleOptionEls.length - 1]);
484
+ }
485
+ break;
486
+ case "Escape":
487
+ ev.preventDefault();
488
+ this.close();
489
+ break;
490
+ }
491
+ }
309
492
  setButtonText() {
310
- this.displayedItems = this.childItems.filter((x) => x.selected);
311
- this.allSelected = this.displayedItems.length === this.childItems.length;
493
+ this.displayedOptions = this.childOptions
494
+ .filter((x) => x.selected)
495
+ .map((y) => (!y.classList.contains("hidden") ? y : this.findCorrespondingOption(y)));
312
496
  // handle overflow + counter for multiselect
313
497
  if (this.multiple) {
314
498
  // this is a fixed measurement accounting for the max width of a 3 character overflow counter
@@ -318,34 +502,41 @@ export class Select {
318
502
  const paddingLeft = parseInt(computedStyle.getPropertyValue("padding-left").slice(0, -2));
319
503
  const paddingRight = parseInt(computedStyle.getPropertyValue("padding-right").slice(0, -2));
320
504
  const availableSpace = this.buttonEl.clientWidth - paddingLeft - paddingRight - overflowCounterWidth;
321
- let optionsWidths = this.displayedItems.map((x) => x.shadowRoot.querySelector(".option-wrapper").clientWidth);
505
+ let optionsWidths = this.displayedOptions.map((x) => x.shadowRoot.querySelector(".option-wrapper").clientWidth);
322
506
  let optionsTotalWidth = optionsWidths.reduce((acc, x) => acc + x, 0);
323
507
  this.overflowCount = 0;
324
- while (optionsTotalWidth > availableSpace && this.displayedItems.length > 1) {
508
+ while (optionsTotalWidth > availableSpace && this.displayedOptions.length > 1) {
325
509
  this.overflowCount++;
326
510
  optionsTotalWidth -= optionsWidths[optionsWidths.length - 1];
327
511
  optionsWidths.pop();
328
- this.displayedItems.pop();
512
+ this.displayedOptions.pop();
329
513
  }
330
514
  }
331
515
  }
516
+ announce(message) {
517
+ // \u00A0 is a non-breaking space character, which causes the message to be read as a new one
518
+ if (this.liveRegionEl.textContent === message) {
519
+ message += "\u00A0";
520
+ }
521
+ this.announcement = message;
522
+ }
332
523
  renderButtonText() {
333
- if (this.multiple && this.displayedItems.length < 1) {
524
+ if (this.multiple && this.displayedOptions.length < 1) {
334
525
  return h("span", null, this.placeholder);
335
526
  }
336
527
  else if (this.multiple && this.allSelected && this.overflowCount > 0) {
337
528
  return this.allSelectedMessage;
338
529
  }
339
530
  else {
340
- return this.displayedItems.map((x, idx) => (h("span", null,
531
+ return this.displayedOptions.map((x, idx) => (h("span", null,
341
532
  idx > 0 ? ", " : "",
342
533
  x.textContent)));
343
534
  }
344
535
  }
345
536
  renderSubinfo() {
346
537
  // multiselects cannot have subinfo for options
347
- if (!this.multiple && this.selectedItems.length > 0 && this.selectedItems[0].subinfo) {
348
- return h("span", { class: "subinfo" }, this.selectedItems[0].subinfo);
538
+ if (!this.multiple && this.selectedOptions.length > 0 && this.selectedOptions[0].subinfo) {
539
+ return h("span", { class: "subinfo" }, this.selectedOptions[0].subinfo);
349
540
  }
350
541
  }
351
542
  renderOverflowCount() {
@@ -356,6 +547,20 @@ export class Select {
356
547
  this.overflowCount)));
357
548
  }
358
549
  }
550
+ renderSearchField() {
551
+ return (h("div", { class: "search" },
552
+ h("div", { class: "searchfield-wrapper", ref: (el) => (this.searchFieldWrapperEl = el) },
553
+ h("div", { class: "icon" }),
554
+ h("input", { ref: (el) => (this.searchFieldEl = el), class: "searchfield", role: "combobox", "aria-controls": `list-${this.uid}`, "aria-expanded": this.isExpanded ? "true" : "false", onKeyDown: (ev) => this.handleSearchFieldKeyDown(ev), onFocus: () => this.searchFieldWrapperEl.classList.add("focus"), onBlur: (ev) => this.handleSearchFieldBlur(ev), onInput: () => this.debouncedSearch(), placeholder: this.searchPlaceholder }))));
555
+ }
556
+ renderSearchFailedMessage() {
557
+ return h("div", { class: "search-results-message" }, this.noResultsFoundMessage);
558
+ }
559
+ renderDuplicateOptions() {
560
+ return Array.from(this.el.children).map((option) => {
561
+ return (h("wm-option", { class: "duplicate", selected: option.selected }, option.textContent));
562
+ });
563
+ }
359
564
  render() {
360
565
  const buttonProps = {
361
566
  id: `selectbtn-${this.uid}`,
@@ -375,17 +580,22 @@ export class Select {
375
580
  this.requiredField ? (h("span", { class: "required" },
376
581
  h("span", { class: "sr-only" }, this.requiredMessage),
377
582
  h("span", { "aria-hidden": "true" }, "*"))) : (""))),
378
- h("div", { class: "dropdown" },
379
- h("button", Object.assign({}, buttonProps, { class: `displayedoption ${this.isTabbing ? "user-is-tabbing" : ""}`, ref: (el) => (this.buttonEl = el), onBlur: (ev) => this.handleButtonBlur(ev) }),
380
- h("span", { class: this.selectedItems.length > 0 && this.selectedItems.filter((x) => x.subinfo).length > 0
583
+ h("div", { class: "button-wrapper" },
584
+ h("button", Object.assign({}, buttonProps, { class: `displayedoption ${this.isTabbing ? "user-is-tabbing" : ""}`, ref: (el) => (this.buttonEl = el), onBlur: (ev) => this.handleButtonBlur(ev), onFocus: () => this.close() }),
585
+ h("span", { class: this.selectedOptions.length > 0 && this.selectedOptions.filter((x) => x.subinfo).length > 0
381
586
  ? "overflowcontrol hassubinfo"
382
587
  : "overflowcontrol" },
383
588
  h("span", { class: "button-text" }, this.renderButtonText()),
384
589
  this.renderSubinfo()),
385
590
  this.renderOverflowCount()),
386
- h("div", { class: `options ${this.isExpanded ? "open" : ""} ${this.openUp ? "upwards" : ""}`, id: `list-${this.uid}`, tabindex: -1, role: "listbox", "aria-multiselectable": this.multiple ? "true" : null, "aria-labelledby": `label-${this.uid}`, ref: (el) => (this.optionsEl = el) },
387
- h("slot", null)),
388
- this.renderErrorContainer()))));
591
+ h("div", { class: `dropdown ${this.isExpanded ? "open" : ""} ${this.openUp ? "upwards" : ""}`, ref: (el) => (this.dropdownEl = el) },
592
+ this.search && this.renderSearchField(),
593
+ h("div", { id: `list-${this.uid}`, tabindex: -1, role: "listbox", "aria-multiselectable": this.multiple ? "true" : null, "aria-labelledby": `label-${this.uid}` },
594
+ this.search && this.filteredOptions.length === 0 && this.renderSearchFailedMessage(),
595
+ this.multiple && this.renderDuplicateOptions(),
596
+ h("slot", null))),
597
+ this.renderErrorContainer(),
598
+ h("div", { "aria-live": "polite", class: "sr-only", ref: (el) => (this.liveRegionEl = el) }, this.announcement)))));
389
599
  }
390
600
  static get is() { return "wm-select"; }
391
601
  static get encapsulation() { return "shadow"; }
@@ -538,6 +748,24 @@ export class Select {
538
748
  "reflect": false,
539
749
  "defaultValue": "false"
540
750
  },
751
+ "search": {
752
+ "type": "boolean",
753
+ "mutable": false,
754
+ "complexType": {
755
+ "original": "boolean",
756
+ "resolved": "boolean",
757
+ "references": {}
758
+ },
759
+ "required": false,
760
+ "optional": false,
761
+ "docs": {
762
+ "tags": [],
763
+ "text": ""
764
+ },
765
+ "attribute": "search",
766
+ "reflect": false,
767
+ "defaultValue": "false"
768
+ },
541
769
  "placeholder": {
542
770
  "type": "string",
543
771
  "mutable": false,
@@ -556,6 +784,24 @@ export class Select {
556
784
  "reflect": false,
557
785
  "defaultValue": "intl.formatMessage({\r\n id: \"select.multiPlaceholder\",\r\n defaultMessage: \"Make a selection\",\r\n description: \"Placeholder text. Use imperative\",\r\n })"
558
786
  },
787
+ "searchPlaceholder": {
788
+ "type": "string",
789
+ "mutable": false,
790
+ "complexType": {
791
+ "original": "string",
792
+ "resolved": "string",
793
+ "references": {}
794
+ },
795
+ "required": false,
796
+ "optional": false,
797
+ "docs": {
798
+ "tags": [],
799
+ "text": ""
800
+ },
801
+ "attribute": "search-placeholder",
802
+ "reflect": false,
803
+ "defaultValue": "intl.formatMessage({\r\n id: \"select.searchPlaceholder\",\r\n defaultMessage: \"Search\",\r\n description: \"Placeholder text. Use imperative\",\r\n })"
804
+ },
559
805
  "allSelectedMessage": {
560
806
  "type": "string",
561
807
  "mutable": false,
@@ -577,7 +823,8 @@ export class Select {
577
823
  }; }
578
824
  static get states() { return {
579
825
  "isTabbing": {},
580
- "isExpanded": {}
826
+ "isExpanded": {},
827
+ "announcement": {}
581
828
  }; }
582
829
  static get events() { return [{
583
830
  "method": "wmSelectDidLoad",
@@ -624,6 +871,25 @@ export class Select {
624
871
  "resolved": "void",
625
872
  "references": {}
626
873
  }
874
+ }, {
875
+ "method": "wmSelectSearchChanged",
876
+ "name": "wmSelectSearchChanged",
877
+ "bubbles": true,
878
+ "cancelable": true,
879
+ "composed": true,
880
+ "docs": {
881
+ "tags": [],
882
+ "text": ""
883
+ },
884
+ "complexType": {
885
+ "original": "Object",
886
+ "resolved": "Object",
887
+ "references": {
888
+ "Object": {
889
+ "location": "global"
890
+ }
891
+ }
892
+ }
627
893
  }]; }
628
894
  static get elementRef() { return "el"; }
629
895
  static get watchers() { return [{
@@ -668,19 +934,13 @@ export class Select {
668
934
  "passive": false
669
935
  }, {
670
936
  "name": "wmHomeKeyPressed",
671
- "method": "moveToFirstItem",
937
+ "method": "moveToFirstOption",
672
938
  "target": undefined,
673
939
  "capture": false,
674
940
  "passive": false
675
941
  }, {
676
942
  "name": "wmEndKeyPressed",
677
- "method": "moveToLastItem",
678
- "target": undefined,
679
- "capture": false,
680
- "passive": false
681
- }, {
682
- "name": "wmTabKeyPressed",
683
- "method": "handleTabKey",
943
+ "method": "moveToLastOption",
684
944
  "target": undefined,
685
945
  "capture": false,
686
946
  "passive": false
@@ -710,7 +970,7 @@ export class Select {
710
970
  "passive": false
711
971
  }, {
712
972
  "name": "wmLetterPressed",
713
- "method": "findAndFocusItem",
973
+ "method": "findAndFocusOption",
714
974
  "target": undefined,
715
975
  "capture": false,
716
976
  "passive": false