@iamproperty/components 5.1.0-beta → 5.1.0-beta11

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 (118) hide show
  1. package/assets/css/components/accordion.global.css.map +1 -1
  2. package/assets/css/components/card.css +1 -1
  3. package/assets/css/components/card.css.map +1 -1
  4. package/assets/css/components/carousel.css +1 -1
  5. package/assets/css/components/carousel.css.map +1 -1
  6. package/assets/css/components/component.native.css +1 -1
  7. package/assets/css/components/component.native.css.map +1 -1
  8. package/assets/css/components/component.reset.css +1 -1
  9. package/assets/css/components/component.reset.css.map +1 -1
  10. package/assets/css/components/fileupload.css +1 -1
  11. package/assets/css/components/fileupload.css.map +1 -1
  12. package/assets/css/components/header.css +1 -1
  13. package/assets/css/components/header.css.map +1 -1
  14. package/assets/css/components/marketing.css +1 -0
  15. package/assets/css/components/marketing.css.map +1 -0
  16. package/assets/css/components/nav.css +1 -1
  17. package/assets/css/components/nav.css.map +1 -1
  18. package/assets/css/components/nav.global.css +1 -1
  19. package/assets/css/components/nav.global.css.map +1 -1
  20. package/assets/css/components/pagination.css +1 -1
  21. package/assets/css/components/pagination.css.map +1 -1
  22. package/assets/css/components/slider.css.map +1 -1
  23. package/assets/css/core.min.css +1 -1
  24. package/assets/css/core.min.css.map +1 -1
  25. package/assets/css/style.min.css +1 -1
  26. package/assets/css/style.min.css.map +1 -1
  27. package/assets/img/signin-bg.png +0 -0
  28. package/assets/js/components/accordion/accordion.component.min.js +1 -1
  29. package/assets/js/components/actionbar/actionbar.component.min.js +1 -1
  30. package/assets/js/components/address-lookup/address-lookup.component.js +17 -3
  31. package/assets/js/components/address-lookup/address-lookup.component.min.js +4 -4
  32. package/assets/js/components/address-lookup/address-lookup.component.min.js.map +1 -1
  33. package/assets/js/components/applied-filters/applied-filters.component.min.js +1 -1
  34. package/assets/js/components/card/card.component.js +2 -1
  35. package/assets/js/components/card/card.component.min.js +4 -3
  36. package/assets/js/components/card/card.component.min.js.map +1 -1
  37. package/assets/js/components/carousel/carousel.component.js +61 -0
  38. package/assets/js/components/collapsible-side/collapsible-side.component.min.js +1 -1
  39. package/assets/js/components/fileupload/fileupload.component.min.js +2 -2
  40. package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
  41. package/assets/js/components/header/header.component.js +6 -12
  42. package/assets/js/components/header/header.component.min.js +8 -14
  43. package/assets/js/components/header/header.component.min.js.map +1 -1
  44. package/assets/js/components/marketing/marketing.component.js +37 -0
  45. package/assets/js/components/nav/nav.component.js +4 -36
  46. package/assets/js/components/nav/nav.component.min.js +10 -13
  47. package/assets/js/components/nav/nav.component.min.js.map +1 -1
  48. package/assets/js/components/notification/notification.component.min.js +1 -1
  49. package/assets/js/components/pagination/pagination.component.min.js +2 -2
  50. package/assets/js/components/search/search.component.js +148 -0
  51. package/assets/js/components/search/search.component.min.js +14 -0
  52. package/assets/js/components/search/search.component.min.js.map +1 -0
  53. package/assets/js/components/table/table.component.min.js +5 -5
  54. package/assets/js/components/table/table.component.min.js.map +1 -1
  55. package/assets/js/components/tabs/tabs.component.min.js +1 -1
  56. package/assets/js/dynamic.js +1 -1
  57. package/assets/js/dynamic.min.js +5 -4
  58. package/assets/js/dynamic.min.js.map +1 -1
  59. package/assets/js/modules/carousel.js +15 -23
  60. package/assets/js/modules/dynamicEvents.js +28 -13
  61. package/assets/js/modules/helpers.js +8 -1
  62. package/assets/js/modules/inputs.js +57 -0
  63. package/assets/js/modules/table.js +8 -6
  64. package/assets/js/scripts.bundle.js +39 -43
  65. package/assets/js/scripts.bundle.js.map +1 -1
  66. package/assets/js/scripts.bundle.min.js +2 -2
  67. package/assets/js/scripts.bundle.min.js.map +1 -1
  68. package/assets/js/vendor/hibp.js +78 -0
  69. package/assets/sass/_corefiles.scss +1 -0
  70. package/assets/sass/_elements.scss +1 -1
  71. package/assets/sass/_functions/mixins.scss +16 -0
  72. package/assets/sass/_functions/utilities.scss +0 -17
  73. package/assets/sass/_functions/variables.scss +1 -0
  74. package/assets/sass/components/card.scss +23 -3
  75. package/assets/sass/components/carousel.scss +86 -159
  76. package/assets/sass/components/component.native.scss +86 -3
  77. package/assets/sass/components/fileupload.scss +1 -1
  78. package/assets/sass/components/header.scss +53 -55
  79. package/assets/sass/components/marketing.scss +64 -0
  80. package/assets/sass/components/nav.global.scss +2 -1
  81. package/assets/sass/components/nav.scss +7 -1
  82. package/assets/sass/components/pagination.scss +4 -0
  83. package/assets/sass/elements/admin-panel.scss +9 -7
  84. package/assets/sass/elements/badge.scss +29 -0
  85. package/assets/sass/elements/dialog.scss +4 -4
  86. package/assets/sass/elements/forms.scss +23 -4
  87. package/assets/sass/elements/links.scss +2 -1
  88. package/assets/sass/foundations/reboot.scss +12 -13
  89. package/assets/sass/foundations/root.scss +11 -3
  90. package/assets/sass/helpers/max-height.scss +78 -4
  91. package/assets/sass/templates/auth.scss +112 -0
  92. package/assets/ts/components/address-lookup/address-lookup.component.ts +23 -4
  93. package/assets/ts/components/card/card.component.ts +2 -1
  94. package/assets/ts/components/carousel/README.md +39 -0
  95. package/assets/ts/components/carousel/carousel.component.ts +75 -0
  96. package/assets/ts/components/header/header.component.ts +6 -12
  97. package/assets/ts/components/marketing/marketing.component.ts +49 -0
  98. package/assets/ts/components/nav/README.md +2 -13
  99. package/assets/ts/components/nav/nav.component.ts +4 -47
  100. package/assets/ts/components/search/search.component.ts +177 -0
  101. package/assets/ts/dynamic.ts +1 -1
  102. package/assets/ts/modules/carousel.ts +21 -33
  103. package/assets/ts/modules/dynamicEvents.ts +44 -24
  104. package/assets/ts/modules/helpers.ts +13 -2
  105. package/assets/ts/modules/inputs.ts +79 -0
  106. package/assets/ts/modules/table.ts +11 -14
  107. package/assets/ts/vendor/hibp.ts +81 -0
  108. package/dist/components.es.js +744 -949
  109. package/dist/components.umd.js +107 -101
  110. package/dist/style.css +1 -1
  111. package/package.json +1 -1
  112. package/src/components/Carousel/Carousel.vue +18 -103
  113. package/src/components/Header/Header.vue +1 -3
  114. package/src/components/Marketing/Marketing.vue +39 -0
  115. package/src/components/Marketing/README.md +20 -0
  116. package/src/components/Nav/README.md +1 -12
  117. package/src/components/Search/Search.vue +25 -0
  118. package/src/components/Carousel/Carousel.spec.js +0 -45
