@iamproperty/components 7.5.1--beta6 → 7.5.1--beta8

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 (190) 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/applied-filters.css +1 -1
  6. package/assets/css/components/applied-filters.css.map +1 -1
  7. package/assets/css/components/calendar.component.css +1 -1
  8. package/assets/css/components/calendar.component.css.map +1 -1
  9. package/assets/css/components/card.component.css +1 -1
  10. package/assets/css/components/card.component.css.map +1 -1
  11. package/assets/css/components/fileupload.css +1 -1
  12. package/assets/css/components/fileupload.css.map +1 -1
  13. package/assets/css/components/input-range.component.css +1 -0
  14. package/assets/css/components/input-range.component.css.map +1 -0
  15. package/assets/css/components/input.component.css +1 -0
  16. package/assets/css/components/input.component.css.map +1 -0
  17. package/assets/css/components/modal.component.css +1 -0
  18. package/assets/css/components/modal.component.css.map +1 -0
  19. package/assets/css/components/multi-step-modal.component.css +1 -0
  20. package/assets/css/components/multi-step-modal.component.css.map +1 -0
  21. package/assets/css/components/multi-step-modal.global.css +1 -0
  22. package/assets/css/components/multi-step-modal.global.css.map +1 -0
  23. package/assets/css/components/multiselect.css +1 -1
  24. package/assets/css/components/multiselect.css.map +1 -1
  25. package/assets/css/components/nav.component.css +1 -1
  26. package/assets/css/components/nav.component.css.map +1 -1
  27. package/assets/css/components/pagination.css +1 -1
  28. package/assets/css/components/pagination.css.map +1 -1
  29. package/assets/css/components/password.component.css +1 -0
  30. package/assets/css/components/password.component.css.map +1 -0
  31. package/assets/css/components/slider.css +1 -1
  32. package/assets/css/components/slider.css.map +1 -1
  33. package/assets/css/components/tabs.component.css +1 -1
  34. package/assets/css/components/tabs.component.css.map +1 -1
  35. package/assets/css/components/tabs.config.css +1 -1
  36. package/assets/css/components/tabs.config.css.map +1 -1
  37. package/assets/css/core.min.css +1 -1
  38. package/assets/css/core.min.css.map +1 -1
  39. package/assets/css/mobile-core.min.css +1 -1
  40. package/assets/css/mobile-core.min.css.map +1 -1
  41. package/assets/css/mobile.min.css +1 -1
  42. package/assets/css/mobile.min.css.map +1 -1
  43. package/assets/css/style.min.css +1 -1
  44. package/assets/css/style.min.css.map +1 -1
  45. package/assets/js/components/accordion/accordion.component.js +1 -1
  46. package/assets/js/components/accordion/accordion.component.min.js +3 -3
  47. package/assets/js/components/accordion/accordion.component.min.js.map +1 -1
  48. package/assets/js/components/actionbar/actionbar.component.js +2 -4
  49. package/assets/js/components/actionbar/actionbar.component.min.js +4 -4
  50. package/assets/js/components/actionbar/actionbar.component.min.js.map +1 -1
  51. package/assets/js/components/address-lookup/address-lookup.component.js +45 -0
  52. package/assets/js/components/address-lookup/address-lookup.component.min.js +12 -4
  53. package/assets/js/components/address-lookup/address-lookup.component.min.js.map +1 -1
  54. package/assets/js/components/advanced-select/advanced-select.component.min.js +1 -1
  55. package/assets/js/components/applied-filters/applied-filters.component.js +0 -2
  56. package/assets/js/components/applied-filters/applied-filters.component.min.js +5 -7
  57. package/assets/js/components/applied-filters/applied-filters.component.min.js.map +1 -1
  58. package/assets/js/components/barchart/barchart.component.min.js +1 -1
  59. package/assets/js/components/bento-grid/bento-grid.component.min.js +1 -1
  60. package/assets/js/components/calendar/calendar.component.min.js +5 -5
  61. package/assets/js/components/card/card.component.min.js +8 -8
  62. package/assets/js/components/card/card.component.min.js.map +1 -1
  63. package/assets/js/components/carousel/carousel.component.min.js +1 -1
  64. package/assets/js/components/collapsible-side/collapsible-side.component.min.js +1 -1
  65. package/assets/js/components/content/content.component.min.js +1 -1
  66. package/assets/js/components/darkmode/darkmode.component.min.js +1 -1
  67. package/assets/js/components/doughnutchart/doughnutchart.component.min.js +1 -1
  68. package/assets/js/components/fileupload/fileupload.component.min.js +4 -4
  69. package/assets/js/components/filter-card/filter-card.component.js +19 -0
  70. package/assets/js/components/filter-card/filter-card.component.min.js +4 -4
  71. package/assets/js/components/filter-card/filter-card.component.min.js.map +1 -1
  72. package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
  73. package/assets/js/components/header/header.component.min.js +1 -1
  74. package/assets/js/components/inline-edit/inline-edit.component.min.js +1 -1
  75. package/assets/js/components/input/input.component.js +128 -0
  76. package/assets/js/components/input/input.component.min.js +16 -0
  77. package/assets/js/components/input/input.component.min.js.map +1 -0
  78. package/assets/js/components/input-range/input-range.component.js +62 -0
  79. package/assets/js/components/input-range/input-range.component.min.js +14 -0
  80. package/assets/js/components/input-range/input-range.component.min.js.map +1 -0
  81. package/assets/js/components/marketing/marketing.component.min.js +1 -1
  82. package/assets/js/components/menu/menu.component.min.js +1 -1
  83. package/assets/js/components/milestone/milestone.component.min.js +1 -1
  84. package/assets/js/components/milestone-group/milestone-group.component.min.js +1 -1
  85. package/assets/js/components/modal/modal.component.js +141 -0
  86. package/assets/js/components/modal/modal.component.min.js +28 -0
  87. package/assets/js/components/modal/modal.component.min.js.map +1 -0
  88. package/assets/js/components/multi-step/multi-step.component.min.js +1 -1
  89. package/assets/js/components/multi-step-modal/multi-step-modal.component.js +233 -0
  90. package/assets/js/components/multi-step-modal/multi-step-modal.component.min.js +17 -0
  91. package/assets/js/components/multi-step-modal/multi-step-modal.component.min.js.map +1 -0
  92. package/assets/js/components/multiselect/multiselect.component.min.js +4 -4
  93. package/assets/js/components/nav/nav.component.min.js +5 -5
  94. package/assets/js/components/nav/nav.component.min.js.map +1 -1
  95. package/assets/js/components/notification/notification.component.min.js +1 -1
  96. package/assets/js/components/pagination/pagination.component.js +0 -1
  97. package/assets/js/components/pagination/pagination.component.min.js +4 -4
  98. package/assets/js/components/pagination/pagination.component.min.js.map +1 -1
  99. package/assets/js/components/password/password.component.js +93 -0
  100. package/assets/js/components/password/password.component.min.js +17 -0
  101. package/assets/js/components/password/password.component.min.js.map +1 -0
  102. package/assets/js/components/rank/rank.component.min.js +1 -1
  103. package/assets/js/components/rankings/rankings.component.min.js +1 -1
  104. package/assets/js/components/record-card/record-card.component.min.js +4 -4
  105. package/assets/js/components/record-card/record-card.component.min.js.map +1 -1
  106. package/assets/js/components/search/search.component.min.js +1 -1
  107. package/assets/js/components/slider/slider.component.min.js +3 -3
  108. package/assets/js/components/split-button/split-button.component.min.js +1 -1
  109. package/assets/js/components/std-address-lookup/std-address-lookup.component.js +2 -0
  110. package/assets/js/components/std-address-lookup/std-address-lookup.component.min.js +18 -8
  111. package/assets/js/components/std-address-lookup/std-address-lookup.component.min.js.map +1 -1
  112. package/assets/js/components/table/table.component.min.js +4 -4
  113. package/assets/js/components/table/table.component.min.js.map +1 -1
  114. package/assets/js/components/table-ajax/table-ajax.component.min.js +4 -4
  115. package/assets/js/components/table-ajax/table-ajax.component.min.js.map +1 -1
  116. package/assets/js/components/table-basic/table-basic.component.min.js +2 -2
  117. package/assets/js/components/table-basic/table-basic.component.min.js.map +1 -1
  118. package/assets/js/components/table-no-submit/table-no-submit.component.min.js +1 -1
  119. package/assets/js/components/table-no-submit/table-no-submit.component.min.js.map +1 -1
  120. package/assets/js/components/table-submit/table-submit.component.min.js +2 -2
  121. package/assets/js/components/table-submit/table-submit.component.min.js.map +1 -1
  122. package/assets/js/components/tabs/tabs.component.min.js +2 -2
  123. package/assets/js/components/video-card/video-card.component.min.js +4 -4
  124. package/assets/js/components/video-card/video-card.component.min.js.map +1 -1
  125. package/assets/js/components/word-count/word-count.component.min.js +1 -1
  126. package/assets/js/modules/applied-filters.js +80 -62
  127. package/assets/js/modules/card.module.js +6 -1
  128. package/assets/js/modules/dialogs.js +6 -2
  129. package/assets/js/modules/password.js +72 -0
  130. package/assets/js/modules/table.js +103 -32
  131. package/assets/js/scripts.bundle.js +2 -3
  132. package/assets/js/scripts.bundle.js.map +1 -1
  133. package/assets/js/scripts.bundle.min.js +2 -2
  134. package/assets/js/scripts.bundle.min.js.map +1 -1
  135. package/assets/js/scripts.js +0 -2
  136. package/assets/sass/_components.scss +2 -0
  137. package/assets/sass/_elements.scss +2 -0
  138. package/assets/sass/components/actionbar.component.scss +1 -0
  139. package/assets/sass/components/address-lookup.component.scss +20 -0
  140. package/assets/sass/components/applied-filters.scss +10 -14
  141. package/assets/sass/components/input-range.component.scss +38 -0
  142. package/assets/sass/components/input.component.scss +102 -0
  143. package/assets/sass/components/modal.component.scss +269 -0
  144. package/assets/sass/components/multi-step-modal.component.scss +255 -0
  145. package/assets/sass/components/multi-step-modal.global.scss +92 -0
  146. package/assets/sass/components/password.component.scss +60 -0
  147. package/assets/sass/components/tabs.config.scss +2 -2
  148. package/assets/sass/elements/badge-tag.scss +0 -1
  149. package/assets/sass/elements/details.scss +12 -7
  150. package/assets/sass/elements/dialog.scss +46 -5
  151. package/assets/sass/elements/forms.scss +41 -177
  152. package/assets/sass/elements/hr.scss +1 -1
  153. package/assets/sass/elements/modal.scss +19 -21
  154. package/assets/sass/elements/prefix.scss +115 -0
  155. package/assets/ts/components/accordion/accordion.component.ts +1 -1
  156. package/assets/ts/components/actionbar/actionbar.component.ts +3 -10
  157. package/assets/ts/components/address-lookup/address-lookup.component.ts +60 -0
  158. package/assets/ts/components/applied-filters/applied-filters.component.ts +0 -2
  159. package/assets/ts/components/filter-card/filter-card.component.ts +27 -0
  160. package/assets/ts/components/input/input.component.ts +168 -0
  161. package/assets/ts/components/input-range/input-range.component.ts +78 -0
  162. package/assets/ts/components/modal/modal.component.ts +188 -0
  163. package/assets/ts/components/multi-step-modal/multi-step-modal.component.ts +304 -0
  164. package/assets/ts/components/pagination/pagination.component.ts +0 -2
  165. package/assets/ts/components/password/password.component.ts +118 -0
  166. package/assets/ts/components/std-address-lookup/std-address-lookup.component.ts +2 -1
  167. package/assets/ts/modules/applied-filters.ts +110 -71
  168. package/assets/ts/modules/card.module.ts +9 -4
  169. package/assets/ts/modules/dialogs.ts +6 -2
  170. package/assets/ts/modules/password.ts +82 -0
  171. package/assets/ts/modules/table.ts +102 -12
  172. package/assets/ts/scripts.ts +2 -2
  173. package/dist/components.es.js +641 -959
  174. package/dist/components.umd.js +275 -182
  175. package/package.json +2 -2
  176. package/src/components/Input/Input.vue +19 -363
  177. package/src/components/InputRange/InputRange.vue +22 -0
  178. package/src/components/Modal/Modal.vue +22 -0
  179. package/src/components/MultiStepModal/MultiStepModal.vue +23 -0
  180. package/src/components/{PasswordIndicator/PasswordIndicator.vue → Password/Password.vue} +23 -23
  181. package/assets/js/components/password-indicator/password-indicator.component.js +0 -19
  182. package/assets/js/components/password-indicator/password-indicator.component.min.js +0 -7
  183. package/assets/js/components/password-indicator/password-indicator.component.min.js.map +0 -1
  184. package/assets/js/modules/form.js +0 -125
  185. package/assets/js/modules/inputs.js +0 -151
  186. package/assets/js/modules/password-indicator.js +0 -21
  187. package/assets/ts/components/password-indicator/password-indicator.component.ts +0 -24
  188. package/assets/ts/modules/form.ts +0 -166
  189. package/assets/ts/modules/inputs.ts +0 -181
  190. package/assets/ts/modules/password-indicator.ts +0 -29
