@iamproperty/components 7.5.1--beta5 → 7.5.1--beta7
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.
- package/assets/css/components/actionbar.component.css +1 -1
- package/assets/css/components/actionbar.component.css.map +1 -1
- package/assets/css/components/address-lookup.component.css +1 -1
- package/assets/css/components/address-lookup.component.css.map +1 -1
- package/assets/css/components/applied-filters.css +1 -1
- package/assets/css/components/applied-filters.css.map +1 -1
- package/assets/css/components/calendar.component.css +1 -1
- package/assets/css/components/calendar.component.css.map +1 -1
- package/assets/css/components/card.component.css +1 -1
- package/assets/css/components/card.component.css.map +1 -1
- package/assets/css/components/fileupload.css +1 -1
- package/assets/css/components/fileupload.css.map +1 -1
- package/assets/css/components/input-range.component.css +1 -0
- package/assets/css/components/input-range.component.css.map +1 -0
- package/assets/css/components/input.component.css +1 -0
- package/assets/css/components/input.component.css.map +1 -0
- package/assets/css/components/modal.component.css +1 -0
- package/assets/css/components/modal.component.css.map +1 -0
- package/assets/css/components/multi-step-modal.component.css +1 -0
- package/assets/css/components/multi-step-modal.component.css.map +1 -0
- package/assets/css/components/multi-step-modal.global.css +1 -0
- package/assets/css/components/multi-step-modal.global.css.map +1 -0
- package/assets/css/components/multiselect.css +1 -1
- package/assets/css/components/multiselect.css.map +1 -1
- package/assets/css/components/nav.component.css +1 -1
- package/assets/css/components/nav.component.css.map +1 -1
- package/assets/css/components/pagination.css +1 -1
- package/assets/css/components/pagination.css.map +1 -1
- package/assets/css/components/password.component.css +1 -0
- package/assets/css/components/password.component.css.map +1 -0
- package/assets/css/components/slider.css +1 -1
- package/assets/css/components/slider.css.map +1 -1
- package/assets/css/components/tabs.component.css +1 -1
- package/assets/css/components/tabs.component.css.map +1 -1
- package/assets/css/components/tabs.config.css +1 -1
- package/assets/css/components/tabs.config.css.map +1 -1
- package/assets/css/core.min.css +1 -1
- package/assets/css/core.min.css.map +1 -1
- package/assets/css/mobile-core.min.css +1 -1
- package/assets/css/mobile-core.min.css.map +1 -1
- package/assets/css/mobile.min.css +1 -1
- package/assets/css/mobile.min.css.map +1 -1
- package/assets/css/style.min.css +1 -1
- package/assets/css/style.min.css.map +1 -1
- package/assets/js/components/accordion/accordion.component.js +1 -1
- package/assets/js/components/accordion/accordion.component.min.js +3 -3
- package/assets/js/components/accordion/accordion.component.min.js.map +1 -1
- package/assets/js/components/actionbar/actionbar.component.js +2 -4
- package/assets/js/components/actionbar/actionbar.component.min.js +4 -4
- package/assets/js/components/actionbar/actionbar.component.min.js.map +1 -1
- package/assets/js/components/address-lookup/address-lookup.component.js +45 -0
- package/assets/js/components/address-lookup/address-lookup.component.min.js +12 -4
- package/assets/js/components/address-lookup/address-lookup.component.min.js.map +1 -1
- package/assets/js/components/advanced-select/advanced-select.component.min.js +1 -1
- package/assets/js/components/applied-filters/applied-filters.component.js +0 -2
- package/assets/js/components/applied-filters/applied-filters.component.min.js +5 -7
- package/assets/js/components/applied-filters/applied-filters.component.min.js.map +1 -1
- package/assets/js/components/barchart/barchart.component.min.js +1 -1
- package/assets/js/components/bento-grid/bento-grid.component.min.js +1 -1
- package/assets/js/components/calendar/calendar.component.min.js +5 -5
- package/assets/js/components/card/card.component.min.js +8 -8
- package/assets/js/components/card/card.component.min.js.map +1 -1
- package/assets/js/components/carousel/carousel.component.min.js +1 -1
- package/assets/js/components/collapsible-side/collapsible-side.component.min.js +1 -1
- package/assets/js/components/content/content.component.min.js +1 -1
- package/assets/js/components/darkmode/darkmode.component.min.js +1 -1
- package/assets/js/components/doughnutchart/doughnutchart.component.min.js +1 -1
- package/assets/js/components/fileupload/fileupload.component.min.js +4 -4
- package/assets/js/components/filter-card/filter-card.component.js +19 -0
- package/assets/js/components/filter-card/filter-card.component.min.js +4 -4
- package/assets/js/components/filter-card/filter-card.component.min.js.map +1 -1
- package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
- package/assets/js/components/header/header.component.min.js +1 -1
- package/assets/js/components/inline-edit/inline-edit.component.min.js +1 -1
- package/assets/js/components/input/input.component.js +128 -0
- package/assets/js/components/input/input.component.min.js +16 -0
- package/assets/js/components/input/input.component.min.js.map +1 -0
- package/assets/js/components/input-range/input-range.component.js +62 -0
- package/assets/js/components/input-range/input-range.component.min.js +14 -0
- package/assets/js/components/input-range/input-range.component.min.js.map +1 -0
- package/assets/js/components/marketing/marketing.component.min.js +1 -1
- package/assets/js/components/menu/menu.component.min.js +1 -1
- package/assets/js/components/milestone/milestone.component.min.js +1 -1
- package/assets/js/components/milestone-group/milestone-group.component.min.js +1 -1
- package/assets/js/components/modal/modal.component.js +141 -0
- package/assets/js/components/modal/modal.component.min.js +28 -0
- package/assets/js/components/modal/modal.component.min.js.map +1 -0
- package/assets/js/components/multi-step/multi-step.component.min.js +1 -1
- package/assets/js/components/multi-step-modal/multi-step-modal.component.js +233 -0
- package/assets/js/components/multi-step-modal/multi-step-modal.component.min.js +17 -0
- package/assets/js/components/multi-step-modal/multi-step-modal.component.min.js.map +1 -0
- package/assets/js/components/multiselect/multiselect.component.js +1 -1
- package/assets/js/components/multiselect/multiselect.component.min.js +5 -5
- package/assets/js/components/multiselect/multiselect.component.min.js.map +1 -1
- package/assets/js/components/nav/nav.component.min.js +5 -5
- package/assets/js/components/nav/nav.component.min.js.map +1 -1
- package/assets/js/components/notification/notification.component.min.js +1 -1
- package/assets/js/components/pagination/pagination.component.min.js +3 -3
- package/assets/js/components/password/password.component.js +93 -0
- package/assets/js/components/password/password.component.min.js +17 -0
- package/assets/js/components/password/password.component.min.js.map +1 -0
- package/assets/js/components/rank/rank.component.min.js +1 -1
- package/assets/js/components/rankings/rankings.component.min.js +1 -1
- package/assets/js/components/record-card/record-card.component.min.js +4 -4
- package/assets/js/components/record-card/record-card.component.min.js.map +1 -1
- package/assets/js/components/search/search.component.js +1 -1
- package/assets/js/components/search/search.component.min.js +5 -5
- package/assets/js/components/search/search.component.min.js.map +1 -1
- package/assets/js/components/slider/slider.component.min.js +3 -3
- package/assets/js/components/split-button/split-button.component.min.js +1 -1
- package/assets/js/components/std-address-lookup/std-address-lookup.component.js +5 -1
- package/assets/js/components/std-address-lookup/std-address-lookup.component.min.js +22 -9
- package/assets/js/components/std-address-lookup/std-address-lookup.component.min.js.map +1 -1
- package/assets/js/components/table/table.component.min.js +3 -3
- package/assets/js/components/table/table.component.min.js.map +1 -1
- package/assets/js/components/table-ajax/table-ajax.component.min.js +4 -4
- package/assets/js/components/table-ajax/table-ajax.component.min.js.map +1 -1
- package/assets/js/components/table-basic/table-basic.component.min.js +1 -1
- package/assets/js/components/table-basic/table-basic.component.min.js.map +1 -1
- package/assets/js/components/table-no-submit/table-no-submit.component.min.js +1 -1
- package/assets/js/components/table-no-submit/table-no-submit.component.min.js.map +1 -1
- package/assets/js/components/table-submit/table-submit.component.min.js +1 -1
- package/assets/js/components/table-submit/table-submit.component.min.js.map +1 -1
- package/assets/js/components/tabs/tabs.component.min.js +2 -2
- package/assets/js/components/video-card/video-card.component.min.js +4 -4
- package/assets/js/components/video-card/video-card.component.min.js.map +1 -1
- package/assets/js/components/word-count/word-count.component.min.js +1 -1
- package/assets/js/modules/applied-filters.js +78 -61
- package/assets/js/modules/card.module.js +6 -1
- package/assets/js/modules/dialogs.js +6 -2
- package/assets/js/modules/password.js +72 -0
- package/assets/js/modules/table.js +10 -6
- package/assets/js/scripts.bundle.js +2 -3
- package/assets/js/scripts.bundle.js.map +1 -1
- package/assets/js/scripts.bundle.min.js +2 -2
- package/assets/js/scripts.bundle.min.js.map +1 -1
- package/assets/js/scripts.js +0 -2
- package/assets/js/tests/helpers.spec.js +54 -1
- package/assets/sass/_components.scss +2 -0
- package/assets/sass/_elements.scss +2 -0
- package/assets/sass/components/actionbar.component.scss +1 -0
- package/assets/sass/components/address-lookup.component.scss +24 -0
- package/assets/sass/components/applied-filters.scss +10 -14
- package/assets/sass/components/input-range.component.scss +38 -0
- package/assets/sass/components/input.component.scss +102 -0
- package/assets/sass/components/modal.component.scss +269 -0
- package/assets/sass/components/multi-step-modal.component.scss +255 -0
- package/assets/sass/components/multi-step-modal.global.scss +92 -0
- package/assets/sass/components/multiselect.scss +2 -2
- package/assets/sass/components/password.component.scss +60 -0
- package/assets/sass/components/tabs.config.scss +2 -2
- package/assets/sass/elements/badge-tag.scss +0 -1
- package/assets/sass/elements/details.scss +12 -7
- package/assets/sass/elements/dialog.scss +46 -5
- package/assets/sass/elements/forms.scss +41 -177
- package/assets/sass/elements/hr.scss +1 -1
- package/assets/sass/elements/modal.scss +19 -21
- package/assets/sass/elements/prefix.scss +115 -0
- package/assets/ts/components/accordion/accordion.component.ts +1 -1
- package/assets/ts/components/actionbar/actionbar.component.ts +3 -10
- package/assets/ts/components/address-lookup/address-lookup.component.ts +60 -0
- package/assets/ts/components/applied-filters/applied-filters.component.ts +0 -2
- package/assets/ts/components/filter-card/filter-card.component.ts +27 -0
- package/assets/ts/components/input/input.component.ts +168 -0
- package/assets/ts/components/input-range/input-range.component.ts +78 -0
- package/assets/ts/components/modal/modal.component.ts +188 -0
- package/assets/ts/components/multi-step-modal/multi-step-modal.component.ts +304 -0
- package/assets/ts/components/multiselect/multiselect.component.ts +1 -1
- package/assets/ts/components/password/password.component.ts +118 -0
- package/assets/ts/components/search/search.component.ts +1 -1
- package/assets/ts/components/std-address-lookup/std-address-lookup.component.ts +5 -3
- package/assets/ts/modules/applied-filters.ts +107 -71
- package/assets/ts/modules/card.module.ts +9 -4
- package/assets/ts/modules/dialogs.ts +6 -2
- package/assets/ts/modules/password.ts +82 -0
- package/assets/ts/modules/table.ts +13 -6
- package/assets/ts/scripts.ts +2 -2
- package/assets/ts/tests/helpers.spec.ts +100 -1
- package/dist/components.es.js +641 -959
- package/dist/components.umd.js +281 -182
- package/package.json +2 -2
- package/src/components/Input/Input.vue +19 -363
- package/src/components/InputRange/InputRange.vue +22 -0
- package/src/components/Modal/Modal.vue +22 -0
- package/src/components/MultiStepModal/MultiStepModal.vue +23 -0
- package/src/components/{PasswordIndicator/PasswordIndicator.vue → Password/Password.vue} +23 -23
- package/assets/js/components/password-indicator/password-indicator.component.js +0 -19
- package/assets/js/components/password-indicator/password-indicator.component.min.js +0 -7
- package/assets/js/components/password-indicator/password-indicator.component.min.js.map +0 -1
- package/assets/js/modules/form.js +0 -125
- package/assets/js/modules/inputs.js +0 -151
- package/assets/js/modules/password-indicator.js +0 -21
- package/assets/ts/components/password-indicator/password-indicator.component.ts +0 -24
- package/assets/ts/modules/form.ts +0 -166
- package/assets/ts/modules/inputs.ts +0 -181
- package/assets/ts/modules/password-indicator.ts +0 -29
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { trackComponent, trackComponentRegistered } from '../_global';
|
|
2
|
+
import { cardHTML, setupCard } from '../../modules/card.module';
|
|
3
|
+
import iamMenu from '../menu/menu.component';
|
|
4
|
+
import Modal from '../../../../src/components/Modal/Modal.vue';
|
|
5
|
+
|
|
6
|
+
trackComponentRegistered('iam-card');
|
|
7
|
+
|
|
8
|
+
class iamModal extends HTMLElement {
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
this.attachShadow({ mode: 'open' });
|
|
12
|
+
|
|
13
|
+
const assetLocation = document.body.hasAttribute('data-assets-location')
|
|
14
|
+
? document.body.getAttribute('data-assets-location')
|
|
15
|
+
: '/assets';
|
|
16
|
+
const loadCSS = `@import "${assetLocation}/css/components/modal.component.css";`;
|
|
17
|
+
|
|
18
|
+
const template = document.createElement('template');
|
|
19
|
+
template.innerHTML = `
|
|
20
|
+
<style>
|
|
21
|
+
${this.hasAttribute('css') ? `@import "${this.getAttribute('css')}";` : ``}
|
|
22
|
+
|
|
23
|
+
${loadCSS}
|
|
24
|
+
</style>
|
|
25
|
+
<link rel="stylesheet" href="https://kit.fontawesome.com/26fdbf0179.css" crossorigin="anonymous" />
|
|
26
|
+
<dialog>
|
|
27
|
+
<button class="btn btn-compact btn-secondary fa-xmark-large" data-close>Close</button>
|
|
28
|
+
<div class="scroll">
|
|
29
|
+
<i class="fa-light fa-circle" aria-hidden="true">
|
|
30
|
+
<i class="fa-regular fa-${this.hasAttribute('data-icon') ? this.getAttribute('data-icon') : 'info'}" aria-hidden="true"></i>
|
|
31
|
+
</i>
|
|
32
|
+
<slot></slot>
|
|
33
|
+
<div class="btn-group">
|
|
34
|
+
<button class="btn btn-secondary" data-cancel>Cancel</button>
|
|
35
|
+
<slot name="agreed-button">
|
|
36
|
+
<button class="btn btn-primary" data-agreed>${this.hasAttribute('data-agreed-text') ? this.getAttribute('data-agreed-text') : 'Ok'}</button>
|
|
37
|
+
</slot>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</dialog>
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
connectedCallback(): void {
|
|
47
|
+
|
|
48
|
+
const originalDialog = this.querySelector('dialog');
|
|
49
|
+
|
|
50
|
+
const id = this.hasAttribute('id') ? this.getAttribute('id') : originalDialog?.getAttribute('id');
|
|
51
|
+
const dialog = this.shadowRoot?.querySelector('dialog');
|
|
52
|
+
const closeButton = this.shadowRoot?.querySelector('[data-close]');
|
|
53
|
+
const cancelButton = this.shadowRoot?.querySelector('[data-cancel]');
|
|
54
|
+
const agreedButton = this.shadowRoot?.querySelector('[data-agreed]');
|
|
55
|
+
const slottedAgreedButton = this.querySelector('button[slot="agreed-button"]');
|
|
56
|
+
const modalType = this.hasAttribute('data-type') ? this.getAttribute('data-type') : 'passive';
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
const openModal = () => {
|
|
62
|
+
dialog?.showModal();
|
|
63
|
+
dialog?.focus();
|
|
64
|
+
|
|
65
|
+
const closeEvent = new CustomEvent('modal-opened', {
|
|
66
|
+
bubbles: true,
|
|
67
|
+
cancelable: true,
|
|
68
|
+
detail: { modalId: id },
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
this.dispatchEvent(closeEvent);
|
|
72
|
+
|
|
73
|
+
window.dataLayer = window.dataLayer || [];
|
|
74
|
+
window.dataLayer.push({
|
|
75
|
+
event: 'openModal',
|
|
76
|
+
id: id,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
document.addEventListener('click', (e) => {
|
|
81
|
+
|
|
82
|
+
if(e.target.matches(`[command="show-modal"][commandfor="${id}"]`) || e.target.matches(`[data-modal="${id}"]`)){
|
|
83
|
+
openModal();
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Disable the original event
|
|
88
|
+
originalDialog?.addEventListener('command', (e) => {
|
|
89
|
+
|
|
90
|
+
if (event.command == "show-modal") {
|
|
91
|
+
e.preventDefault();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
originalDialog?.addEventListener('command', (e) => {
|
|
96
|
+
|
|
97
|
+
if (event.command == "close") {
|
|
98
|
+
closeModal();
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
originalDialog?.addEventListener('close', (e) => {
|
|
103
|
+
|
|
104
|
+
closeModal();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Move the submit button so that the slot functionality works
|
|
108
|
+
Array.from(originalDialog?.querySelectorAll('[slot]')).forEach((element) => {
|
|
109
|
+
this.moveBefore(element, originalDialog);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const closeModal = () => {
|
|
113
|
+
dialog?.close();
|
|
114
|
+
|
|
115
|
+
const closeEvent = new CustomEvent('modal-closed', {
|
|
116
|
+
bubbles: true,
|
|
117
|
+
cancelable: true,
|
|
118
|
+
detail: { modalId: id },
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
this.dispatchEvent(closeEvent);
|
|
122
|
+
|
|
123
|
+
window.dataLayer = window.dataLayer || [];
|
|
124
|
+
window.dataLayer.push({
|
|
125
|
+
event: 'closeModal',
|
|
126
|
+
id: id,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
closeButton?.addEventListener('click', () => {
|
|
131
|
+
closeModal();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
cancelButton?.addEventListener('click', () => {
|
|
135
|
+
closeModal();
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
agreedButton?.addEventListener('click', () => {
|
|
139
|
+
|
|
140
|
+
const agreedEvent = new CustomEvent('agreed', {
|
|
141
|
+
detail: { modalId: id },
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
this.dispatchEvent(agreedEvent);
|
|
145
|
+
|
|
146
|
+
closeModal();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
slottedAgreedButton?.addEventListener('click', () => {
|
|
150
|
+
|
|
151
|
+
const agreedEvent = new CustomEvent('agreed', {
|
|
152
|
+
detail: { modalId: id },
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
this.dispatchEvent(agreedEvent);
|
|
156
|
+
|
|
157
|
+
closeModal();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
this.addEventListener('close-modal', () => {
|
|
161
|
+
closeModal();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
this.addEventListener('click', (event) => {
|
|
165
|
+
|
|
166
|
+
// Small fix to make sure the dialog isn't a dialog inside of a dialog.
|
|
167
|
+
const style = window.getComputedStyle(dialog);
|
|
168
|
+
if (style.display === 'contents') dialog = dialog.parentNode.closest('dialog[open]');
|
|
169
|
+
|
|
170
|
+
// Dont allow the backdrop to be clicked when transactional
|
|
171
|
+
if (modalType != 'transactional' && modalType != 'acknowledgement') {
|
|
172
|
+
const dialogDimensions = dialog.getBoundingClientRect();
|
|
173
|
+
|
|
174
|
+
if (
|
|
175
|
+
event.clientX < dialogDimensions.left ||
|
|
176
|
+
event.clientX > dialogDimensions.right ||
|
|
177
|
+
event.clientY < dialogDimensions.top ||
|
|
178
|
+
event.clientY > dialogDimensions.bottom
|
|
179
|
+
) {
|
|
180
|
+
if (!event.target.closest('dialog *'))
|
|
181
|
+
closeModal(); // Weird bug when interacting with radio input fields within dialogs cuases it to close
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export default iamModal;
|
|
@@ -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;
|
|
@@ -35,7 +35,7 @@ class iamMultiselect extends HTMLElement {
|
|
|
35
35
|
<div class="admin-panel dropdown" part="dropdown">
|
|
36
36
|
<slot></slot>
|
|
37
37
|
</div>
|
|
38
|
-
<button id="clear"><span class="visually-hidden">Clear</span></button>
|
|
38
|
+
<button id="clear" class="btn btn-action "><span class="visually-hidden">Clear</span></button>
|
|
39
39
|
</div>
|
|
40
40
|
</div>
|
|
41
41
|
</label>
|
|
@@ -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;
|
|
@@ -1554,6 +1554,8 @@ class iamSTDAddressLookup extends HTMLElement {
|
|
|
1554
1554
|
data-url="/standardaddress.json?search_query="
|
|
1555
1555
|
data-postcode="true"
|
|
1556
1556
|
data-min-chars="5"
|
|
1557
|
+
data-title="Find an address by postcode"
|
|
1558
|
+
data-placeholder="UK, Isle of Man, & Channel Islands "
|
|
1557
1559
|
${this.hasAttribute('data-manual') ? 'data-manual' : ''}
|
|
1558
1560
|
${this.hasAttribute('data-allow-manual') ? 'data-allow-manual' : ''}
|
|
1559
1561
|
${this.hasAttribute('data-use') ? `data-use='${this.getAttribute('data-use')}'` : ''}
|
|
@@ -1564,6 +1566,8 @@ class iamSTDAddressLookup extends HTMLElement {
|
|
|
1564
1566
|
${this.hasAttribute('data-error-msg') ? `data-error-msg='${this.getAttribute('data-error-msg')}'` : ''}
|
|
1565
1567
|
${this.hasAttribute('data-use-default') ? `data-use-default` : ''}
|
|
1566
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')}'` : ''}
|
|
1567
1571
|
data-postcode-lookup-label="Back to UK postcode lookup">
|
|
1568
1572
|
|
|
1569
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>
|
|
@@ -1600,7 +1604,7 @@ class iamSTDAddressLookup extends HTMLElement {
|
|
|
1600
1604
|
<option></option>
|
|
1601
1605
|
${countiesString}
|
|
1602
1606
|
</select></label>
|
|
1603
|
-
<label>Postcode${this.hasAttribute('data-show-required') ? '*' : ''} <input name="postcode" type="text" data-required data-readonly maxlength="8" ${this.hasAttribute('data-required') ? ' required' : ''}/></label>
|
|
1607
|
+
<label>Postcode${this.hasAttribute('data-show-required') ? '*' : ''} <input name="postcode" type="text" required data-required data-readonly maxlength="8" ${this.hasAttribute('data-required') ? ' required' : ''}/></label>
|
|
1604
1608
|
<label>Country${this.hasAttribute('data-show-required') && this.hasAttribute('data-country-required') ? '*' : (!this.hasAttribute('data-show-required') && !this.hasAttribute('data-county-required') ? ' (optional)' : '')}
|
|
1605
1609
|
<select name="region" data-readonly ${this.hasAttribute('data-country-required') ? 'data-required' : ''}>
|
|
1606
1610
|
<option value=""></option>
|
|
@@ -1749,8 +1753,6 @@ class iamSTDAddressLookup extends HTMLElement {
|
|
|
1749
1753
|
}
|
|
1750
1754
|
});
|
|
1751
1755
|
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
1756
|
}
|
|
1755
1757
|
}
|
|
1756
1758
|
|