@shoper/phoenix_design_system 1.11.13 → 1.11.14

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 (49) hide show
  1. package/build/cjs/packages/phoenix/src/components/form/search/search.js +279 -95
  2. package/build/cjs/packages/phoenix/src/components/form/search/search.js.map +1 -1
  3. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/buttons/search_clear.js +5 -0
  4. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/buttons/search_clear.js.map +1 -1
  5. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/history/search_history.js +22 -9
  6. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/history/search_history.js.map +1 -1
  7. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/input/search_input.js +15 -1
  8. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/input/search_input.js.map +1 -1
  9. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/message/search_message.js +8 -1
  10. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/message/search_message.js.map +1 -1
  11. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/results/search_producer_content.js +9 -4
  12. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/results/search_producer_content.js.map +1 -1
  13. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/results/search_product_content.js +9 -4
  14. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/results/search_product_content.js.map +1 -1
  15. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/results/search_results.js +11 -4
  16. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/results/search_results.js.map +1 -1
  17. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/results/search_suggestion_content.js +12 -5
  18. package/build/cjs/packages/phoenix/src/components/form/search/subcomponents/results/search_suggestion_content.js.map +1 -1
  19. package/build/cjs/packages/phoenix/src/index.js +12 -12
  20. package/build/esm/packages/phoenix/src/components/form/search/search.d.ts +26 -5
  21. package/build/esm/packages/phoenix/src/components/form/search/search.js +280 -96
  22. package/build/esm/packages/phoenix/src/components/form/search/search.js.map +1 -1
  23. package/build/esm/packages/phoenix/src/components/form/search/search_types.d.ts +4 -0
  24. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/buttons/search_clear.d.ts +2 -1
  25. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/buttons/search_clear.js +5 -0
  26. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/buttons/search_clear.js.map +1 -1
  27. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/history/search_history.d.ts +2 -2
  28. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/history/search_history.js +22 -9
  29. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/history/search_history.js.map +1 -1
  30. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/input/search_input.d.ts +1 -0
  31. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/input/search_input.js +16 -2
  32. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/input/search_input.js.map +1 -1
  33. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/message/search_message.d.ts +1 -0
  34. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/message/search_message.js +8 -1
  35. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/message/search_message.js.map +1 -1
  36. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_producer_content.d.ts +2 -1
  37. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_producer_content.js +9 -4
  38. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_producer_content.js.map +1 -1
  39. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_product_content.d.ts +2 -1
  40. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_product_content.js +9 -4
  41. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_product_content.js.map +1 -1
  42. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_results.d.ts +2 -1
  43. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_results.js +11 -4
  44. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_results.js.map +1 -1
  45. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_suggestion_content.d.ts +2 -1
  46. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_suggestion_content.js +12 -5
  47. package/build/esm/packages/phoenix/src/components/form/search/subcomponents/results/search_suggestion_content.js.map +1 -1
  48. package/build/esm/packages/phoenix/src/index.js +2 -2
  49. package/package.json +2 -2
