@iamproperty/components 7.8.2--beta3 → 7.8.2--beta5

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 (235) hide show
  1. package/assets/css/components/actionbar.component.css +1 -1
  2. package/assets/css/components/actionbar.component.css.map +1 -1
  3. package/assets/css/components/address-lookup.component.css +1 -1
  4. package/assets/css/components/address-lookup.component.css.map +1 -1
  5. package/assets/css/components/advanced-select.component.css +1 -1
  6. package/assets/css/components/advanced-select.component.css.map +1 -1
  7. package/assets/css/components/banner.preload.css +1 -0
  8. package/assets/css/components/banner.preload.css.map +1 -0
  9. package/assets/css/components/calendar.component.css +1 -1
  10. package/assets/css/components/calendar.component.css.map +1 -1
  11. package/assets/css/components/card.component.css +1 -1
  12. package/assets/css/components/card.component.css.map +1 -1
  13. package/assets/css/components/card.module.css +1 -1
  14. package/assets/css/components/card.module.css.map +1 -1
  15. package/assets/css/components/card.preload.css +1 -0
  16. package/assets/css/components/card.preload.css.map +1 -0
  17. package/assets/css/components/carousel.component.css +1 -1
  18. package/assets/css/components/carousel.component.css.map +1 -1
  19. package/assets/css/components/carousel.config.css +1 -1
  20. package/assets/css/components/carousel.config.css.map +1 -1
  21. package/assets/css/components/config.component.css +1 -1
  22. package/assets/css/components/config.component.css.map +1 -1
  23. package/assets/css/components/content.component.css +1 -1
  24. package/assets/css/components/content.component.css.map +1 -1
  25. package/assets/css/components/fileupload.css +1 -1
  26. package/assets/css/components/fileupload.css.map +1 -1
  27. package/assets/css/components/filter-card.component.css +1 -1
  28. package/assets/css/components/filter-card.component.css.map +1 -1
  29. package/assets/css/components/modal.component.css +1 -1
  30. package/assets/css/components/modal.component.css.map +1 -1
  31. package/assets/css/components/multi-step-modal.component.css +1 -1
  32. package/assets/css/components/multi-step-modal.component.css.map +1 -1
  33. package/assets/css/components/multiselect.css +1 -1
  34. package/assets/css/components/multiselect.css.map +1 -1
  35. package/assets/css/components/nav.component.css +1 -1
  36. package/assets/css/components/nav.component.css.map +1 -1
  37. package/assets/css/components/nav.global.css +1 -1
  38. package/assets/css/components/nav.global.css.map +1 -1
  39. package/assets/css/components/notification.global.css +1 -1
  40. package/assets/css/components/notification.global.css.map +1 -1
  41. package/assets/css/components/pagination.css +1 -1
  42. package/assets/css/components/pagination.css.map +1 -1
  43. package/assets/css/components/record-card.component.css +1 -1
  44. package/assets/css/components/record-card.component.css.map +1 -1
  45. package/assets/css/components/search.component.css +1 -1
  46. package/assets/css/components/search.component.css.map +1 -1
  47. package/assets/css/components/skeleton.global.css +1 -1
  48. package/assets/css/components/skeleton.global.css.map +1 -1
  49. package/assets/css/components/slider.css +1 -1
  50. package/assets/css/components/slider.css.map +1 -1
  51. package/assets/css/components/split-button.component.css +1 -1
  52. package/assets/css/components/split-button.component.css.map +1 -1
  53. package/assets/css/components/std-nav-standalone.component.css +1 -1
  54. package/assets/css/components/std-nav-standalone.component.css.map +1 -1
  55. package/assets/css/components/tabs.component.css +1 -1
  56. package/assets/css/components/tabs.component.css.map +1 -1
  57. package/assets/css/components/tag.component.css +1 -1
  58. package/assets/css/components/tag.component.css.map +1 -1
  59. package/assets/css/components/video-card.component.css +1 -1
  60. package/assets/css/components/video-card.component.css.map +1 -1
  61. package/assets/css/components/video-modal.component.css +1 -1
  62. package/assets/css/components/video-modal.component.css.map +1 -1
  63. package/assets/css/core.min.css +1 -1
  64. package/assets/css/core.min.css.map +1 -1
  65. package/assets/css/elements/dialog.css +1 -1
  66. package/assets/css/elements/dialog.css.map +1 -1
  67. package/assets/css/elements/dropdown.css +1 -1
  68. package/assets/css/elements/dropdown.css.map +1 -1
  69. package/assets/css/elements/forms.css +1 -1
  70. package/assets/css/elements/forms.css.map +1 -1
  71. package/assets/css/elements/links--global.css +1 -1
  72. package/assets/css/elements/links--global.css.map +1 -1
  73. package/assets/css/elements/links.css +1 -1
  74. package/assets/css/elements/links.css.map +1 -1
  75. package/assets/css/style.min.css +1 -1
  76. package/assets/css/style.min.css.map +1 -1
  77. package/assets/js/components/accordion/accordion.component.min.js +1 -1
  78. package/assets/js/components/actionbar/actionbar.component.min.js +3 -3
  79. package/assets/js/components/address-lookup/address-lookup.component.min.js +4 -4
  80. package/assets/js/components/address-lookup/address-lookup.component.min.js.map +1 -1
  81. package/assets/js/components/advanced-select/advanced-select.component.min.js +2 -2
  82. package/assets/js/components/applied-filters/applied-filters.component.min.js +1 -1
  83. package/assets/js/components/banner/banner.component.min.js +1 -1
  84. package/assets/js/components/barchart/barchart.component.min.js +1 -1
  85. package/assets/js/components/bento-grid/bento-grid.component.min.js +1 -1
  86. package/assets/js/components/bone/bone.component.min.js +1 -1
  87. package/assets/js/components/button/button.component.min.js +1 -1
  88. package/assets/js/components/calendar/calendar.component.min.js +2 -2
  89. package/assets/js/components/card/card.component.js +114 -125
  90. package/assets/js/components/card/card.component.min.js +7 -7
  91. package/assets/js/components/card/card.component.min.js.map +1 -1
  92. package/assets/js/components/carousel/carousel.component.js +83 -29
  93. package/assets/js/components/carousel/carousel.component.min.js +16 -11
  94. package/assets/js/components/carousel/carousel.component.min.js.map +1 -1
  95. package/assets/js/components/collapsible-side/collapsible-side.component.min.js +1 -1
  96. package/assets/js/components/config/config.component.min.js +7 -7
  97. package/assets/js/components/config/config.component.min.js.map +1 -1
  98. package/assets/js/components/content/content.component.js +28 -69
  99. package/assets/js/components/content/content.component.min.js +4 -4
  100. package/assets/js/components/content/content.component.min.js.map +1 -1
  101. package/assets/js/components/darkmode/darkmode.component.min.js +1 -1
  102. package/assets/js/components/doughnutchart/doughnutchart.component.min.js +1 -1
  103. package/assets/js/components/fileupload/fileupload.component.min.js +2 -2
  104. package/assets/js/components/filter-card/filter-card.component.min.js +5 -5
  105. package/assets/js/components/filter-card/filter-card.component.min.js.map +1 -1
  106. package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
  107. package/assets/js/components/form/form.component.js +42 -151
  108. package/assets/js/components/form/form.component.min.js +3 -3
  109. package/assets/js/components/form/form.component.min.js.map +1 -1
  110. package/assets/js/components/header/header.component.min.js +1 -1
  111. package/assets/js/components/inline-edit/inline-edit.component.min.js +1 -1
  112. package/assets/js/components/input/input.component.min.js +1 -1
  113. package/assets/js/components/input-range/input-range.component.min.js +1 -1
  114. package/assets/js/components/marketing/marketing.component.min.js +1 -1
  115. package/assets/js/components/menu/menu.component.min.js +1 -1
  116. package/assets/js/components/milestone/milestone.component.min.js +1 -1
  117. package/assets/js/components/milestone-group/milestone-group.component.min.js +1 -1
  118. package/assets/js/components/modal/modal.component.js +16 -11
  119. package/assets/js/components/modal/modal.component.min.js +7 -7
  120. package/assets/js/components/modal/modal.component.min.js.map +1 -1
  121. package/assets/js/components/multi-step/multi-step.component.min.js +1 -1
  122. package/assets/js/components/multi-step-modal/multi-step-modal.component.min.js +4 -4
  123. package/assets/js/components/multiselect/multiselect.component.min.js +4 -4
  124. package/assets/js/components/multiselect/multiselect.component.min.js.map +1 -1
  125. package/assets/js/components/nav/nav.component.js +88 -79
  126. package/assets/js/components/nav/nav.component.min.js +8 -8
  127. package/assets/js/components/nav/nav.component.min.js.map +1 -1
  128. package/assets/js/components/notification/notification.component.min.js +2 -2
  129. package/assets/js/components/pagination/pagination.component.min.js +5 -5
  130. package/assets/js/components/password/password.component.min.js +1 -1
  131. package/assets/js/components/popover/popover.component.min.js +1 -1
  132. package/assets/js/components/rank/rank.component.min.js +1 -1
  133. package/assets/js/components/rankings/rankings.component.min.js +1 -1
  134. package/assets/js/components/rating/rating.component.min.js +1 -1
  135. package/assets/js/components/record-card/record-card.component.min.js +6 -6
  136. package/assets/js/components/record-card/record-card.component.min.js.map +1 -1
  137. package/assets/js/components/search/search.component.js +235 -186
  138. package/assets/js/components/search/search.component.min.js +12 -7
  139. package/assets/js/components/search/search.component.min.js.map +1 -1
  140. package/assets/js/components/skeleton/skeleton.component.min.js +1 -1
  141. package/assets/js/components/slider/slider.component.min.js +2 -2
  142. package/assets/js/components/split-button/split-button.component.min.js +2 -2
  143. package/assets/js/components/std-address-lookup/std-address-lookup.component.min.js +5 -5
  144. package/assets/js/components/std-address-lookup/std-address-lookup.component.min.js.map +1 -1
  145. package/assets/js/components/std-nav/std-nav.component.js +12 -9
  146. package/assets/js/components/std-nav/std-nav.component.min.js +12 -15
  147. package/assets/js/components/std-nav/std-nav.component.min.js.map +1 -1
  148. package/assets/js/components/std-nav-standalone/std-nav-standalone.component.min.js +5 -5
  149. package/assets/js/components/std-nav-standalone/std-nav-standalone.component.min.js.map +1 -1
  150. package/assets/js/components/table/table.component.min.js +1 -1
  151. package/assets/js/components/table-ajax/table-ajax.component.min.js +1 -1
  152. package/assets/js/components/table-basic/table-basic.component.min.js +1 -1
  153. package/assets/js/components/table-no-submit/table-no-submit.component.min.js +1 -1
  154. package/assets/js/components/table-submit/table-submit.component.min.js +1 -1
  155. package/assets/js/components/tabs/tabs.component.min.js +4 -4
  156. package/assets/js/components/tag/tag.component.min.js +3 -3
  157. package/assets/js/components/tag/tag.component.min.js.map +1 -1
  158. package/assets/js/components/tooltip/tooltip.component.min.js +1 -1
  159. package/assets/js/components/video/video.component.min.js +1 -1
  160. package/assets/js/components/video-card/video-card.component.min.js +9 -9
  161. package/assets/js/components/video-card/video-card.component.min.js.map +1 -1
  162. package/assets/js/components/video-modal/video-modal.component.min.js +5 -5
  163. package/assets/js/components/word-count/word-count.component.min.js +1 -1
  164. package/assets/js/modules/card.module.js +12 -11
  165. package/assets/js/modules/content.js +40 -8
  166. package/assets/js/modules/content.test.js +62 -12
  167. package/assets/js/modules/data-layer.js +7 -6
  168. package/assets/js/modules/dropdown.js +0 -1
  169. package/assets/js/modules/form.js +129 -0
  170. package/assets/js/modules/form.test.js +132 -0
  171. package/assets/js/modules/nav.js +10 -3
  172. package/assets/js/modules/search.js +153 -0
  173. package/assets/js/modules/search.test.js +125 -0
  174. package/assets/js/modules/tabs.test.js +64 -12
  175. package/assets/js/modules/test-dom.js +5 -0
  176. package/assets/js/modules/testimonial.test.js +44 -6
  177. package/assets/js/modules/videos.test.js +61 -13
  178. package/assets/js/scripts.bundle.js +3 -3
  179. package/assets/js/scripts.bundle.js.map +1 -1
  180. package/assets/js/scripts.bundle.min.js +2 -2
  181. package/assets/js/scripts.bundle.min.js.map +1 -1
  182. package/assets/sass/_components.scss +2 -63
  183. package/assets/sass/_utilities.scss +1 -0
  184. package/assets/sass/components/banner.preload.scss +26 -0
  185. package/assets/sass/components/card.component.scss +1 -7
  186. package/assets/sass/components/card.module.scss +6 -6
  187. package/assets/sass/components/card.preload.scss +80 -0
  188. package/assets/sass/components/carousel.component.scss +165 -0
  189. package/assets/sass/components/carousel.config.scss +90 -249
  190. package/assets/sass/components/content.component.scss +0 -7
  191. package/assets/sass/components/modal.component.scss +5 -1
  192. package/assets/sass/components/nav.component.scss +2 -1
  193. package/assets/sass/components/nav.global.scss +0 -10
  194. package/assets/sass/components/notification.global.scss +8 -0
  195. package/assets/sass/components/search.component.scss +89 -7
  196. package/assets/sass/components/skeleton.global.scss +4 -0
  197. package/assets/sass/elements/dialog.scss +43 -0
  198. package/assets/sass/elements/dropdown.css +2 -0
  199. package/assets/sass/elements/forms.scss +0 -27
  200. package/assets/sass/elements/links--global.scss +40 -2
  201. package/assets/sass/foundations/colours.scss +0 -24
  202. package/assets/sass/foundations/reboot.scss +4 -0
  203. package/assets/sass/foundations/root.scss +0 -1
  204. package/assets/sass/utilities/js-display.css +2 -3
  205. package/assets/sass/utilities/wordpress.css +7 -0
  206. package/assets/ts/components/card/card.component.ts +72 -62
  207. package/assets/ts/components/carousel/carousel.component.ts +84 -19
  208. package/assets/ts/components/content/content.component.ts +36 -100
  209. package/assets/ts/components/form/form.component.ts +54 -213
  210. package/assets/ts/components/modal/modal.component.ts +27 -19
  211. package/assets/ts/components/nav/nav.component.ts +107 -95
  212. package/assets/ts/components/search/search.component.ts +260 -184
  213. package/assets/ts/components/std-nav/std-nav.component.ts +20 -17
  214. package/assets/ts/html.d.ts +6 -0
  215. package/assets/ts/modules/card.module.ts +19 -11
  216. package/assets/ts/modules/content.test.ts +84 -12
  217. package/assets/ts/modules/content.ts +56 -9
  218. package/assets/ts/modules/data-layer.ts +7 -11
  219. package/assets/ts/modules/dropdown.ts +0 -2
  220. package/assets/ts/modules/form.test.ts +183 -0
  221. package/assets/ts/modules/form.ts +210 -0
  222. package/assets/ts/modules/nav.ts +12 -3
  223. package/assets/ts/modules/search.test.ts +142 -0
  224. package/assets/ts/modules/search.ts +206 -0
  225. package/assets/ts/modules/tabs.test.ts +79 -12
  226. package/assets/ts/modules/test-dom.ts +5 -0
  227. package/assets/ts/modules/testimonial.test.ts +45 -6
  228. package/assets/ts/modules/videos.test.ts +74 -14
  229. package/dist/components.es.js +25 -25
  230. package/dist/components.umd.js +170 -163
  231. package/package.json +1 -1
  232. package/assets/js/modules/carousel.js +0 -214
  233. package/assets/js/modules/carousel.test.js +0 -18
  234. package/assets/ts/modules/carousel.test.ts +0 -27
  235. package/assets/ts/modules/carousel.ts +0 -301