@@ -1,33 +1,32 @@
1
1
  // @ts-nocheck
2
- function carousel(carouselElement) {
2
+ function carousel(carouselElement, row) {
3
3
 
4
4
  var scrollTimeout;
5
5
 
6
6
  let carouselInner = carouselElement.querySelector('.carousel__inner');
7
- let itemCount = carouselElement.querySelectorAll('.carousel__item').length;
8
- let cols = carouselElement.getAttribute('data-cols');
9
- let smCols = carouselElement.getAttribute('data-sm-cols');
10
- let mdCols = carouselElement.getAttribute('data-md-cols');
11
-
12
- carouselElement.querySelector('.carousel__controls a').setAttribute('aria-current', true);
7
+ let carouselControls = carouselElement.querySelector('.carousel__controls');
8
+ let itemCount = row.querySelectorAll('.col').length;
13
9
 
14
10
  // On scroll we need to make sure the buttons get corrected and the next testimonial is shown
15
11
  carouselInner.addEventListener('scroll', function(e){
16
12
  clearTimeout(scrollTimeout);
17
- scrollTimeout = setTimeout(function(){
13
+ scrollTimeout = setTimeout(function(){
18
14
 
19
15
  let scrollArea = carouselInner.clientWidth;
20
16
  let scrollWidth = carouselInner.scrollWidth;
21
17
  let scrollLeft = carouselInner.scrollLeft;
22
18
  let targetSlide = Math.round((scrollLeft / scrollWidth) * itemCount) + 1;
23
- let lastItemOffset = carouselElement.querySelector('.carousel__item:last-child').offsetLeft;
19
+ let lastItemOffset = row.querySelector('.col:last-child').offsetLeft + 50;
20
+
21
+ if(carouselInner.scrollLeft + scrollArea >= lastItemOffset)
22
+ targetSlide = itemCount;
24
23
 
25
- Array.from(carouselElement.querySelectorAll('.carousel__controls a')).forEach((link, index) => {
26
- link.removeAttribute('aria-current');
24
+ Array.from(carouselElement.querySelectorAll('.carousel__controls button')).forEach((button, index) => {
25
+ button.removeAttribute('aria-current');
27
26
  });
28
27
 
29
28
  carouselElement.querySelector('.control-'+targetSlide).setAttribute('aria-current', true);
30
-
29
+
31
30
  // Disable the previous button
32
31
  if(targetSlide == 1)
33
32
  carouselElement.querySelector('.btn-prev').setAttribute('disabled','disabled');
@@ -35,29 +34,29 @@ function carousel(carouselElement) {
35
34
  carouselElement.querySelector('.btn-prev').removeAttribute('disabled');
36
35
 
37
36
  // Disable the next button if the last item is in view
38
- if(carouselInner.scrollLeft + scrollArea > lastItemOffset)
37
+ if(targetSlide == itemCount)
39
38
  carouselElement.querySelector('.btn-next').setAttribute('disabled','disabled');
40
39
  else
41
40
  carouselElement.querySelector('.btn-next').removeAttribute('disabled');
42
-
41
+
43
42
  }, 100);
44
43
 
45
44
  }, false);
46
45
 
47
46
  // when the buttons are used we need to make sure the carousel scrolls to the correct place
48
- carouselElement.addEventListener('click', function(e){
47
+ carouselControls.addEventListener('click', function(e){
49
48
 
50
49
  for (var target = e.target; target && target != this; target = target.parentNode) {
51
- if (target.matches('.carousel__controls a')) {
50
+ if (typeof target.matches == "function" && target.matches('button')) {
52
51
 
53
52
  e.preventDefault();
54
53
 
55
- Array.from(carouselElement.querySelectorAll('.carousel__controls a')).forEach((link, index) => {
56
- link.removeAttribute('aria-current');
54
+ Array.from(carouselControls.querySelectorAll('button')).forEach((button, index) => {
55
+ button.removeAttribute('aria-current');
57
56
  });
58
57
  target.setAttribute('aria-current', true);
59
-
60
- const el = document.querySelector(target.getAttribute('href'));
58
+
59
+ const el = row.querySelector(`*:nth-child(${target.getAttribute('data-slide')})`);
61
60
 
62
61
  carouselInner.scroll({
63
62
  top: 0,
@@ -69,11 +68,11 @@ function carousel(carouselElement) {
69
68
  }
70
69
  }
71
70
  }, false);
72
-
71
+
73
72
  carouselElement.addEventListener('click', function(e){
74
73
 
75
74
  for (var target = e.target; target && target != this; target = target.parentNode) {
76
- if (target.matches('.btn-next, .btn-prev')) {
75
+ if (typeof target.matches == "function" && target.matches('.btn-next, .btn-prev')) {
77
76
 
78
77
  e.preventDefault();
79
78
  let scrollTo = target.classList.contains('btn-prev') ? carouselInner.scrollLeft - carouselInner.clientWidth : carouselInner.scrollLeft + carouselInner.clientWidth;
@@ -87,17 +86,6 @@ function carousel(carouselElement) {
87
86
  }
88
87
  }
89
88
  }, false);
90
-
91
-
92
- // Add responsive hide button classes
93
- if(itemCount == 1)
94
- carouselElement.classList.add('hide-btns');
95
-
96
- if(smCols >= itemCount)
97
- carouselElement.classList.add('hide-sm-btns');
98
-
99
- if(mdCols >= itemCount)
100
- carouselElement.classList.add('hide-md-btns');
101
89
  }
102
90
 
103
91
  export default carousel
@@ -77,43 +77,63 @@ const runEvent = (element,event,eventType) => {
77
77
  switch (event[eventType]){
78
78
  case "hide":
79
79
 
80
- let hideElement = document.querySelector(event['target'])
81
- hideElement.classList.add('js-hide');
82
-
83
- Array.from(hideElement.querySelectorAll('[data-required]')).forEach((input, index) => {
84
-
85
- input.removeAttribute('required');
86
- });
80
+ if(document.querySelector(event['target'])){
81
+
82
+ let hideElement = document.querySelector(event['target']);
83
+ hideElement.classList.add('js-hide');
84
+
85
+ Array.from(hideElement.querySelectorAll('[data-required]')).forEach((input, index) => {
86
+
87
+ input.removeAttribute('required');
88
+ });
89
+ }
87
90
  break;
88
91
  case "show":
89
92
 
90
- let showElement = document.querySelector(event['target'])
91
- showElement.classList.remove('js-hide');
92
-
93
- Array.from(showElement.querySelectorAll('[data-required]')).forEach((input, index) => {
94
-
95
- if(!input.closest('.js-hide'))
96
- input.setAttribute('required','true');
97
- });
93
+ if(document.querySelector(event['target'])){
94
+
95
+ let showElement = document.querySelector(event['target']);
96
+ showElement.classList.remove('js-hide');
97
+
98
+ Array.from(showElement.querySelectorAll('[data-required]')).forEach((input, index) => {
99
+
100
+ if(!input.closest('.js-hide'))
101
+ input.setAttribute('required','true');
102
+ });
103
+ }
104
+ break;
105
+ case "populate-form":
106
+ populateForm(element,event);
107
+ break;
108
+ case "dispatchEvent":
109
+ let theEvent = new Event(event['value']);
110
+ document.querySelector(`${event['target']}`).dispatchEvent(theEvent);
98
111
  break;
99
- case "populate-form":
100
- populateForm(element,event);
101
- break;
102
- case "dispatchEvent":
103
- let theEvent = new Event(event['value']);
104
- document.querySelector(`${event['target']}`).dispatchEvent(theEvent);
105
- break;
106
112
  case "setAttribute":
107
- document.querySelector(`${event['target']}`).setAttribute(event['attribute'],event['value']);
113
+
114
+ Array.from(document.querySelectorAll(`${event['target']}`)).forEach(function(element,index){
115
+ element.setAttribute(event['attribute'],event['value']);
116
+ });
108
117
  break;
109
118
  case "removeAttribute":
110
- document.querySelector(`${event['target']}`).removeAttribute(event['attribute']);
119
+ Array.from(document.querySelectorAll(`${event['target']}`)).forEach(function(element,index){
120
+ element.removeAttribute(event['attribute']);
121
+ });
111
122
  break;
112
123
  case "updateValue":
113
124
  document.querySelector(`${event['target']}`).value = event['value'] ? event['value'] : "";
114
125
 
115
126
  let changeEvent = new Event('change');
116
127
  document.querySelector(`${event['target']}`).dispatchEvent(changeEvent);
128
+ break;
129
+ case "submitForm":
130
+ document.querySelector(`${event['target']}`).submit();
131
+ break;
132
+ case "openLink":
133
+
134
+ if(document.querySelector(`${event['target']}`).value)
135
+ window.location.href = document.querySelector(`${event['target']}`).value;
136
+
117
137
  break;
118
138
  default:
119
139
  break;
@@ -66,7 +66,12 @@ export const addGlobalEvents = (body) => {
66
66
 
67
67
  let form = event.target;
68
68
 
69
- if(form.querySelector(':invalid')){
69
+ // Reset password types
70
+ Array.from(form.querySelectorAll('[data-password-type]')).forEach((input,index) => {
71
+ input.setAttribute('type','password');
72
+ });
73
+
74
+ if(form.querySelector(':invalid') || form.querySelector('.pwd-checker[data-strength="1"]') || form.querySelector('.pwd-checker[data-strength="2"]')){
70
75
 
71
76
  form.classList.add('was-validated');
72
77
  event.preventDefault();
@@ -97,4 +102,10 @@ export const safeID = function(str){
97
102
  str = str.replace(/\W/g,'');
98
103
 
99
104
  return str;
100
- }
105
+ }
106
+
107
+ // Used to get values from nested json objects
108
+ export const resolvePath = (object, path, defaultValue) => path.split(/[\.\[\]\'\"]/).filter(p => p).reduce((o, p) => o ? o[p] : defaultValue, object);
109
+
110
+
111
+ export const isTraversable = o => Array.isArray(o) || o !== null && ['function', 'object'].includes(typeof o);
@@ -1,4 +1,6 @@
1
1
  // @ts-nocheck
2
+ import hibpCheck from '../vendor/hibp'
3
+
2
4
  const extendInputs = (body) => {
3
5
 
4
6
  function loadInput(){
@@ -79,6 +81,10 @@ const extendInputs = (body) => {
79
81
 
80
82
  if(input.hasAttribute('maxlength') && input.nextElementSibling)
81
83
  input.nextElementSibling.setAttribute("data-count", input.value.length);
84
+
85
+
86
+ if(input.hasAttribute('data-strength-checker'))
87
+ checkPWDStrength(input);
82
88
  }
83
89
  });
84
90
 
@@ -151,7 +157,80 @@ export const setMaxlengthVars = (input) => {
151
157
 
152
158
  export const changeType = (input,type) => {
153
159
 
160
+ if(input.hasAttribute('type') && input.getAttribute('type') == 'password')
161
+ input.setAttribute('data-password-type',true);
162
+
154
163
  input.setAttribute('type',type);
155
164
  }
156
165
 
166
+ export const checkPWDStrength = (input, check = 'no') => {
167
+
168
+ const pwdChecker = document.getElementById(input.getAttribute('data-strength-checker'))
169
+ const password = input.value;
170
+ const minChars = input.hasAttribute('minlength') ? input.getAttribute('minlength') : 12;
171
+
172
+ let strength = 1;
173
+ let strengthName = ['Very weak', 'Weak', 'Average', 'Strong', 'Very strong'];
174
+ let extraMsg = '';
175
+
176
+ //has number
177
+ if (password.match(/(?=.*[0-9])/))
178
+ strength += 1;
179
+ // has special character
180
+ if (password.match(/(?=.*[!,%,&,#,$,^,*,?,_,~,<,>,])/))
181
+ strength += 1;
182
+ // has lowercase alpha
183
+ if (password.match(/(?=.*[a-z])/))
184
+ strength += 1;
185
+ // has uppercase alpha
186
+ if (password.match(/(?=.*[A-Z])/))
187
+ strength += 1;
188
+
189
+ if (password.length < minChars){
190
+ strength = 1;
191
+ extraMsg = `(must be at least ${minChars} characters.)`;
192
+ }
193
+
194
+
195
+ // 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
196
+
197
+ if(strength >= 3 && check == 'no'){
198
+ hibpCheck(password,input);
199
+
200
+
201
+ input.addEventListener('hibpCheck', function (event) {
202
+ checkhibpCheck(event, input)
203
+ });
204
+
205
+ function checkhibpCheck(event, input){
206
+
207
+ if(event.detail){ // found
208
+ checkPWDStrength(input,'danger');
209
+ } else { // not found
210
+ checkPWDStrength(input,'success');
211
+ }
212
+
213
+ input.removeEventListener("hibpCheck", checkhibpCheck); // Succeeds
214
+ }
215
+
216
+ }
217
+ else if(strength >= 3 && check == 'danger'){
218
+ strength = 3;
219
+ extraMsg = `(this password is very common)`;
220
+ }
221
+
222
+
223
+ if(pwdChecker){
224
+ if(strength <= 3)
225
+ pwdChecker.classList.add('invalid-feedback');
226
+ else
227
+ pwdChecker.classList.remove('invalid-feedback');
228
+
229
+ pwdChecker.setAttribute('data-strength',strength)
230
+ pwdChecker.innerHTML = `Password strength: ${strengthName[strength-1]} ${extraMsg}`;
231
+ }
232
+
233
+ }
234
+
235
+
157
236
  export default extendInputs;
@@ -1,5 +1,5 @@
1
1
  // @ts-nocheck
2
- import { zeroPad, isNumeric, ucfirst } from "./helpers";
2
+ import { zeroPad, isNumeric, ucfirst, resolvePath } from "./helpers";
3
3
 
4
4
  // Basic functionality needed
5
5
  export const addDataAttributes = (table) => {
@@ -61,20 +61,20 @@ export const getLargestLastColWidth = (table) => {
61
61
 
62
62
  export const createMobileButton = (table, wrapper) => {
63
63
 
64
-
65
- if(wrapper.classList.contains('.table--fullwidth') && !wrapper.hasAttribute('data-expandable'))
64
+ if(wrapper.classList.contains('table--fullwidth') && !wrapper.hasAttribute('data-expandable'))
66
65
  return false;
67
66
 
68
67
  if(table.querySelectorAll('thead tr th').length < 4 && !wrapper.hasAttribute('data-expandable'))
69
68
  return false;
70
69
 
71
-
70
+ //If the expand column already exists we don't need to add a new one.
72
71
  Array.from(table.querySelectorAll('thead tr')).forEach((row,index) => {
73
-
74
- row.insertAdjacentHTML(
75
- 'afterbegin',
76
- `<th class="th--fixed expand-button-heading"></th>`
77
- );
72
+ if(!table.querySelectorAll('thead tr th.expand-button-heading').length){
73
+ row.insertAdjacentHTML(
74
+ 'afterbegin',
75
+ `<th class="th--fixed expand-button-heading"></th>`
76
+ );
77
+ }
78
78
  });
79
79
 
80
80
  Array.from(table.querySelectorAll('tbody tr')).forEach((row,index) => {
@@ -690,7 +690,7 @@ export const populateDataQueries = (table,form,wrapper) => {
690
690
  dataQueries.forEach((queryElement, index) => {
691
691
 
692
692
  let query = queryElement.getAttribute('data-query');
693
- let numberOfMatchedRows: 0;
693
+ let numberOfMatchedRows = 0;
694
694
 
695
695
  if(query == 'total'){
696
696
  if(wrapper.hasAttribute('data-total'))
@@ -903,11 +903,9 @@ const filterFilters = function(form){
903
903
 
904
904
  export const loadAjaxTable = async function (table, form, pagination, wrapper){
905
905
 
906
- const resolvePath = (object, path, defaultValue) => path.split(/[\.\[\]\'\"]/).filter(p => p).reduce((o, p) => o ? o[p] : defaultValue, object);
907
-
908
906
  let formData = new FormData(form);
909
907
  let queryString = new URLSearchParams(formData).toString();
910
- let columns = table.querySelectorAll('thead tr th');
908
+ let columns = table.querySelectorAll('thead tr th:not(.expand-button-heading)');
911
909
  let tbody = table.querySelector('tbody');
912
910
  let ajaxURL = form.getAttribute('data-ajax');
913
911
 
@@ -985,7 +983,6 @@ export const loadAjaxTable = async function (table, form, pagination, wrapper){
985
983
  var table_row = document.createElement('tr');
986
984
 
987
985
  columns.forEach((col, index) => {
988
-
989
986
  let cellOutput = '';
990
987
  var table_cell = document.createElement('td');
991
988
  // Add some data to help with the mobile layout design
@@ -0,0 +1,81 @@
1
+ // @ts-nocheck
2
+
3
+ /**
4
+ * hibp.js
5
+ * @version v1
6
+ * @author Mehdi Bounya
7
+ *
8
+ * Report any bugs here: https://github.com/mehdibo/hibp-js
9
+ *
10
+ * The MIT License (http://www.opensource.org/licenses/mit-license.php)
11
+ *
12
+ * Permission is hereby granted, free of charge, to any person
13
+ * obtaining a copy of this software and associated documentation
14
+ * files (the "Software"), to deal in the Software without
15
+ * restriction, including without limitation the rights to use,
16
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ * copies of the Software, and to permit persons to whom the
18
+ * Software is furnished to do so, subject to the following
19
+ * conditions:
20
+ *
21
+ * The above copyright notice and this permission notice shall be
22
+ * included in all copies or substantial portions of the Software.
23
+ *
24
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
26
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
28
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
29
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31
+ * OTHER DEALINGS IN THE SOFTWARE.
32
+ */
33
+ function sha1(string){
34
+ var buffer = new TextEncoder("utf-8").encode(string);
35
+ return crypto.subtle.digest("SHA-1", buffer).then(function (buffer) {
36
+ // Get the hex code
37
+ var hexCodes = [];
38
+ var view = new DataView(buffer);
39
+ for (var i = 0; i < view.byteLength; i += 4) {
40
+ // Using getUint32 reduces the number of iterations needed (we process 4 bytes each time)
41
+ var value = view.getUint32(i)
42
+ // toString(16) will give the hex representation of the number without padding
43
+ var stringValue = value.toString(16)
44
+ // We use concatenation and slice for padding
45
+ var padding = '00000000'
46
+ var paddedValue = (padding + stringValue).slice(-padding.length)
47
+ hexCodes.push(paddedValue);
48
+ }
49
+ // Join all the hex strings into one
50
+ return hexCodes.join("");
51
+ });
52
+ }
53
+
54
+ const hibpCheck = (pwd,input) => {
55
+ // We hash the pwd first
56
+ sha1(pwd).then(function(hash){
57
+ // We send the first 5 chars of the hash to hibp's API
58
+ const req = new XMLHttpRequest();
59
+ req.addEventListener("load", function(){
60
+ // When we get back a response from the server
61
+ // We create an array of lines and loop through them
62
+ const resp = this.responseText.split('\n');
63
+ const hashSub = hash.slice(5).toUpperCase();
64
+ var result = false;
65
+ for(let index in resp){
66
+ // Check if the line matches the rest of the hash
67
+ if(resp[index].substring(0, 35) == hashSub){
68
+ result = true;
69
+ break; // If found no need to continue the loop
70
+ }
71
+ }
72
+ // Trigger an event with the result
73
+ const event = new CustomEvent('hibpCheck', {detail: result});
74
+ input.dispatchEvent(event);
75
+ });
76
+ req.open('GET', 'https://api.pwnedpasswords.com/range/'+hash.substr(0, 5));
77
+ req.send();
78
+ });
79
+ }
80
+
81
+ export default hibpCheck;