@@ -0,0 +1,304 @@
1
+ import { trackComponent, trackComponentRegistered } from '../_global';
2
+
3
+ trackComponentRegistered('iam-multi-step-modal');
4
+
5
+ class iamMultiStepModal extends HTMLElement {
6
+ constructor() {
7
+ super();
8
+ this.attachShadow({ mode: 'open' });
9
+
10
+ const assetLocation = document.body.hasAttribute('data-assets-location')
11
+ ? document.body.getAttribute('data-assets-location')
12
+ : '/assets';
13
+ const loadCSS = `@import "${assetLocation}/css/components/multi-step-modal.component.css";`;
14
+
15
+ const template = document.createElement('template');
16
+ template.innerHTML = `
17
+ <style>
18
+ ${loadCSS}
19
+ </style>
20
+ <link rel="stylesheet" href="https://kit.fontawesome.com/26fdbf0179.css" crossorigin="anonymous" />
21
+ <dialog>
22
+ <button class="btn btn-compact btn-secondary fa-xmark-large" data-close>Close</button>
23
+ <div class="steps" parts="steps">
24
+ </div>
25
+ <slot></slot>
26
+ </dialog>
27
+ `;
28
+
29
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
30
+ }
31
+
32
+ connectedCallback(): void {
33
+
34
+ const originalDialog = this.querySelector('dialog');
35
+
36
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
37
+ const MultiStepComponent = this;
38
+ const id = this.hasAttribute('id') ? this.getAttribute('id') : originalDialog?.getAttribute('id');
39
+ const dialog = this.shadowRoot?.querySelector('dialog');
40
+
41
+ const closeButton = this.shadowRoot?.querySelector('[data-close]');
42
+ const button = document.querySelector(`[data-modal="${id}"]`);
43
+
44
+ const steps = this.shadowRoot.querySelector('.steps');
45
+ const form = this.querySelector('form');
46
+
47
+ const openModal = () => {
48
+ dialog?.showModal();
49
+ dialog?.focus();
50
+
51
+ const closeEvent = new CustomEvent('modal-opened', {
52
+ bubbles: true,
53
+ cancelable: true,
54
+ detail: { modalId: id },
55
+ });
56
+
57
+ this.dispatchEvent(closeEvent);
58
+
59
+ window.dataLayer = window.dataLayer || [];
60
+ window.dataLayer.push({
61
+ event: 'openModal',
62
+ id: id,
63
+ });
64
+ }
65
+
66
+ // Disable the original event
67
+ originalDialog?.addEventListener('command', (e) => {
68
+
69
+ if (event.command == "show-modal") {
70
+ e.preventDefault();
71
+ }
72
+ });
73
+
74
+ document.addEventListener('click', (e) => {
75
+
76
+ if(e.target.matches(`[command="show-modal"][commandfor="${id}"]`) || e.target.matches(`[data-modal="${id}"]`)){
77
+ openModal();
78
+ }
79
+ });
80
+
81
+ button?.addEventListener('click', () => {
82
+ dialog?.showModal();
83
+ dialog?.focus();
84
+
85
+ const closeEvent = new CustomEvent('modal-opened', {
86
+ bubbles: true,
87
+ cancelable: true,
88
+ detail: { modalId: id },
89
+ });
90
+
91
+ this.dispatchEvent(closeEvent);
92
+
93
+ window.dataLayer = window.dataLayer || [];
94
+ window.dataLayer.push({
95
+ event: 'openModal',
96
+ id: id,
97
+ });
98
+ });
99
+
100
+ const closeModal = () => {
101
+ dialog?.close();
102
+
103
+ const closeEvent = new CustomEvent('modal-closed', {
104
+ bubbles: true,
105
+ cancelable: true,
106
+ detail: { modalId: id },
107
+ });
108
+
109
+ this.dispatchEvent(closeEvent);
110
+
111
+ window.dataLayer = window.dataLayer || [];
112
+ window.dataLayer.push({
113
+ event: 'closeModal',
114
+ id: id,
115
+ });
116
+ }
117
+
118
+ closeButton?.addEventListener('click', () => {
119
+ closeModal();
120
+ });
121
+
122
+ const fieldsets = Array.from(MultiStepComponent.querySelectorAll('fieldset[data-title]'));
123
+
124
+ fieldsets.forEach((fieldset, index) => {
125
+ steps.insertAdjacentHTML(
126
+ 'beforeend',
127
+ `<button data-title="${fieldset.getAttribute('data-title')}" type="button" class="${index == 0 ? 'active' : ''}" tabindex="-1">${fieldset.getAttribute('data-title')}</button>`
128
+ );
129
+
130
+ if (index === 0) fieldset.classList.add('active');
131
+
132
+ const btnWrapper = document.createElement('div');
133
+ btnWrapper.classList.add('btn--wrapper');
134
+ fieldset.appendChild(btnWrapper);
135
+
136
+ if (index != 0)
137
+ btnWrapper.innerHTML += `<button data-title="${fieldsets[index - 1].getAttribute('data-title')}" class="btn btn-secondary mb-0" data-previous type="button">Previous</button>`;
138
+
139
+ if (index != fieldsets.length - 1)
140
+ btnWrapper.innerHTML += `<button data-title="${fieldsets[index + 1].getAttribute('data-title')}" class="btn btn-primary mb-0" data-next type="button">Next</button>`;
141
+
142
+ // Last fieldset
143
+ if (index == fieldsets.length - 1) {
144
+ if (form && form.querySelector(':scope > button[type="submit"]')) {
145
+ const existingButton = form.querySelector(':scope > button[type="submit"]');
146
+ existingButton.classList.add('mb-0');
147
+
148
+ btnWrapper.insertAdjacentElement('beforeend', existingButton);
149
+ } else
150
+ btnWrapper.innerHTML += `<button data-title="${fieldsets[index].getAttribute('data-title')}" class="btn btn-primary mb-0" data-next type="submit">Submit</button>`;
151
+ }
152
+ });
153
+
154
+ // Open the fieldset with an error inside
155
+ const validatedFieldsets = Array.from(MultiStepComponent.querySelectorAll('fieldset.was-validated'));
156
+ for (let i = 0; i < validatedFieldsets.length; i++) {
157
+ const fieldset = validatedFieldsets[i];
158
+ const fieldsetID = fieldset.getAttribute('data-title');
159
+
160
+ if (fieldset.querySelector('.is-invalid')) {
161
+ Array.from(MultiStepComponent.querySelectorAll(`[data-title="${fieldsetID}"]`)).forEach((element) => {
162
+ element.classList.add('active');
163
+ });
164
+
165
+ break;
166
+ } else {
167
+ Array.from(MultiStepComponent.querySelectorAll(`[data-title="${fieldsetID}"]`)).forEach((element) => {
168
+ element.classList.add('valid');
169
+ });
170
+ }
171
+ }
172
+
173
+ // Prevent the bubble messages
174
+ MultiStepComponent.addEventListener(
175
+ 'invalid',
176
+ (function () {
177
+ return function (e): any {
178
+ e.preventDefault();
179
+ };
180
+ })(),
181
+ true
182
+ );
183
+
184
+ function validateFieldset(button): void {
185
+ const currentFieldset = MultiStepComponent.querySelector(`fieldset.active`)
186
+ ? MultiStepComponent.querySelector(`fieldset.active`)
187
+ : MultiStepComponent.querySelector(`fieldset[data-title]`);
188
+ const currentFieldsetID = currentFieldset.getAttribute('data-title');
189
+ let isFieldsetValid = true;
190
+
191
+ currentFieldset.classList.add('was-validated');
192
+
193
+ Array.from(currentFieldset.querySelectorAll('input')).forEach((input) => {
194
+ if (!input.checkValidity()) isFieldsetValid = false;
195
+ });
196
+
197
+ // If valid mode to next field set
198
+ if (!isFieldsetValid) {
199
+ Array.from(MultiStepComponent.querySelectorAll(`[data-title="${currentFieldsetID}"]`)).forEach((element) => {
200
+ element.classList.remove('valid');
201
+ });
202
+
203
+ Array.from(MultiStepComponent.shadowRoot.querySelectorAll(`[data-title="${currentFieldsetID}"]`)).forEach(
204
+ (element) => {
205
+ element.classList.remove('valid');
206
+ }
207
+ );
208
+ } else {
209
+ Array.from(MultiStepComponent.querySelectorAll(`[data-title="${currentFieldsetID}"]`)).forEach((element) => {
210
+ element.classList.add('valid');
211
+ });
212
+
213
+ Array.from(MultiStepComponent.shadowRoot.querySelectorAll(`[data-title="${currentFieldsetID}"]`)).forEach(
214
+ (element) => {
215
+ element.classList.add('valid');
216
+ }
217
+ );
218
+ }
219
+
220
+ // Allow the previous button to navigate
221
+ if (isFieldsetValid || !button.hasAttribute('data-next')) {
222
+ const fieldset = MultiStepComponent.querySelector(
223
+ `fieldset[data-title="${button.getAttribute('data-title')}"]`
224
+ );
225
+ const step = MultiStepComponent.shadowRoot.querySelector(
226
+ `.steps button[data-title="${button.getAttribute('data-title')}"]`
227
+ );
228
+
229
+ Array.from(MultiStepComponent.querySelectorAll('button')).forEach((button) => {
230
+ button.classList.remove('active');
231
+ });
232
+ Array.from(MultiStepComponent.querySelectorAll('fieldset')).forEach((button) => {
233
+ button.classList.remove('active');
234
+ });
235
+
236
+ step.classList.add('active');
237
+ fieldset.classList.add('active');
238
+ }
239
+
240
+ const fieldsetCount = Array.from(MultiStepComponent.querySelectorAll(`fieldset`)).length;
241
+ const validFieldsetCount = Array.from(MultiStepComponent.querySelectorAll(`fieldset.valid`)).length;
242
+
243
+ // update the progress bar
244
+ MultiStepComponent.style.setProperty('--progress', `${(validFieldsetCount / (fieldsetCount - 1)) * 100}%`);
245
+ }
246
+
247
+ // remove error messages from server
248
+ MultiStepComponent.addEventListener('keydown', (event) => {
249
+ if (event && event.target instanceof HTMLElement && event.target.closest('button')) {
250
+ const button = event.target.closest('button');
251
+
252
+ if (event.keyCode == 13 && button.getAttribute('type') != 'submit') {
253
+ event.preventDefault();
254
+ validateFieldset(button);
255
+ }
256
+ }
257
+
258
+ if (event && event.target instanceof HTMLElement && event.target.closest('input')) {
259
+ const input = event.target.closest('input');
260
+
261
+ input.classList.remove('is-invalid');
262
+
263
+ if (event.keyCode == 13) {
264
+ event.preventDefault();
265
+ }
266
+ }
267
+ });
268
+
269
+ MultiStepComponent.addEventListener('click', (event) => {
270
+ if (event && event.target instanceof HTMLElement && event.target.closest('button[type="submit"]')) {
271
+ const form = event.target.closest('form');
272
+ form.classList.add('was-validated');
273
+ }
274
+ return null;
275
+ });
276
+
277
+ MultiStepComponent.shadowRoot.addEventListener('click', (event) => {
278
+ if (event && event.target instanceof HTMLElement && event.target.closest('button[data-title]')) {
279
+ const button = event.target.closest('button[data-title]');
280
+
281
+ validateFieldset(button);
282
+ }
283
+ return null;
284
+ });
285
+
286
+ trackComponent(MultiStepComponent, 'iam-multi-step', []);
287
+ }
288
+
289
+ static get observedAttributes(): any {
290
+ return ['data-image'];
291
+ }
292
+
293
+ attributeChangedCallback(attrName, oldVal, newVal): void {
294
+ switch (attrName) {
295
+ case 'data-total': {
296
+ if (this.shadowRoot.querySelector('.card__total'))
297
+ this.shadowRoot.querySelector('.card__total').innerHTML = newVal;
298
+ break;
299
+ }
300
+ }
301
+ }
302
+ }
303
+
304
+ export default iamMultiStepModal;
@@ -201,8 +201,6 @@ class iamPagination extends HTMLElement {
201
201
  if (oldVal && oldVal != newVal) {
202
202
  this.setup();
203
203
 
204
- console.log(newVal);
205
-
206
204
  // Dispact the event for other components to use as triggers
207
205
  this.dispatchEvent(new CustomEvent('update-page', { detail: { page: newVal } }));
208
206
  }
@@ -0,0 +1,118 @@
1
+ import { trackComponentRegistered } from '../_global';
2
+ import hibpCheck from '../../vendor/hibp.js';
3
+
4
+ trackComponentRegistered('iam-password');
5
+
6
+ class iamPassword extends HTMLElement {
7
+ constructor() {
8
+ super();
9
+ this.attachShadow({ mode: 'open' });
10
+
11
+ const assetLocation = document.body.hasAttribute('data-assets-location')
12
+ ? document.body.getAttribute('data-assets-location')
13
+ : '/assets';
14
+
15
+ const loadCSS = `@import "${assetLocation}/css/components/password.component.css";`;
16
+
17
+
18
+ const template = document.createElement('template');
19
+ template.innerHTML = `
20
+ <style>
21
+ ${loadCSS}
22
+ </style>
23
+ <link rel="stylesheet" href="https://kit.fontawesome.com/26fdbf0179.css" crossorigin="anonymous">
24
+ <div class="wrapper">
25
+ <slot></slot>
26
+ <button type="button" class="suffix fa-solid fa-eye-slash" data-alt-class="suffix fa-solid fa-eye" aria-hidden="true"><span class="visually-hidden">Show password</span></button>
27
+ </div>
28
+ <span class="pwd-checker"></span>
29
+ `;
30
+ this.shadowRoot?.appendChild(template.content.cloneNode(true));
31
+ }
32
+
33
+ connectedCallback(): void {
34
+
35
+
36
+ const input = this.querySelector('input');
37
+
38
+ const buttonEle = this.shadowRoot.querySelector('button')
39
+ const pwdChecker = this.shadowRoot?.querySelector('.pwd-checker')
40
+
41
+ // Switch icon and input type
42
+ buttonEle.addEventListener('click', (event) => {
43
+ const currentType = input.type;
44
+
45
+ const newType = currentType === 'password' ? 'text' : 'password';
46
+ const isPasswordType = currentType === 'password';
47
+
48
+ input.setAttribute('type', newType);
49
+ input.setAttribute('data-password-type', isPasswordType);
50
+
51
+ if (buttonEle.hasAttribute('data-alt-class')) {
52
+ const newClass = buttonEle.getAttribute('data-alt-class');
53
+ buttonEle.setAttribute('data-alt-class', buttonEle.getAttribute('class'));
54
+ buttonEle.setAttribute('class', newClass);
55
+ }
56
+ });
57
+
58
+
59
+
60
+ input.addEventListener('input', (event) => {
61
+
62
+
63
+ const password = input.value;
64
+ const minChars = input.hasAttribute('minlength') ? input.getAttribute('minlength') : 12;
65
+
66
+ let strength = 1;
67
+ const strengthName = ['Very weak', 'Weak', 'Average', 'Strong', 'Very strong'];
68
+ let extraMsg = '';
69
+
70
+ //has number
71
+ if (password.match(/(?=.*[0-9])/)) strength += 1;
72
+ // has special character
73
+ if (password.match(/(?=.*[!,%,&,#,$,^,*,?,_,~,<,>,])/)) strength += 1;
74
+ // has lowercase alpha
75
+ if (password.match(/(?=.*[a-z])/)) strength += 1;
76
+ // has uppercase alpha
77
+ if (password.match(/(?=.*[A-Z])/)) strength += 1;
78
+
79
+ if (password.length < minChars) {
80
+ strength = 1;
81
+ extraMsg = `(must be at least ${minChars} characters.)`;
82
+ }
83
+
84
+ // if the strength is above weak and above the minimum length do some kind of api call to check if its in a list of passwords
85
+
86
+ if (strength >= 3) {
87
+ hibpCheck(password, input);
88
+
89
+ input.addEventListener('hibpCheck', function (event) {
90
+ checkhibpCheck(event, input);
91
+ });
92
+
93
+ function checkhibpCheck(event, input): void {
94
+ console.log(event.detail);
95
+ if (event.detail) {
96
+ // found
97
+ strength = 3;
98
+ extraMsg = `(this password is very common)`;
99
+
100
+ pwdChecker.innerHTML = `Password strength: ${strengthName[strength - 1]} ${extraMsg}`;
101
+ }
102
+
103
+ input.removeEventListener('hibpCheck', checkhibpCheck); // Succeeds
104
+ }
105
+ }
106
+
107
+ if (strength <= 3) pwdChecker.classList.add('invalid-feedback');
108
+ else pwdChecker.classList.remove('invalid-feedback');
109
+
110
+ pwdChecker.setAttribute('data-strength', strength);
111
+ pwdChecker.innerHTML = `Password strength: ${strengthName[strength - 1]} ${extraMsg}`;
112
+
113
+ });
114
+
115
+ }
116
+ }
117
+
118
+ export default iamPassword;
@@ -1566,6 +1566,8 @@ class iamSTDAddressLookup extends HTMLElement {
1566
1566
  ${this.hasAttribute('data-error-msg') ? `data-error-msg='${this.getAttribute('data-error-msg')}'` : ''}
1567
1567
  ${this.hasAttribute('data-use-default') ? `data-use-default` : ''}
1568
1568
  ${this.hasAttribute('data-force-manual') ? `data-force-manual` : ''}
1569
+ ${this.hasAttribute('data-matched') ? `data-matched='${this.getAttribute('data-matched')}'` : ''}
1570
+ ${this.hasAttribute('data-matched-label') ? `data-matched-label='${this.getAttribute('data-matched-label')}'` : ''}
1569
1571
  data-postcode-lookup-label="Back to UK postcode lookup">
1570
1572
 
1571
1573
  <p class="hint pb-2 d-block" slot="hint">Unsure of the postcode? Check with the <a href="https://www.royalmail.com/find-a-postcode" target="_blank"><i class="fa-regular fa-arrow-up-right-from-square"></i>Royal Mail address finder</a></p>
@@ -1751,7 +1753,6 @@ class iamSTDAddressLookup extends HTMLElement {
1751
1753
  }
1752
1754
  });
1753
1755
 
1754
-
1755
1756
  }
1756
1757
  }
1757
1758
 
@@ -1,5 +1,8 @@
1
1
  function createAppliedFilters(container, filters): void {
2
- function addFilterButton(filters, input, notSet = true): void | boolean {
2
+
3
+ const dialog = container.closest('dialog');
4
+
5
+ const addFilterButton = (filters, input, setFilter = false): void | boolean => {
3
6
  let shouldRemoveFilter = false;
4
7
  let inputName = input.getAttribute('name');
5
8
 
@@ -26,7 +29,7 @@ function createAppliedFilters(container, filters): void {
26
29
  filter.classList.add('filter');
27
30
  filter.classList.add('tag');
28
31
 
29
- if (notSet) filter.classList.add('tag--not-set');
32
+ if (!setFilter) filter.classList.add('tag--not-set');
30
33
 
31
34
  filter.setAttribute('data-name', inputName);
32
35
 
@@ -55,7 +58,7 @@ function createAppliedFilters(container, filters): void {
55
58
  childFilter.classList.add('filter');
56
59
  childFilter.classList.add('tag');
57
60
 
58
- if (notSet) filter.classList.add('tag--not-set');
61
+ if (!setFilter) filter.classList.add('tag--not-set');
59
62
 
60
63
  childFilter.setAttribute('data-name', name);
61
64
  childFilter.innerHTML = filterText.replace('$value', element.value);
@@ -82,107 +85,143 @@ function createAppliedFilters(container, filters): void {
82
85
  parentFilter.classList.add('filter');
83
86
  parentFilter.classList.add('tag');
84
87
 
85
- if (notSet) filter.classList.add('tag--not-set');
88
+ if (!setFilter) filter.classList.add('tag--not-set');
86
89
 
87
90
  parentFilter.setAttribute('data-name', inputName);
88
91
  parentFilter.innerHTML = newFilterText;
89
92
  filters.appendChild(parentFilter);
90
93
  }
91
94
  }
92
- }
93
-
94
- // check for inputs on load
95
- Array.from(
96
- container.querySelectorAll('input[type="checkbox"]:checked, input:not([type="checkbox"]):not([type="radio"])')
97
- ).forEach((input) => {
98
- addFilterButton(filters, input, false);
99
- });
100
-
101
- const dialog = container.closest('dialog');
95
+ };
102
96
 
103
- if (dialog) {
104
- const observer = new MutationObserver(function (event) {
105
- if (event[0].attributeName == 'open') {
106
- Array.from(
107
- container.querySelectorAll('input[type="checkbox"]:checked, input:not([type="checkbox"]):not([type="radio"])')
108
- ).forEach((input) => {
109
- addFilterButton(filters, input, false);
110
- });
111
- }
112
- });
97
+ const checkForChecked = (setFilter = false) => {
113
98
 
114
- observer.observe(dialog, { attributes: true });
115
- }
116
-
117
- container.addEventListener('tags-set', function () {
118
99
  filters.innerHTML = '';
119
100
  Array.from(
120
- container.querySelectorAll('input[type="checkbox"]:checked, input:not([type="checkbox"]):not([type="radio"])')
101
+ container.querySelectorAll('input:is([type="checkbox"],[type="radio"]):checked, input:not([type="checkbox"], [type="radio"])')
121
102
  ).forEach((input) => {
122
- addFilterButton(filters, input, false);
103
+ addFilterButton(filters, input, setFilter);
123
104
  });
124
- });
105
+ };
106
+ // Check for which inputs have been set, setting true sets the filter as set (blue)
107
+ checkForChecked(true);
125
108
 
126
- // check for change in displayed inputs
127
- Array.from(
128
- container.querySelectorAll('input[type="checkbox"]:checked, input:not([type="checkbox"]):not([type="radio"])')
129
- ).forEach((input) => {
130
- input.addEventListener('change', function (event) {
131
- if (!container.hasAttribute('data-keep-same')) addFilterButton(filters, input);
109
+ // Create the main event listener for the component watching for inputs to change
132
110
 
133
- event.stopPropagation(); // Don't allow the below event handler to trigger
111
+ Array.from(container.querySelectorAll('input[data-filter-text]')).forEach((input) => {
112
+
113
+ input.addEventListener('change', function (event) {
114
+
115
+ const setFilter = container.closest('dialog') ? false : true;
116
+
117
+ if (!container.hasAttribute('data-keep-same') && !container.querySelector('dialog'))
118
+ addFilterButton(filters, input, setFilter);
119
+
120
+ if(setFilter){
121
+
122
+ const event = new CustomEvent('update');
123
+ container.parentElement.closest('iam-applied-filters')?.dispatchEvent(event);
124
+ }
134
125
  });
135
126
  });
136
127
 
137
- // Some change event aren't getting triggered above so this event listener on the container will pick them up. This happens with input in modals
138
- container.addEventListener('change', function (event) {
139
- if (event && event.target instanceof HTMLElement && event.target.closest('input[data-filter-text]')) {
140
- const input = event.target.closest('input[data-filter-text]');
141
- if (!container.hasAttribute('data-keep-same')) addFilterButton(filters, input);
128
+
129
+ const filterClicked = (filter) => {
130
+ const names = filter.getAttribute('data-name').split(',');
131
+
132
+ for (let t = 0; t < names.length; t++) {
133
+ const name = names[t];
134
+ let selector = `[name="${name}"]`;
135
+
136
+ if (name.match(/\[(.*)\]/)) {
137
+ //const newName = name.replace(/\[(.*)\]/, `[]`);
138
+ const value = name.replace(/.*\[(.*)\]/, `$1`);
139
+ selector = `[value="${value}"]`;
140
+ }
141
+
142
+ const inputs = container.querySelectorAll(selector);
143
+
144
+ for (let i = 0; i < inputs.length; i++) {
145
+ const input = inputs[i];
146
+
147
+ if (input.getAttribute('type') != 'radio' && input.getAttribute('type') != 'checkbox') {
148
+ input.value = '';
149
+ } else {
150
+ input.checked = false;
151
+ }
152
+
153
+ const changeEvent = new CustomEvent('change');
154
+ input?.dispatchEvent(changeEvent);
155
+ }
142
156
  }
143
- });
157
+
158
+ filter.remove();
159
+ checkForChecked();
160
+ };
161
+
162
+
163
+
164
+
144
165
 
145
166
  filters.addEventListener(
146
167
  'click',
147
168
  function (event) {
148
169
  if (event && event.target instanceof HTMLElement && event.target.closest('.filter')) {
149
170
  const filter = event.target.closest('.filter');
150
- const names = filter.getAttribute('data-name').split(',');
171
+ const filterName = filter.getAttribute('data-name');
151
172
 
152
- for (let t = 0; t < names.length; t++) {
153
- const name = names[t];
154
- let selector = `[name="${name}"]`;
173
+ filterClicked(filter);
155
174
 
156
- if (name.match(/\[(.*)\]/)) {
157
- //const newName = name.replace(/\[(.*)\]/, `[]`);
158
- const value = name.replace(/.*\[(.*)\]/, `$1`);
159
- selector = `[value="${value}"]`;
160
- }
175
+ // If you clicked on the filter on the parent component we want to tell the child component which filter to copy
176
+ if(container.querySelector('dialog iam-applied-filters')) {
177
+ const event = new CustomEvent('filter',{'detail':filterName });
178
+ container.querySelector('dialog iam-applied-filters').dispatchEvent(event);
179
+ }
180
+ }
181
+ },
182
+ false
183
+ );
161
184
 
162
- const inputs = container.querySelectorAll(selector);
185
+ // Listen for
186
+ container.addEventListener('filter', (e) => {
163
187
 
164
- for (let i = 0; i < inputs.length; i++) {
165
- const input = inputs[i];
188
+ const filter = container.shadowRoot.querySelector(`[data-name="${e.detail}"]`);
166
189
 
167
- if (input.getAttribute('type') != 'radio' && input.getAttribute('type') != 'checkbox') {
168
- input.value = '';
190
+ filterClicked(filter);
191
+ });
169
192
 
170
- const event = new Event('force');
171
- if (!container.hasAttribute('data-nosubmit')) input.closest('form').dispatchEvent(event);
172
- } else {
173
- input.checked = false;
193
+ container.addEventListener('set-filters', (e) => {
174
194
 
175
- const event = new Event('force');
176
- if (!container.hasAttribute('data-nosubmit')) input.closest('form').dispatchEvent(event);
177
- }
178
- }
179
- }
195
+ checkForChecked(true);
196
+ });
180
197
 
181
- filter.remove();
198
+ if(dialog){
199
+ // Force the filters inside of the dialog to effect the filters above
200
+ container.querySelector('.btn-primary')?.addEventListener('click', (e) => {
201
+
202
+ const event = new CustomEvent('update');
203
+
204
+ if(container.parentElement.closest('iam-applied-filters'))
205
+ container.parentElement.closest('iam-applied-filters').dispatchEvent(event);
206
+
207
+ if(container.parentElement && container.parentElement.closest('iam-applied-filters') && !container.parentElement.closest('iam-applied-filters').closest('dialog')){
208
+
209
+ const event = new CustomEvent('set-filters');
210
+ container.parentElement.closest('iam-applied-filters').dispatchEvent(event);
182
211
  }
183
- },
184
- false
185
- );
212
+
213
+
214
+ checkForChecked(true);
215
+
216
+ if(!container.querySelector('.btn-primary').hasAttribute('command')){
217
+
218
+ dialog.close();
219
+ const event = new Event('close');
220
+ dialog.dispatchEvent(event);
221
+ }
222
+
223
+ });
224
+ }
186
225
  }
187
226
 
188
227
  export default createAppliedFilters;