@@ -15,6 +15,7 @@ var behavior_subject = require('../../../core/classes/behavior_subject/behavior_
15
15
  var ref_js = require('lit-html/directives/ref.js');
16
16
  var context_provider_controller = require('../../../core/context/context_provider_controller.js');
17
17
  var global_constants = require('../../../global_constants.js');
18
+ var v4 = require('../../../../../../external/uuid/dist/esm-browser/v4.js');
18
19
  var when = require('../../../../../../external/lit/external/lit-html/directives/when.js');
19
20
  var search_constants = require('./search_constants.js');
20
21
 
@@ -22,8 +23,11 @@ exports.HSearch = class HSearch extends phoenix_light_lit_element.PhoenixLightLi
22
23
  constructor() {
23
24
  super(...arguments);
24
25
  this.view = search_constants.DEFAULT_VIEW;
26
+ this._id = v4['default']();
27
+ this._searchContentContainerId = v4['default']();
25
28
  this._searchResultsRef = ref_js.createRef();
26
29
  this._searchHistoryRef = ref_js.createRef();
30
+ this._searchMessageRef = ref_js.createRef();
27
31
  this._shouldShowHistory = false;
28
32
  this._shouldShowResults = false;
29
33
  this._shouldShowMessage = false;
@@ -33,84 +37,225 @@ exports.HSearch = class HSearch extends phoenix_light_lit_element.PhoenixLightLi
33
37
  this._historyContext = new behavior_subject.BehaviorSubject({
34
38
  showLoadMore: false
35
39
  });
36
- this._activeItemId = -1;
40
+ this._activeItemId = `${this._id}-1`;
37
41
  this._translations = {};
42
+ this._containerRole = 'grid';
38
43
  this._bindKeys = (ev) => {
39
- var _a;
40
44
  switch (ev.key) {
41
45
  case 'ArrowDown':
42
46
  ev.preventDefault();
43
- this._focusOutsideActiveItemsForward();
44
- this._scroll(search_constants.SCROLL_DIRECTIONS.down);
47
+ this._handleForwardListFocus();
45
48
  break;
46
49
  case 'ArrowUp':
47
- ev.preventDefault();
48
- this._focusOutsideActiveItemsBackward();
49
- this._scroll(search_constants.SCROLL_DIRECTIONS.up);
50
+ this._handleBackwardListFocus(ev);
51
+ break;
52
+ case 'ArrowLeft':
53
+ if (this._containerRole === 'grid') {
54
+ ev.preventDefault();
55
+ this._handleBackwardGridFocus();
56
+ }
57
+ if (this._containerRole === 'listbox')
58
+ this._handleMoveToInputField();
59
+ break;
60
+ case 'ArrowRight':
61
+ if (this._containerRole === 'grid') {
62
+ ev.preventDefault();
63
+ this._handleForwardGridFocus();
64
+ }
65
+ if (this._containerRole === 'listbox')
66
+ this._handleMoveToInputField();
50
67
  break;
51
68
  case 'Enter':
52
69
  ev.preventDefault();
53
- if (this._activeItemId === -1 || !this._shouldShowResults)
70
+ if (this._activeItemId === `${this._id}-1` || !this._shouldShowResults)
54
71
  return;
55
72
  this._handleChooseSearchItem();
56
73
  break;
57
74
  case 'Escape':
58
75
  ev.preventDefault();
59
- this._inputField.blur();
60
- this._resetSearchView();
76
+ if (this._shouldShowHistory || this._shouldShowHistory || this._shouldShowResults) {
77
+ this._inputField.focus();
78
+ this._shouldShowMessage = false;
79
+ this._hideHistorySuggestionsAndResults();
80
+ }
81
+ else {
82
+ this._inputField.value = '';
83
+ }
84
+ break;
85
+ case 'End':
86
+ ev.preventDefault();
87
+ this._handleFocusOnInputWithCaretEnd();
88
+ break;
89
+ case 'Home':
90
+ ev.preventDefault();
91
+ this._handleFocusOnInputWithCaretStart();
92
+ break;
93
+ case 'Backspace':
94
+ this._handleMoveToInputField();
61
95
  break;
62
96
  case 'Tab':
63
- const isFocusedOnSearchInput = !!((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.matches('input[type="search"]'));
64
- if (!isFocusedOnSearchInput) {
65
- const searchBar = this.querySelector(`.${search_constants.SEARCH_CLASS_NAMES.searchBar}`);
66
- searchBar === null || searchBar === void 0 ? void 0 : searchBar.classList.remove(search_constants.SEARCH_CLASS_NAMES.outline);
67
- this._resetSearchView();
68
- document.removeEventListener('keyup', this._bindKeys);
69
- }
97
+ const isFocusedOnSearchInput = document.activeElement === this._inputField;
98
+ if (!isFocusedOnSearchInput)
99
+ ev.preventDefault();
100
+ break;
101
+ default:
102
+ const isAWriteableCharacter = ev.key.length === 1;
103
+ if (isAWriteableCharacter)
104
+ this._handleWriteableCharacter(ev);
70
105
  break;
71
106
  }
72
107
  };
73
- this._focusOutsideActiveItemsForward = () => {
108
+ this._handleSearchTabNavigation = (ev) => {
109
+ if (ev.key !== 'Tab')
110
+ return;
111
+ const isFocusedOnSearchInput = document.activeElement === this._inputField;
112
+ if (ev.shiftKey && !isFocusedOnSearchInput) {
113
+ this._focusOnPreviousElementBeforeSearchInput(ev);
114
+ return;
115
+ }
116
+ if (!isFocusedOnSearchInput) {
117
+ const searchBar = this.querySelector(`.${search_constants.SEARCH_CLASS_NAMES.searchBar}`);
118
+ searchBar === null || searchBar === void 0 ? void 0 : searchBar.classList.remove(search_constants.SEARCH_CLASS_NAMES.outline);
119
+ this._resetSearchView();
120
+ this._removeSearchKeyboardNavigation();
121
+ this._focusOnNextElementAfterSearchInput(ev);
122
+ }
123
+ };
124
+ this._focusOnPreviousElementBeforeSearchInput = async (ev) => {
125
+ ev.preventDefault();
126
+ const searchBar = this.querySelector(`.${search_constants.SEARCH_CLASS_NAMES.searchBar}`);
127
+ searchBar === null || searchBar === void 0 ? void 0 : searchBar.classList.remove(search_constants.SEARCH_CLASS_NAMES.outline);
128
+ this._resetSearchView();
129
+ this._removeSearchKeyboardNavigation();
130
+ utilities.UiDomUtils.getPreviousFocusableElement(this._inputField).focus();
131
+ };
132
+ this._focusOnNextElementAfterSearchInput = async (ev) => {
133
+ ev.preventDefault();
134
+ utilities.UiDomUtils.getNextFocusableElement(this._inputField).focus();
135
+ };
136
+ this._preventScrollingOnSearchContentBrowsing = (ev) => {
74
137
  var _a;
75
- const $activeElement = document.activeElement;
76
- const $searchItemsContainer = this._searchHistoryRef.value || this._searchResultsRef.value;
138
+ const hasArrowBeenPressed = ev.key === "ArrowUp" || ev.key === "ArrowDown";
139
+ const hasHomeOrEndBeenPressed = ev.key === "Home" || ev.key === "End";
140
+ const hasSearchContainerParent = !!((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest('.search__container'));
141
+ if ((hasArrowBeenPressed || hasHomeOrEndBeenPressed) && hasSearchContainerParent) {
142
+ ev.preventDefault();
143
+ }
144
+ };
145
+ this._handleForwardListFocus = () => {
146
+ var _a, _b;
147
+ const $searchItemsContainer = this._findSearchItemsContainer();
77
148
  if (!$searchItemsContainer)
78
149
  return;
79
- const $searchItems = utilities.UiDomUtils.getFocusableElements($searchItemsContainer).filter(($el) => {
150
+ const isActiveElementASearchItem = !!((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.getAttribute('data-search-item-id'));
151
+ const isActiveElementAGridSearchItem = isActiveElementASearchItem && !!((_b = document.activeElement) === null || _b === void 0 ? void 0 : _b.getAttribute('data-search-grid-item'));
152
+ const $listSearchItems = this._findListSearchItems($searchItemsContainer, isActiveElementAGridSearchItem);
153
+ this._handleForwardFocus($listSearchItems);
154
+ };
155
+ this._handleForwardGridFocus = () => {
156
+ const $searchItemsContainer = this._findSearchItemsContainer();
157
+ if (!$searchItemsContainer)
158
+ return;
159
+ const $gridSearchItems = utilities.UiDomUtils.getFocusableElements($searchItemsContainer).filter(($el) => {
80
160
  return !!$el.getAttribute('data-search-item-id');
81
161
  });
162
+ this._handleForwardFocus($gridSearchItems);
163
+ };
164
+ this._handleForwardFocus = ($searchItems) => {
165
+ var _a;
166
+ const $activeElement = document.activeElement;
82
167
  const indexOfCurrentElement = $searchItems.indexOf($activeElement);
83
168
  const indexOfNextElement = indexOfCurrentElement === $searchItems.length - 1 ? 0 : indexOfCurrentElement + 1;
84
169
  const $nextSearchItemElement = $searchItems[indexOfNextElement];
85
170
  $nextSearchItemElement.focus();
86
- this._activeItemId = (_a = Number($nextSearchItemElement.getAttribute('data-search-item-id'))) !== null && _a !== void 0 ? _a : -1;
171
+ this._setActiveItemId((_a = $nextSearchItemElement.getAttribute('data-search-item-id')) !== null && _a !== void 0 ? _a : `${this._id}-1`);
87
172
  };
88
- this._focusOutsideActiveItemsBackward = () => {
89
- var _a;
90
- const $activeElement = document.activeElement;
91
- const $searchItemsContainer = this._searchHistoryRef.value || this._searchResultsRef.value;
173
+ this._handleMoveToInputField = () => {
174
+ const isFocusedOnSearchInput = document.activeElement === this._inputField;
175
+ if (isFocusedOnSearchInput)
176
+ return;
177
+ this._inputField.focus();
178
+ };
179
+ this._handleBackwardListFocus = (ev) => {
180
+ var _a, _b;
181
+ const isFocusedOnSearchInput = document.activeElement === this._inputField;
182
+ const hasPopup = this._shouldShowHistory || this._shouldShowHistory || this._shouldShowResults;
183
+ if (isFocusedOnSearchInput || !hasPopup)
184
+ return;
185
+ ev.preventDefault();
186
+ const $searchItemsContainer = this._findSearchItemsContainer();
187
+ if (!$searchItemsContainer)
188
+ return;
189
+ const isActiveElementASearchItem = !!((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.getAttribute('data-search-item-id'));
190
+ const isActiveElementAGridSearchItem = isActiveElementASearchItem && !!((_b = document.activeElement) === null || _b === void 0 ? void 0 : _b.getAttribute('data-search-grid-item'));
191
+ const $listSearchItems = this._findListSearchItems($searchItemsContainer, isActiveElementAGridSearchItem);
192
+ this._handleBackwardFocus($listSearchItems);
193
+ };
194
+ this._findListSearchItems = ($searchItemsContainer, shouldFindGridList) => {
195
+ return utilities.UiDomUtils.getFocusableElements($searchItemsContainer).filter(($el) => {
196
+ const searchItemId = $el.getAttribute('data-search-item-id');
197
+ const isListSearchItem = !!searchItemId && !$el.getAttribute('data-search-grid-item');
198
+ const isGridSearchItem = !!searchItemId && $el.getAttribute('data-search-grid-item');
199
+ return shouldFindGridList ? isGridSearchItem : isListSearchItem;
200
+ });
201
+ };
202
+ this._handleBackwardGridFocus = () => {
203
+ const $searchItemsContainer = this._findSearchItemsContainer();
92
204
  if (!$searchItemsContainer)
93
205
  return;
94
- const $searchItems = utilities.UiDomUtils.getFocusableElements($searchItemsContainer).filter(($el) => {
206
+ const $gridSearchItems = utilities.UiDomUtils.getFocusableElements($searchItemsContainer).filter(($el) => {
95
207
  return !!$el.getAttribute('data-search-item-id');
96
208
  });
209
+ this._handleBackwardFocus($gridSearchItems);
210
+ };
211
+ this._findSearchItemsContainer = () => {
212
+ const containers = [
213
+ this._searchHistoryRef.value,
214
+ this._searchResultsRef.value,
215
+ this._searchMessageRef.value
216
+ ];
217
+ return containers.find(container => container && !utilities.UiDomUtils.isElementEmpty(container));
218
+ };
219
+ this._handleBackwardFocus = ($searchItems) => {
220
+ var _a;
221
+ const $activeElement = document.activeElement;
97
222
  const indexOfCurrentElement = $searchItems.indexOf($activeElement);
98
223
  const indexOfPreviousElement = indexOfCurrentElement === 0 ? $searchItems.length - 1 : indexOfCurrentElement - 1;
99
224
  const $previousSearchItemElement = $searchItems[indexOfPreviousElement];
100
225
  $previousSearchItemElement.focus();
101
- this._activeItemId = (_a = Number($previousSearchItemElement.getAttribute('data-search-item-id'))) !== null && _a !== void 0 ? _a : -1;
226
+ this._setActiveItemId((_a = $previousSearchItemElement.getAttribute('data-search-item-id')) !== null && _a !== void 0 ? _a : `${this._id}-1`);
102
227
  };
103
- this._getSearchItemsCount = () => {
104
- if (this._shouldShowHistory)
105
- return this._historyLimitedContent.length;
106
- let searchItemsCount = this._searchResults.products.length +
107
- this._searchResults.categories.length +
108
- this._searchResults.suggestions.length +
109
- this._searchResults.producers.length;
110
- if (this._searchResults.products.length && this._searchResults.suggestions.length) {
111
- searchItemsCount += 1;
228
+ this._setActiveItemId = (newActiveItemId) => {
229
+ this._activeItemId = newActiveItemId;
230
+ if (document.activeElement !== this._inputField) {
231
+ this._inputField.setAttribute('aria-activedescendant', this._activeItemId);
232
+ }
233
+ };
234
+ this._removeSearchKeyboardNavigation = () => {
235
+ document.removeEventListener('keydown', this._bindKeys);
236
+ document.removeEventListener('keyup', this._handleSearchTabNavigation);
237
+ };
238
+ this._handleFocusOnInputWithCaretEnd = () => {
239
+ const isFocusedOnSearchInput = document.activeElement === this._inputField;
240
+ if (isFocusedOnSearchInput)
241
+ return;
242
+ this._inputField.focus();
243
+ const endPosition = this._inputField.value.length;
244
+ this._inputField.setSelectionRange(endPosition, endPosition);
245
+ };
246
+ this._handleFocusOnInputWithCaretStart = () => {
247
+ this._inputField.focus();
248
+ this._inputField.setSelectionRange(0, 0);
249
+ };
250
+ this._handleWriteableCharacter = (ev) => {
251
+ const isFocusedOnSearchInput = document.activeElement === this._inputField;
252
+ if (isFocusedOnSearchInput)
253
+ return;
254
+ this._inputField.focus();
255
+ const isAPrintableCharacter = ev.key.match(/\P{C}/u);
256
+ if (ev.key.length !== 1 || !isAPrintableCharacter) {
257
+ ev.preventDefault();
112
258
  }
113
- return searchItemsCount;
114
259
  };
115
260
  this._hideSuggesterOnClickOutside = (ev) => {
116
261
  const outsideClick = typeof ev.composedPath === 'function' && !ev.composedPath().includes(this);
@@ -125,6 +270,12 @@ exports.HSearch = class HSearch extends phoenix_light_lit_element.PhoenixLightLi
125
270
  ? this.classList.remove(search_constants.SEARCH_CLASS_NAMES.mobileOpened)
126
271
  : this.classList.add(search_constants.SEARCH_CLASS_NAMES.mobileOpened);
127
272
  };
273
+ this._preventSubmitOnSearchClear = (ev) => {
274
+ const $searchClear = this.querySelector(search_constants.SEARCH_COMPONENT_NAMES.clearButton);
275
+ if (ev.key === 'Enter' && ev.target === $searchClear) {
276
+ ev.preventDefault();
277
+ }
278
+ };
128
279
  }
129
280
  async connectedCallback() {
130
281
  super.connectedCallback();
@@ -163,7 +314,9 @@ exports.HSearch = class HSearch extends phoenix_light_lit_element.PhoenixLightLi
163
314
  disconnectedCallback() {
164
315
  super.disconnectedCallback();
165
316
  document.removeEventListener('click', this._hideSuggesterOnClickOutside);
317
+ document.removeEventListener('keydown', this._preventScrollingOnSearchContentBrowsing);
166
318
  window.removeEventListener('resize', this._switchTypeOfSearchView);
319
+ this._searchForm.removeEventListener('keydown', this._preventSubmitOnSearchClear);
167
320
  }
168
321
  _setupContext() {
169
322
  this._historyContextProvider = new context_provider_controller.ContextProviderController(this);
@@ -172,8 +325,11 @@ exports.HSearch = class HSearch extends phoenix_light_lit_element.PhoenixLightLi
172
325
  _setupInitialSearchPhrase() {
173
326
  var _a;
174
327
  const searchInput = this.querySelector('input[type="search"]');
328
+ const searchForm = this.closest('form');
175
329
  if (searchInput)
176
330
  this._inputField = searchInput;
331
+ if (searchForm)
332
+ this._searchForm = searchForm;
177
333
  if (!((_a = this._inputField) === null || _a === void 0 ? void 0 : _a.value))
178
334
  return;
179
335
  this._searchPhrase = this._inputField.value;
@@ -192,11 +348,17 @@ exports.HSearch = class HSearch extends phoenix_light_lit_element.PhoenixLightLi
192
348
  }
193
349
  _setupListeners() {
194
350
  this.addEventListener(search_constants.SEARCH_CUSTOM_EVENT_NAMES.focusin, (ev) => {
351
+ var _a, _b, _c;
352
+ const $target = (_a = ev.detail) === null || _a === void 0 ? void 0 : _a.relatedTarget;
353
+ if ($target === null || $target === void 0 ? void 0 : $target.closest(`[id="${this._searchContentContainerId}"]`))
354
+ return;
195
355
  const searchBar = this.querySelector(`.${search_constants.SEARCH_CLASS_NAMES.searchBar}`);
196
356
  searchBar === null || searchBar === void 0 ? void 0 : searchBar.classList.add(search_constants.SEARCH_CLASS_NAMES.outline);
197
- const shouldShowMessage = ev.detail.searchPhrase !== '';
198
- this._updateSearchView(ev.detail.searchPhrase, shouldShowMessage, false);
199
- document.addEventListener('keyup', this._bindKeys);
357
+ const shouldShowMessage = ((_b = ev.detail) === null || _b === void 0 ? void 0 : _b.searchPhrase) !== '';
358
+ this._updateSearchView(((_c = ev.detail) === null || _c === void 0 ? void 0 : _c.searchPhrase) || '', shouldShowMessage, false);
359
+ document.addEventListener('keydown', this._bindKeys);
360
+ document.addEventListener('keyup', this._handleSearchTabNavigation);
361
+ document.addEventListener('keydown', this._preventScrollingOnSearchContentBrowsing);
200
362
  });
201
363
  this.addEventListener(search_constants.SEARCH_CUSTOM_EVENT_NAMES.keyup, (ev) => {
202
364
  const shouldShowMessage = ev.detail.searchPhrase !== '';
@@ -207,7 +369,7 @@ exports.HSearch = class HSearch extends phoenix_light_lit_element.PhoenixLightLi
207
369
  this._updateSearchView('', false);
208
370
  });
209
371
  this.addEventListener(search_constants.SEARCH_CUSTOM_EVENT_NAMES.submit, () => {
210
- if (this._activeItemId !== -1)
372
+ if (this._activeItemId !== `${this._id}-1`)
211
373
  return;
212
374
  if (this._inputField.value === '') {
213
375
  this._updateSearchView(this._inputField.value, true);
@@ -231,10 +393,12 @@ exports.HSearch = class HSearch extends phoenix_light_lit_element.PhoenixLightLi
231
393
  });
232
394
  document.addEventListener('click', this._hideSuggesterOnClickOutside);
233
395
  window.addEventListener('resize', this._switchTypeOfSearchView);
396
+ this._searchForm.addEventListener('keydown', this._preventSubmitOnSearchClear);
234
397
  }
235
398
  _updateSearchView(searchPhrase, shouldShowMessage, shouldUpdateSearchPhrase = true) {
236
399
  this._shouldShowMessage = shouldShowMessage;
237
- this._activeItemId = -1;
400
+ this._setActiveItemId(`${this._id}-1`);
401
+ this._inputField.setAttribute('aria-activedescendant', '');
238
402
  this._displaySuggester(searchPhrase);
239
403
  if (!shouldUpdateSearchPhrase)
240
404
  return;
@@ -272,57 +436,58 @@ exports.HSearch = class HSearch extends phoenix_light_lit_element.PhoenixLightLi
272
436
  _handleToggleHistoryAndResults({ shouldShowHistory, shouldShowResults }) {
273
437
  this._shouldShowHistory = shouldShowHistory;
274
438
  this._shouldShowResults = shouldShowResults;
275
- this._toggleSearchInputAria(shouldShowHistory, shouldShowResults);
439
+ this._toggleSearchInputAttributes(shouldShowHistory, shouldShowResults);
440
+ this._toggleSearchContainerAttributes(shouldShowHistory, shouldShowResults);
276
441
  }
277
- _toggleSearchInputAria(shouldShowHistory, shouldShowResults) {
442
+ _toggleSearchInputAttributes(shouldShowHistory, shouldShowResults) {
278
443
  var _a;
279
444
  const $input = (_a = this._searchInput) === null || _a === void 0 ? void 0 : _a.input;
280
445
  if (!$input)
281
446
  return;
282
447
  if (!shouldShowHistory && !shouldShowResults) {
283
448
  $input.removeAttribute('aria-label');
449
+ $input.setAttribute('aria-activedescendant', '');
284
450
  return;
285
451
  }
286
452
  $input.setAttribute('aria-expanded', 'true');
287
- if (shouldShowHistory)
453
+ if (shouldShowHistory) {
288
454
  $input.setAttribute('aria-label', this.settings.historyGuideAriaLabel);
289
- if (shouldShowResults)
290
- $input.setAttribute('aria-label', this.settings.suggesterGuideAriaLabel);
291
- }
292
- _scroll(direction) {
293
- const searchContainer = this.querySelector(`.${search_constants.SEARCH_CLASS_NAMES.container}`);
294
- const maxScrollTop = searchContainer.scrollHeight - searchContainer.clientHeight;
295
- const activeItem = this.querySelector(`[data-search-item-id="${this._activeItemId}"]`);
296
- const activeItemHeight = (activeItem === null || activeItem === void 0 ? void 0 : activeItem.getBoundingClientRect().height) || 0;
297
- let top;
298
- if (direction === search_constants.SCROLL_DIRECTIONS.up) {
299
- top = searchContainer.scrollTop == 0 ? 0 : searchContainer.scrollTop + 30 - activeItemHeight;
455
+ $input.setAttribute('aria-haspopup', 'grid');
300
456
  }
301
- else {
302
- top = searchContainer.scrollTop == maxScrollTop ? maxScrollTop : activeItemHeight + searchContainer.scrollTop - 30;
457
+ if (shouldShowResults) {
458
+ $input.setAttribute('aria-label', this.settings.suggesterGuideAriaLabel);
459
+ this._inputField.removeAttribute('aria-haspopup');
303
460
  }
304
- if (this._activeItemId === this._getSearchItemsCount() - 1) {
305
- top = maxScrollTop;
461
+ }
462
+ _toggleSearchContainerAttributes(shouldShowHistory, shouldShowResults) {
463
+ if (shouldShowHistory) {
464
+ this._containerRole = 'grid';
306
465
  }
307
- if (this._activeItemId === 0) {
308
- top = 0;
466
+ if (shouldShowResults) {
467
+ this._containerRole = 'listbox';
309
468
  }
310
- searchContainer === null || searchContainer === void 0 ? void 0 : searchContainer.scrollTo({ top, behavior: 'smooth' });
311
469
  }
312
470
  _handleChooseSearchItem() {
313
- const activeSearchItem = this.querySelector(`[data-search-item-id="${this._activeItemId}"]`);
314
- const elementToClick = activeSearchItem.dataset.suggestedValue
315
- ? activeSearchItem
316
- : activeSearchItem.querySelector('a');
317
- elementToClick.click();
471
+ const $activeSearchItem = this.querySelector(`[data-search-item-id="${this._activeItemId}"]`);
472
+ if (!$activeSearchItem)
473
+ return;
474
+ const $linkElement = $activeSearchItem.querySelector('a');
475
+ const $suggestedElement = $linkElement || $activeSearchItem;
476
+ const $elementToClick = $activeSearchItem.dataset.suggestedValue ? $suggestedElement : $linkElement;
477
+ if (!$elementToClick) {
478
+ $activeSearchItem.click();
479
+ }
480
+ else {
481
+ $elementToClick.click();
482
+ }
318
483
  }
319
484
  _resetSearchView() {
320
485
  this._shouldShowMessage = false;
321
- this._activeItemId = -1;
486
+ this._setActiveItemId(`${this._id}-1`);
322
487
  const searchBar = this.querySelector(`.${search_constants.SEARCH_CLASS_NAMES.searchBar}`);
323
488
  searchBar === null || searchBar === void 0 ? void 0 : searchBar.classList.remove(search_constants.SEARCH_CLASS_NAMES.outline);
324
489
  this._hideHistorySuggestionsAndResults();
325
- document.removeEventListener('keyup', this._bindKeys);
490
+ this._removeSearchKeyboardNavigation();
326
491
  }
327
492
  _submitSearchPhrase(searchPhrase) {
328
493
  this._dispatchEventWithSearchPhrase(search_constants.SEARCH_CUSTOM_EVENT_NAMES.searchPhraseSubmitted, searchPhrase);
@@ -357,33 +522,48 @@ exports.HSearch = class HSearch extends phoenix_light_lit_element.PhoenixLightLi
357
522
  <div class="labeled-icon__signature">${this._translations.search}</div>
358
523
  </div>
359
524
 
360
- ${when.when(this._isSuggesterLayerVisible(), () => lit.html `<div class="${search_constants.SEARCH_CLASS_NAMES.container}">
361
- ${when.when(this._shouldShowMessage, () => lit.html `<h-search-message
362
- .history="${this._historyLimitedContent}"
363
- .results="${this._searchResults}"
364
- .translations="${this._translations}"
365
- search-phrase="${this._searchPhrase}"
366
- module-instance-id="${this.moduleInstanceId}"
367
- ></h-search-message>`)}
368
- ${when.when(this._shouldShowHistory, () => lit.html `<h-search-history
369
- ${ref_js.ref(this._searchHistoryRef)}
525
+ ${when.when(this._isSuggesterLayerVisible(), () => lit.html `
526
+ <div
527
+ class="${search_constants.SEARCH_CLASS_NAMES.container}"
528
+ id="${this._searchContentContainerId}"
529
+ role="${this._containerRole}"
530
+ >
531
+ ${when.when(this._shouldShowMessage, () => lit.html `<h-search-message
532
+ ${ref_js.ref(this._searchMessageRef)}
370
533
  .history="${this._historyLimitedContent}"
371
- .translations="${this._translations}"
372
- active-item-id="${this._activeItemId}"
373
- module-instance-id="${this.moduleInstanceId}"
374
- ></h-search-history>`)}
375
- ${when.when(this._shouldShowResults, () => lit.html `<h-search-results
376
- ${ref_js.ref(this._searchResultsRef)}
377
534
  .results="${this._searchResults}"
378
- search-phrase="${this._searchPhrase}"
379
- .settings="${this.settings}"
380
- locale="${this.locale}"
381
- view="${this.view}"
382
535
  .translations="${this._translations}"
383
- active-item-id="${this._activeItemId}"
536
+ search-phrase="${this._searchPhrase}"
384
537
  module-instance-id="${this.moduleInstanceId}"
385
- ></h-search-results>`)}
386
- </div>`)}
538
+ ></h-search-message>`)}
539
+ ${when.when(this._shouldShowHistory, () => lit.html `<h-search-history
540
+ ${ref_js.ref(this._searchHistoryRef)}
541
+ .history="${this._historyLimitedContent}"
542
+ .translations="${this._translations}"
543
+ active-item-id="${this._activeItemId}"
544
+ search-id="${this._id}"
545
+ module-instance-id="${this.moduleInstanceId}"
546
+ ></h-search-history>`)}
547
+ ${when.when(this._shouldShowResults, () => lit.html `<h-search-results
548
+ ${ref_js.ref(this._searchResultsRef)}
549
+ .results="${this._searchResults}"
550
+ search-phrase="${this._searchPhrase}"
551
+ .settings="${this.settings}"
552
+ locale="${this.locale}"
553
+ view="${this.view}"
554
+ .translations="${this._translations}"
555
+ active-item-id="${this._activeItemId}"
556
+ search-id="${this._id}"
557
+ module-instance-id="${this.moduleInstanceId}"
558
+ ></h-search-results>`)}
559
+ </div>
560
+ `, () => lit.html `
561
+ <div
562
+ class="${search_constants.SEARCH_CLASS_NAMES.container}"
563
+ id="${this._searchContentContainerId}"
564
+ role="${this._containerRole}"
565
+ hidden
566
+ ></div>`)}
387
567
  `;
388
568
  }
389
569
  };
@@ -437,12 +617,16 @@ tslib_es6.__decorate([
437
617
  ], exports.HSearch.prototype, "_historyContext", void 0);
438
618
  tslib_es6.__decorate([
439
619
  decorators.state(),
440
- tslib_es6.__metadata("design:type", Number)
620
+ tslib_es6.__metadata("design:type", String)
441
621
  ], exports.HSearch.prototype, "_activeItemId", void 0);
442
622
  tslib_es6.__decorate([
443
623
  decorators.state(),
444
624
  tslib_es6.__metadata("design:type", Object)
445
625
  ], exports.HSearch.prototype, "_translations", void 0);
626
+ tslib_es6.__decorate([
627
+ decorators.state(),
628
+ tslib_es6.__metadata("design:type", String)
629
+ ], exports.HSearch.prototype, "_containerRole", void 0);
446
630
  exports.HSearch = tslib_es6.__decorate([
447
631
  phoenix_custom_element.phoenixCustomElement(search_constants.SEARCH_COMPONENT_NAMES.search)
448
632
  ], exports.HSearch);
@@ -1 +1 @@
1
- {"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA,wBAAwB,+CAAmD;AAC3E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,qEAA6E;AAChG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
1
+ {"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA,wBAAwB,+CAAmD;AAC3E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,wDAA4D;AAC7E,mBAAmB,qEAA6E;AAChG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
@@ -36,6 +36,11 @@ exports.HSearchClear = class HSearchClear extends phoenix_light_lit_element.Phoe
36
36
  this.addEventListener('click', this._dispatchClearEvent);
37
37
  document.addEventListener(search_constants.SEARCH_CUSTOM_EVENT_NAMES.keyup, this._handleClearButtonOnPhraseEnter);
38
38
  }
39
+ updated(_changedProperties) {
40
+ super.updated(_changedProperties);
41
+ const newTabIndex = this._shouldShow ? '0' : '-1';
42
+ this.setAttribute('tabindex', newTabIndex);
43
+ }
39
44
  async _searchContextSetup() {
40
45
  try {
41
46
  this._searchContextConsumer = new context_consumer_controller.ContextConsumerController(this);
@@ -1 +1 @@
1
- {"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA,wBAAwB,qDAAyD;AACjF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,2EAAmF;AACtG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}
1
+ {"version":3,"file":null,"sources":[null],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA,wBAAwB,qDAAyD;AACjF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,2EAAmF;AACtG;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;"}