@@ -1,10 +1,18 @@
1
- import Cookies from '../../../../node_modules/js-cookie/dist/js.cookie.mjs';
2
- import { safeID, resolvePath, isTraversable } from '../../modules/helpers';
3
- import advancedSelect from '../../modules/advanced-select';
1
+ import search, { filterDatalist, datalistSelectOption } from '../../modules/search';
2
+
3
+ const getIntegerAttribute = (element: HTMLElement, attributeName: string, fallback: number): number => {
4
+ const value = Number.parseInt(element.getAttribute(attributeName) || '', 10);
5
+
6
+ return Number.isNaN(value) ? fallback : value;
7
+ };
8
+
9
+ const getOptionFromEvent = (event: Event): HTMLOptionElement | null =>
10
+ event.target instanceof HTMLElement ? event.target.closest<HTMLOptionElement>('option') : null;
4
11
 
5
12
  // Data layer Web component created
6
- window.dataLayer = window.dataLayer || [];
7
- window.dataLayer.push({
13
+ const searchWindow = window as WindowWithDataLayer;
14
+ searchWindow.dataLayer = searchWindow.dataLayer || [];
15
+ searchWindow.dataLayer.push({
8
16
  event: 'customElementRegistered',
9
17
  element: 'Search',
10
18
  });
@@ -12,246 +20,314 @@ window.dataLayer.push({
12
20
  class iamSearch extends HTMLElement {
13
21
  constructor() {
14
22
  super();
15
- this.attachShadow({ mode: 'open' });
23
+ const shadowRoot = this.attachShadow({ mode: 'open' });
16
24
 
17
- const assetLocation = document.body.hasAttribute('data-assets-location')
18
- ? document.body.getAttribute('data-assets-location')
19
- : '/assets';
25
+ const assetLocation = document.body.getAttribute('data-assets-location') || '/assets';
20
26
 
21
27
  const loadCSS = `@import "${assetLocation}/css/components/search.component.css";`;
22
28
 
23
29
  const template = document.createElement('template');
24
- template.innerHTML = `
30
+ template.innerHTML = /* HTML */ `
25
31
  <style>
26
32
  ${loadCSS}
27
33
  </style>
28
34
  <link rel="stylesheet" href="https://kit.fontawesome.com/8bd0fca975.css" crossorigin="anonymous" />
29
- <span class="wrapper"><span class="input__wrapper"><slot></slot></span><span class="suffix fa-regular fa-search"></span></span>
35
+ <span class="wrapper">
36
+ <span class="input__wrapper">
37
+ <slot></slot>
38
+ <button class="clear-search btn btn-action" type="button"><i class="fa-light fa-times me-0"></i></button>
39
+ </span>
40
+ <button class="suffix fa-regular fa-search"></button>
41
+ </span>
30
42
  <slot name="datalist"></slot>
31
43
  `;
32
- this.shadowRoot.appendChild(template.content.cloneNode(true));
44
+ shadowRoot.appendChild(template.content.cloneNode(true));
33
45
  }
34
46
 
35
- async connectedCallback(): void {
47
+ connectedCallback(): void {
48
+ const shadowRoot = this.shadowRoot;
49
+
50
+ if (!shadowRoot) return;
36
51
 
37
- // Make the datalist a dropdown
38
- this.classList.add('dropdown__wrapper');
52
+ let datalistElement = this.querySelector<HTMLDataListElement>('datalist');
53
+ const inputElement = this.querySelector<HTMLInputElement>('input');
54
+ const suffixElement = shadowRoot.querySelector<HTMLButtonElement>('.suffix');
55
+ const clearBtn = shadowRoot.querySelector<HTMLButtonElement>('.clear-search');
39
56
 
40
- if(this.querySelector('input.input--sm'))
41
- this.classList.add('hasInputSm');
57
+ let minLength = this.hasAttribute('data-min-length') ? getIntegerAttribute(this, 'data-min-length', 1) : 1;
42
58
 
43
-
44
- if(this.querySelector('label'))
45
- this.classList.add('has-label');
46
59
 
47
- // eslint-disable-next-line @typescript-eslint/no-this-alias
48
- const searchWrapper = this;
49
- const inputField = this.querySelector('input');
50
- const valueSchema = this.hasAttribute('data-value-schema') ? this.getAttribute('data-value-schema') : 'value';
51
- const displaySchema = this.hasAttribute('data-display-schema') ? this.getAttribute('data-display-schema') : 'label';
52
- const loopSchema = this.hasAttribute('data-schema') ? this.getAttribute('data-schema') : '';
53
- let datalist = this.querySelector('datalist');
54
- let minLength = this.hasAttribute('data-min-length') ? this.getAttribute('data-min-length') : 0;
60
+ suffixElement?.setAttribute('class',`suffix ${this.hasAttribute('data-icon') ? this.getAttribute('data-icon') : 'fa-regular fa-search'}`);
55
61
 
56
- if (searchWrapper.hasAttribute('data-url') && !this.hasAttribute('data-min-length')) {
62
+
63
+ if (this.hasAttribute('data-url') && !this.hasAttribute('data-min-length')) {
57
64
 
58
65
  minLength = 3;
59
66
  }
60
67
 
61
- // Clone original input field, re-name and use for display purposes
62
- const displayInputField = inputField.cloneNode();
63
- displayInputField.setAttribute('name', `${inputField.getAttribute('name')}Alt`);
64
- inputField.removeAttribute('data-change-events');
65
- displayInputField.removeAttribute('id');
68
+ if(!inputElement || !suffixElement) return;
69
+
70
+ // #region maintain the original placeholder value in a data attribute to allow for it to be reset when the field is emptied
71
+ const originalPlaceholder = inputElement.getAttribute('placeholder');
72
+
73
+ if(originalPlaceholder !== null)
74
+ this.setAttribute('data-original-placeholder', originalPlaceholder);
75
+ // #endregion
76
+
66
77
 
67
- inputField.after(displayInputField);
78
+ // #region transform datalist into dropdown
68
79
 
69
- // Hide original input field
70
- inputField.setAttribute('type', 'hidden');
80
+ // Turn off the browser's default datalist functionality to allow for a custom implementation
81
+ inputElement.setAttribute('autocomplete', 'off');
82
+ inputElement.setAttribute('aria-autocomplete', 'none');
71
83
 
72
- // if data list does not exist then create one and append
73
- if (!datalist) {
74
- datalist = document.createElement('datalist');
75
- const listID = safeID('list');
76
- datalist.setAttribute('id', listID);
77
- searchWrapper.appendChild(datalist);
84
+ if(inputElement && inputElement.hasAttribute('list')){
78
85
 
79
- displayInputField.setAttribute('list', listID);
86
+ inputElement.setAttribute('data-list', inputElement.getAttribute('list') || '');
87
+ inputElement.setAttribute('list', '');
80
88
  }
81
89
 
82
- displayInputField.addEventListener('change', function (e) {
83
- inputField.value = displayInputField.value;
90
+ if (!datalistElement) {
91
+ datalistElement = document.createElement('datalist');
92
+ const listID = `${inputElement?.getAttribute('name')}-list`;
93
+ datalistElement.setAttribute('id', listID);
94
+ inputElement?.setAttribute('data-list', listID);
95
+ this.appendChild(datalistElement);
96
+ }
97
+ datalistElement.setAttribute('slot', 'datalist');
98
+
99
+ datalistElement.querySelectorAll<HTMLOptionElement>('option').forEach((option) => {
100
+
101
+ option.setAttribute('tabindex', '0');
102
+
103
+ if(option.textContent == '' && option.hasAttribute('value')){
104
+ option.textContent = option.getAttribute('value');
105
+ }
106
+
84
107
  });
85
108
 
86
- advancedSelect(this, displayInputField, datalist, false);
109
+ datalistElement.addEventListener('click', (event) => {
110
+ const optionElement = getOptionFromEvent(event);
111
+
112
+ if (optionElement) {
113
+
114
+ event.stopPropagation();
115
+ event.preventDefault();
87
116
 
117
+ if (document.activeElement instanceof HTMLElement) document.activeElement.blur();
118
+ this.classList.remove('js-show-datalist');
119
+ datalistSelectOption(this, inputElement, optionElement);
120
+ }
121
+ });
122
+ // #endregion
88
123
 
89
- const checkMatch = (): void => {
90
- const match = datalist.querySelector(`option[value="${displayInputField.value}" i]`);
91
- const subMatch = datalist.querySelector(`option[value*="${displayInputField.value}" i]`);
124
+ // #region control input field
125
+ inputElement.addEventListener('input', () => {
126
+
127
+ if(inputElement.value.length >= 1){
128
+ this.classList.add('has-value');
129
+ }
130
+ else{
131
+ this.classList.remove('has-value');
132
+ }
92
133
 
93
- if (match) {
94
- inputField.value = match.getAttribute('data-actual-value');
95
- displayInputField.value = match.getAttribute('data-actual-value');
134
+ if(inputElement.value.length >= minLength){
135
+ //inputElement.removeAttribute('data-value');
136
+ this.classList.add('js-show-datalist');
96
137
 
97
- displayInputField.classList.remove('is-invalid');
98
- displayInputField.closest('label').removeAttribute('data-error');
99
- }
100
- else if (displayInputField.value.length >= minLength && !subMatch) {
101
- displayInputField.classList.add('is-invalid');
102
- displayInputField.closest('label').setAttribute('data-error', 'No results returned');
103
138
 
104
- if(searchWrapper.hasAttribute('data-url'))
105
- datalist.innerHTML = '';
106
- }
139
+ if(this.hasAttribute('data-url')){
140
+ void search(this, datalistElement, inputElement.value)
141
+ }
142
+ else {
143
+ filterDatalist(datalistElement, inputElement.value);
144
+ }
145
+ }
107
146
  else {
108
- displayInputField.classList.remove('is-invalid');
109
- displayInputField.closest('label').removeAttribute('data-error');
147
+ this.classList.remove('js-show-datalist');
110
148
  }
111
- }
112
149
 
113
-
114
- const search = async (searchterm): any => {
115
-
116
- if(!this.getAttribute('data-url'))
117
- return false;
118
-
119
- let ajaxURL = this.getAttribute('data-url');
120
- ajaxURL += `${encodeURI(searchterm)}`;
121
-
122
- // Setup controller vars if not already set
123
- if (!window.controller) window.controller = [];
124
-
125
- // Abort if controller already present for this url
126
- if (window.controller[ajaxURL]) window.controller[ajaxURL].abort();
127
-
128
- // Create a new controller so it can be aborted if new fetch made
129
- window.controller[ajaxURL] = new AbortController();
130
- const { signal } = controller[ajaxURL];
131
-
132
- try {
133
- await fetch(ajaxURL, {
134
- signal: signal,
135
- method: 'get',
136
- credentials: 'same-origin',
137
- mode: 'no-cors',
138
- headers: new Headers({
139
- 'Content-Type': 'application/json',
140
- Accept: 'application/json',
141
- 'X-Requested-With': 'XMLHttpRequest',
142
- 'X-XSRF-TOKEN': Cookies.get('XSRF-TOKEN'),
143
- }),
144
- })
145
- .then((response) => response.json())
146
- .then((response) => {
147
- // populate datalist
148
- let listString = '';
149
- const loopValues = resolvePath(response, loopSchema, '');
150
-
151
- if (isTraversable(loopValues) && typeof loopValues.forEach == 'function') {
152
- loopValues.forEach((item) => {
153
- const actualValue = resolvePath(item, valueSchema, '');
154
- const displayValue = resolvePath(item, displaySchema, '').replace('\n', ', ');
155
-
156
- if (!datalist.querySelector(`option[data-actual-value="${actualValue}"]`))
157
- listString += `<option value="${displayValue}" data-actual-value="${actualValue}">${displayValue}</option>`;
158
- });
159
- } else if (typeof loopValues == 'object') {
160
- for (const [key, value] of Object.entries(loopValues)) {
161
- if (isTraversable(value) && typeof value.forEach == 'function') {
162
- value.forEach((item) => {
163
- const actualValue = resolvePath(item, valueSchema, '');
164
- const displayValue = resolvePath(item, displaySchema, '').replace('\n', ', ');
165
-
166
- if (!datalist.querySelector(`option[data-actual-value="${actualValue}"]`))
167
- listString += `<option value="${key}: ${displayValue}" data-actual-value='${actualValue}'>${key}: ${displayValue}</option>`;
168
- });
169
- }
170
- }
171
- }
150
+ });
151
+ inputElement.addEventListener('focus', () => {
172
152
 
173
- datalist.innerHTML += listString;
174
-
175
- // filter the list on the client side just in case
176
- const text = searchterm.toUpperCase();
177
- for (const option of datalist.options) {
178
- if (option.value.toUpperCase().indexOf(text) > -1) {
179
- option.style.display = 'block';
180
- option.classList.remove('hide');
181
- } else {
182
- option.style.display = 'none';
183
- option.classList.add('hide');
184
- }
185
- }
153
+ if(inputElement.value == inputElement.getAttribute('data-value')){
154
+ const selectedValue = inputElement.getAttribute('data-value') || '';
155
+
156
+ inputElement.value = '';
157
+ inputElement.setAttribute('placeholder', selectedValue);
158
+ this.classList.remove('js-show-datalist');
159
+ }
160
+ else if(inputElement.value.length >= minLength){
161
+ this.classList.add('js-show-datalist');
162
+ }
163
+ });
186
164
 
187
- searchWrapper.classList.add('was-validated');
188
- checkMatch();
165
+ inputElement.addEventListener('blur', () => {
166
+ const selectedValue = inputElement.getAttribute('data-value');
189
167
 
190
- return response;
191
- });
192
- } catch (error) {
193
- console.log(error);
168
+ if(!inputElement.value && selectedValue){
169
+
170
+ inputElement.value = selectedValue;
171
+ //inputElement.setAttribute('placeholder', inputElement.getAttribute('data-value'));
172
+ //this.classList.remove('js-show-datalist');
194
173
  }
195
- };
174
+ // Set timeout to allow click event to fire on options before hiding the list again
175
+
176
+ setTimeout(() => {
177
+ this.classList.remove('js-force-show-datalist');
178
+ this.classList.remove('js-show-datalist');
179
+ }, 200);
180
+
181
+ const placeholder = inputElement.getAttribute('data-placeholder');
182
+
183
+ if(placeholder)
184
+ inputElement.setAttribute('placeholder', placeholder);
185
+ });
196
186
 
187
+ // #endregion
197
188
 
198
- datalist.addEventListener('click', function (event) {
189
+ // #region control suffix button
190
+ suffixElement.addEventListener('click', () => {
191
+ const form = this.closest<HTMLFormElement>('form');
199
192
 
200
- if (event && event.target instanceof HTMLElement && event.target.closest('option')) {
201
-
202
- const option = event.target.closest('option');
203
- const value = option?.hasAttribute('data-actual-value') ? option?.getAttribute('data-actual-value') : option?.getAttribute('data-value');
204
- inputField.value = value;
193
+ if(form && !this.hasAttribute('data-prevent-submit')){
205
194
 
206
- const changeEvent = new CustomEvent('value-change', {
207
- detail: { value: value },
208
- });
209
- searchWrapper.dispatchEvent(changeEvent);
195
+ form.requestSubmit();
196
+ }
197
+ else {
198
+ inputElement.focus();
199
+ this.classList.add('js-force-show-datalist');
210
200
  }
211
201
  });
202
+ // #endregion
203
+
204
+ // #region keyboard navigation
205
+
206
+ this.addEventListener('keydown', (event) => {
207
+
208
+
209
+ switch (event.key) {
210
+
211
+ case 'ArrowDown':
212
+ //event.stopPropagation();
213
+ //event.preventDefault();
214
+
215
+ if(event && event.target instanceof HTMLElement && event.target == inputElement){
216
+ this.querySelector<HTMLOptionElement>('datalist option:not(.js-hide)')?.focus();
217
+ }
218
+
219
+ break;
220
+
221
+ }
212
222
 
213
- this.addEventListener('close-button-pressed', function (event) {
223
+ /*
224
+ if (event && event.target instanceof HTMLElement && event.target.closest('a, button, summary')) {
225
+ const activeItem = document.activeElement;
226
+ const prevIndex = Array.from(topLevelmenuItems).indexOf(activeItem) - 1;
227
+ const nextIndex = Array.from(topLevelmenuItems).indexOf(activeItem) + 1;
228
+
229
+ switch (
230
+ event.keyCode // change to event.key to key to use the above variable
231
+ ) {
232
+ case 27: // Esc
233
+ if (activeItem.closest('details')) {
234
+ event.stopPropagation();
235
+ event.preventDefault();
236
+ activeItem.closest('details').removeAttribute('open');
237
+ activeItem.closest('details').querySelector(':scope summary').focus();
238
+ } else {
239
+ event.stopPropagation();
240
+ menuButton.focus();
241
+ }
242
+
243
+ break;
244
+ case 32: // Space
245
+ case 13: // Enter
246
+ break;
247
+ case 35: // end
248
+ event.stopPropagation();
249
+ event.preventDefault();
250
+
251
+ this.querySelector('details[open]').removeAttribute('open');
252
+ Array.from(menuItems)[menuItems.length - 1].focus();
253
+
254
+ break;
255
+ case 36: // home
256
+ event.stopPropagation();
257
+ event.preventDefault();
258
+
259
+ this.querySelector('details[open]').removeAttribute('open');
260
+ Array.from(menuItems)[0].focus();
261
+
262
+ break;
263
+ case 38: // up
264
+ event.stopPropagation();
265
+ event.preventDefault();
266
+
267
+ if (Array.from(topLevelmenuItems).indexOf(activeItem) > -1) {
268
+ if (Array.from(topLevelmenuItems)[prevIndex] != undefined)
269
+ Array.from(topLevelmenuItems)[prevIndex].focus();
270
+ else Array.from(topLevelmenuItems)[topLevelmenuItems.length - 1].focus();
271
+ } else if (activeItem.closest('details')) {
272
+ const subMenuItems = activeItem
273
+ .closest('details')
274
+ .querySelectorAll('a, button, :scope details > summary');
275
+ subPrevIndex = Array.from(subMenuItems).indexOf(activeItem) - 1;
276
+
277
+ if (Array.from(subMenuItems)[subPrevIndex] != undefined) Array.from(subMenuItems)[subPrevIndex].focus();
278
+ else Array.from(subMenuItems)[subMenuItems.length - 1].focus();
279
+ }
280
+
281
+ break;
282
+ case 40: // down
283
+ event.stopPropagation();
284
+ event.preventDefault();
285
+
286
+ if (Array.from(topLevelmenuItems).indexOf(activeItem) > -1) {
287
+ if (Array.from(topLevelmenuItems)[nextIndex] != undefined)
288
+ Array.from(topLevelmenuItems)[nextIndex].focus();
289
+ else Array.from(topLevelmenuItems)[0].focus();
290
+ } else if (activeItem.closest('details')) {
291
+ const subMenuItems = activeItem
292
+ .closest('details')
293
+ .querySelectorAll('a, button, :scope details > summary');
294
+ subNextIndex = Array.from(subMenuItems).indexOf(activeItem) + 1;
295
+
296
+ if (Array.from(subMenuItems)[subNextIndex] != undefined) Array.from(subMenuItems)[subNextIndex].focus();
297
+ else Array.from(subMenuItems)[0].focus();
298
+ }
214
299
 
215
- if(searchWrapper.hasAttribute('data-url')) {
216
- datalist.innerHTML = '';
300
+ break;
301
+ }
217
302
  }
218
- inputField?.value = '';
219
303
 
220
- searchWrapper.classList.remove('was-validated');
221
-
222
- displayInputField.classList.remove('is-invalid');
223
- displayInputField.closest('label').removeAttribute('data-error');
304
+ */
224
305
  });
225
306
 
307
+ // #endregion
226
308
 
227
- // Search the endpoint when 3 characters has been added
228
- if (searchWrapper.hasAttribute('data-url')) {
309
+ // #region empty button
310
+ clearBtn?.addEventListener('click', () => {
229
311
 
230
- displayInputField.addEventListener('input', () => {
312
+ this.classList.remove('js-show-datalist');
313
+ inputElement.value = '';
314
+ inputElement.removeAttribute('data-value');
315
+ inputElement.focus();
316
+ this.classList.remove('has-value');
231
317
 
232
- if(displayInputField.value.length < minLength){
233
- datalist.innerHTML = '';
234
- }
318
+ inputElement.setAttribute('placeholder', this.getAttribute('data-original-placeholder') || '');
235
319
 
236
- if (displayInputField.value.length == minLength) {
237
- search(displayInputField.value);
238
- }
239
- });
240
- }
241
- else {
242
- // on change update oringinal field with the actual value and use displayed input for the nice display text
243
- displayInputField.addEventListener('input', () => {
244
- checkMatch();
245
- });
246
- }
320
+ const inputName = inputElement.getAttribute('name');
321
+ const alternateInput = inputName ? this.querySelector<HTMLInputElement>(`[name="${inputName}Alt"]`) : null;
247
322
 
248
- if (searchWrapper.hasAttribute('data-prevent-submit')) {
249
- const form = searchWrapper.closest('form');
323
+ alternateInput?.remove();
250
324
 
251
- form.addEventListener('submit', (e) => {
252
- e.preventDefault();
325
+ datalistElement.querySelectorAll<HTMLOptionElement>('option').forEach((option) => {
326
+
327
+ option.classList.remove('active');
253
328
  });
254
- }
329
+ });
330
+
255
331
  }
256
332
  }
257
333
 
@@ -17,26 +17,28 @@ class iamSTDNav extends HTMLElement {
17
17
  defaultToNav = ():void => {
18
18
 
19
19
  const defaultContent = this.innerHTML;
20
- this.innerHTML = `<iam-nav>
20
+ this.innerHTML = `<iam-nav ${(this.hasAttribute('class') ? `class="${this.getAttribute('class')}"`:'')}>
21
21
  ${defaultContent}
22
22
  </iam-nav>`;
23
23
  }
24
24
 
25
25
  transformToNav = (data):void => {
26
-
26
+
27
+ const navElement = this.querySelector('iam-nav') ?? this;
28
+
27
29
  // Remove current links
28
- this.querySelector('iam-nav').querySelectorAll(`:scope > *`).forEach((element) => {
30
+ navElement.querySelectorAll(`:scope > *`).forEach((element) => {
29
31
 
30
32
  if(!element.hasAttribute('slot'))
31
33
  element.remove();
32
34
  });
33
35
 
34
- const defaultContent = this.querySelector('iam-nav').innerHTML;
36
+ const defaultContent = navElement.innerHTML;
35
37
 
36
- this.innerHTML = `<iam-nav ${(this.hasAttribute('class') ? `class="${this.getAttribute('class')}"`:'')}>
37
- ${defaultContent}
38
- ${populateNav(data)}
39
- </iam-nav>`;
38
+ navElement.innerHTML = `${defaultContent}${populateNav(data)}`;
39
+
40
+ const customEvent = new CustomEvent('rebuilt');
41
+ navElement.dispatchEvent(customEvent);
40
42
  }
41
43
 
42
44
  defaultToSecondary = (): void => {
@@ -65,36 +67,38 @@ class iamSTDNav extends HTMLElement {
65
67
  this.outerHTML = `${defaultContent}`;
66
68
  }
67
69
 
68
-
69
70
  async connectedCallback(): void {
70
-
71
+
71
72
  const component = this;
72
73
  this.wrapper = this.shadowRoot?.querySelector('.wrapper');
73
74
 
74
75
  if (!window.customElements.get(`iam-nav`))
75
76
  window.customElements.define(`iam-nav`, iamNav);
76
-
77
+
77
78
  if(this.hasAttribute('data-hub')){
78
79
  this.defaultToNav();
80
+
81
+ this.querySelector('.nav--menu.js-show')?.classList.remove('js-show');
79
82
  }
80
83
  else {
81
84
  //this.defaultToSecondary(); TODO: change this to show default content but still be able to update
82
85
  }
83
86
 
84
87
 
85
-
86
88
  const data = await loadNavData(Cookies).then(
87
89
  (data) => {
88
90
 
89
-
90
91
  if(typeof data == 'string'){
91
-
92
+
92
93
  return data;
93
94
  }
94
95
 
95
96
  //console.log(data);
96
97
  if(this.hasAttribute('data-hub')){
97
- this.transformToNav(data);
98
+
99
+ const filteredData = data.filter(section => section.attributes.title != "Learning and support");
100
+
101
+ this.transformToNav(filteredData);
98
102
  }
99
103
  else {
100
104
  this.transformToSecondary(data);
@@ -104,13 +108,12 @@ class iamSTDNav extends HTMLElement {
104
108
  }
105
109
  );
106
110
 
107
-
111
+
108
112
  const userData = await loadUserData(Cookies).then(
109
113
  (data) => {
110
114
 
111
115
  setEnabledLinks(component,data);
112
116
 
113
-
114
117
  Array.from(document.querySelectorAll('[data-variable]')).forEach((element) => {
115
118
 
116
119
  if(data.attributes[element.getAttribute('data-variable')])
@@ -2,3 +2,9 @@ declare module '*.html' {
2
2
  const value: string;
3
3
  export default value;
4
4
  }
5
+
6
+ type DataLayerEvent = Record<string, unknown>;
7
+
8
+ type WindowWithDataLayer = Window & {
9
+ dataLayer: DataLayerEvent[];
10
+ };