@iamproperty/components 5.5.1-beta-1 → 5.5.1-beta-4

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 (124) hide show
  1. package/assets/css/components/actionbar.css +1 -1
  2. package/assets/css/components/actionbar.css.map +1 -1
  3. package/assets/css/components/applied-filters.css +1 -1
  4. package/assets/css/components/applied-filters.css.map +1 -1
  5. package/assets/css/components/card.css +1 -1
  6. package/assets/css/components/card.css.map +1 -1
  7. package/assets/css/components/card.global.css +1 -1
  8. package/assets/css/components/card.global.css.map +1 -1
  9. package/assets/css/components/charts.css +1 -1
  10. package/assets/css/components/charts.css.map +1 -1
  11. package/assets/css/components/fileupload.css.map +1 -1
  12. package/assets/css/components/inline-edit.css +1 -0
  13. package/assets/css/components/inline-edit.css.map +1 -0
  14. package/assets/css/components/inline-edit.preload.css +1 -0
  15. package/assets/css/components/inline-edit.preload.css.map +1 -0
  16. package/assets/css/components/multiselect.css +1 -0
  17. package/assets/css/components/multiselect.css.map +1 -0
  18. package/assets/css/components/multiselect.preload.css +1 -0
  19. package/assets/css/components/multiselect.preload.css.map +1 -0
  20. package/assets/css/components/nav.css.map +1 -1
  21. package/assets/css/components/nav.global.css +1 -1
  22. package/assets/css/components/nav.global.css.map +1 -1
  23. package/assets/css/components/slider.css.map +1 -1
  24. package/assets/css/components/tabs.css +1 -1
  25. package/assets/css/components/tabs.css.map +1 -1
  26. package/assets/css/core.min.css +1 -1
  27. package/assets/css/core.min.css.map +1 -1
  28. package/assets/css/style.min.css +1 -1
  29. package/assets/css/style.min.css.map +1 -1
  30. package/assets/js/components/accordion/accordion.component.min.js +1 -1
  31. package/assets/js/components/actionbar/actionbar.component.js +12 -3
  32. package/assets/js/components/actionbar/actionbar.component.min.js +6 -6
  33. package/assets/js/components/actionbar/actionbar.component.min.js.map +1 -1
  34. package/assets/js/components/address-lookup/address-lookup.component.min.js +1 -1
  35. package/assets/js/components/applied-filters/applied-filters.component.min.js +6 -6
  36. package/assets/js/components/applied-filters/applied-filters.component.min.js.map +1 -1
  37. package/assets/js/components/card/card.component.min.js +3 -3
  38. package/assets/js/components/chart/chart.component.js +71 -0
  39. package/assets/js/components/collapsible-side/collapsible-side.component.min.js +1 -1
  40. package/assets/js/components/fileupload/fileupload.component.js +1 -1
  41. package/assets/js/components/fileupload/fileupload.component.min.js +5 -5
  42. package/assets/js/components/fileupload/fileupload.component.min.js.map +1 -1
  43. package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
  44. package/assets/js/components/header/header.component.min.js +1 -1
  45. package/assets/js/components/inline-edit/inline-edit.component.js +148 -0
  46. package/assets/js/components/inline-edit/inline-edit.component.min.js +22 -0
  47. package/assets/js/components/inline-edit/inline-edit.component.min.js.map +1 -0
  48. package/assets/js/components/multiselect/multiselect.component.js +221 -0
  49. package/assets/js/components/multiselect/multiselect.component.min.js +25 -0
  50. package/assets/js/components/multiselect/multiselect.component.min.js.map +1 -0
  51. package/assets/js/components/nav/nav.component.min.js +2 -2
  52. package/assets/js/components/notification/notification.component.min.js +1 -1
  53. package/assets/js/components/pagination/pagination.component.min.js +1 -1
  54. package/assets/js/components/search/search.component.min.js +1 -1
  55. package/assets/js/components/search/search.component.min.js.map +1 -1
  56. package/assets/js/components/table/table.component.js +2 -2
  57. package/assets/js/components/table/table.component.min.js +6 -6
  58. package/assets/js/components/table/table.component.min.js.map +1 -1
  59. package/assets/js/components/tabs/tabs.component.min.js +2 -2
  60. package/assets/js/dynamic.min.js +5 -5
  61. package/assets/js/dynamic.min.js.map +1 -1
  62. package/assets/js/modules/applied-filters.js +39 -7
  63. package/assets/js/modules/chart.js +613 -111
  64. package/assets/js/modules/fileupload.js +11 -0
  65. package/assets/js/modules/helpers.js +20 -0
  66. package/assets/js/modules/inputs.js +6 -2
  67. package/assets/js/modules/table.js +62 -11
  68. package/assets/js/scripts.bundle.js +31 -31
  69. package/assets/js/scripts.bundle.js.map +1 -1
  70. package/assets/js/scripts.bundle.min.js +2 -2
  71. package/assets/js/scripts.bundle.min.js.map +1 -1
  72. package/assets/sass/_components.scss +5 -0
  73. package/assets/sass/_elements.scss +1 -1
  74. package/assets/sass/_functions/variables.scss +80 -0
  75. package/assets/sass/_utilities.scss +1 -0
  76. package/assets/sass/components/actionbar.scss +16 -0
  77. package/assets/sass/components/applied-filters.scss +6 -48
  78. package/assets/sass/components/card.global.scss +4 -0
  79. package/assets/sass/components/card.scss +1 -1
  80. package/assets/sass/components/charts.scss +981 -234
  81. package/assets/sass/components/inline-edit.preload.scss +98 -0
  82. package/assets/sass/components/inline-edit.scss +32 -0
  83. package/assets/sass/components/multiselect.preload.scss +37 -0
  84. package/assets/sass/components/multiselect.scss +186 -0
  85. package/assets/sass/components/nav.global.scss +2 -0
  86. package/assets/sass/components/tabs.scss +10 -1
  87. package/assets/sass/elements/admin-panel.scss +0 -3
  88. package/assets/sass/elements/badge-tag.scss +92 -0
  89. package/assets/sass/elements/buttons.scss +13 -1
  90. package/assets/sass/elements/details.scss +94 -5
  91. package/assets/sass/elements/dialog.scss +2 -0
  92. package/assets/sass/elements/forms.scss +42 -25
  93. package/assets/sass/elements/tooltips.scss +4 -3
  94. package/assets/sass/foundations/root.scss +11 -0
  95. package/assets/sass/helpers/wider-colours.scss +11 -0
  96. package/assets/ts/components/actionbar/actionbar.component.ts +14 -3
  97. package/assets/ts/components/chart/README.md +37 -0
  98. package/assets/ts/components/chart/chart.component.ts +98 -0
  99. package/assets/ts/components/fileupload/fileupload.component.ts +1 -1
  100. package/assets/ts/components/inline-edit/README.md +30 -0
  101. package/assets/ts/components/inline-edit/inline-edit.component.ts +211 -0
  102. package/assets/ts/components/multiselect/README.md +35 -0
  103. package/assets/ts/components/multiselect/multiselect.component.ts +304 -0
  104. package/assets/ts/components/search/README.md +36 -0
  105. package/assets/ts/components/table/table.component.ts +2 -2
  106. package/assets/ts/modules/applied-filters.ts +61 -7
  107. package/assets/ts/modules/chart.ts +808 -119
  108. package/assets/ts/modules/fileupload.ts +19 -0
  109. package/assets/ts/modules/helpers.ts +29 -1
  110. package/assets/ts/modules/inputs.ts +8 -2
  111. package/assets/ts/modules/table.ts +86 -12
  112. package/dist/components.es.js +348 -329
  113. package/dist/components.umd.js +59 -63
  114. package/dist/style.css +1 -1
  115. package/package.json +1 -1
  116. package/src/components/AppliedFilters/AppliedFilters.vue +1 -1
  117. package/src/components/Chart/Chart.vue +26 -96
  118. package/src/components/InlineEdit/InlineEdit.vue +45 -0
  119. package/src/components/InlineEdit/README.md +7 -0
  120. package/src/components/Multiselect/Multiselect.vue +24 -0
  121. package/src/components/Multiselect/README.md +12 -0
  122. package/src/components/Search/README.md +11 -0
  123. package/src/components/Search/Search.vue +1 -1
  124. package/assets/sass/elements/badge.scss +0 -29
@@ -0,0 +1,211 @@
1
+ // @ts-nocheck
2
+
3
+ // Data layer Web component created
4
+ window.dataLayer = window.dataLayer || [];
5
+ window.dataLayer.push({
6
+ "event": "customElementRegistered",
7
+ "element": "inline edit"
8
+ });
9
+
10
+ class iamInlineEdit extends HTMLElement {
11
+
12
+ constructor(){
13
+ super();
14
+ const shadowRoot = this.attachShadow({ mode: 'open'});
15
+
16
+ const assetLocation = document.body.hasAttribute('data-assets-location') ? document.body.getAttribute('data-assets-location') : '/assets';
17
+ const coreCSS = document.body.hasAttribute('data-core-css') ? document.body.getAttribute('data-core-css') : `${assetLocation}/css/core.min.css`;
18
+ const loadCSS = `@import "${assetLocation}/css/components/inline-edit.css";`;
19
+
20
+ const template = document.createElement('template');
21
+ template.innerHTML = `
22
+ <style class="styles">
23
+ @import "${coreCSS}";
24
+ ${loadCSS}
25
+ </style>
26
+ <link rel="stylesheet" href="https://kit.fontawesome.com/26fdbf0179.css" crossorigin="anonymous">
27
+
28
+ <slot></slot>
29
+ <div class="btns">
30
+ <button class="btn btn-action" id="save"><i class="fa-regular fa-save m-0"></i> Save</button><button class="btn btn-action" id="cancel">Cancel</button>
31
+ </div>
32
+ <div class="status pe-none">
33
+ <span class="btn btn-action border-0 bg-transparent prevent-invert d-none" id="saving"><i class="fa-regular fa-spinner fa-spin me-1"></i> Saving...</span>
34
+ <span class="btn btn-action border-0 bg-transparent prevent-invert d-none" id="saved"><i class="fa-regular fa-check me-1"></i> Saved</span>
35
+ <span class="btn btn-action border-0 bg-transparent prevent-invert d-none" id="notsaved"><i class="fa-regular fa-circle-info me-1"></i> Not Saved</span>
36
+ </div>
37
+ `;
38
+
39
+ shadowRoot.appendChild(template.content.cloneNode(true));
40
+ }
41
+
42
+ connectedCallback() {
43
+
44
+ let inlineEdit = this;
45
+ let saveButton = this.shadowRoot.querySelector('#save');
46
+ let cancelButton = this.shadowRoot.querySelector('#cancel');
47
+
48
+ let label = this.querySelector('label');
49
+ let input = this.querySelector('input, textarea, select');
50
+
51
+ let statusSaving = this.shadowRoot.querySelector('#saving');
52
+ let statusSaved = this.shadowRoot.querySelector('#saved');
53
+ let statusNotSaved = this.shadowRoot.querySelector('#notsaved');
54
+
55
+ // Save the original value for later
56
+ let originalValue = input.value;
57
+
58
+ // cancel
59
+ cancelButton.addEventListener('click', (event) => {
60
+
61
+
62
+ console.log(originalValue)
63
+
64
+ input.value = originalValue;
65
+
66
+
67
+ input.blur();
68
+ inlineEdit.blur();
69
+
70
+ inlineEdit.classList.remove('was-validated');
71
+ statusNotSaved.classList.add('d-none');
72
+
73
+ const cancelEvent = new CustomEvent("inline-edit-cancel", { detail: { name: input.getAttribute('name')} });
74
+ inlineEdit.dispatchEvent(cancelEvent);
75
+ });
76
+
77
+ // Save
78
+ saveButton.addEventListener('click', (event) => {
79
+
80
+ if(inlineEdit.querySelector(':invalid')){
81
+
82
+ inlineEdit.classList.add('was-validated');
83
+
84
+ return false;
85
+ }
86
+
87
+ originalValue = input.value;
88
+
89
+ // dispatch save event
90
+ const saveEvent = new CustomEvent("inline-edit-save", { detail: { name: input.getAttribute('name'), value: input.value } });
91
+ inlineEdit.dispatchEvent(saveEvent);
92
+
93
+ //inlineEdit.setAttribute('data-saving','true');
94
+ input.disabled = true;
95
+
96
+ input.blur();
97
+ inlineEdit.blur();
98
+
99
+
100
+ statusSaving.classList.remove('d-none');
101
+ });
102
+
103
+ // Save
104
+ if(input.tagName === 'input'){
105
+ input.addEventListener('keydown', (event) => {
106
+
107
+ switch (event.key) { // change to event.key to key to use the above variable
108
+ case "Enter":
109
+
110
+ event.stopPropagation();
111
+ event.preventDefault();
112
+
113
+ saveButton.click();
114
+
115
+ break;
116
+ }
117
+ });
118
+ }
119
+
120
+ // Saved
121
+ inlineEdit.addEventListener('inline-edit-saved', (event) => {
122
+
123
+ setTimeout(() => {
124
+
125
+ statusSaving.classList.add('d-none');
126
+ statusSaved.classList.remove('d-none');
127
+
128
+ const confirmEvent = new CustomEvent("inline-edit-confirmed", { detail: { name: input.getAttribute('name') } });
129
+ inlineEdit.dispatchEvent(confirmEvent);
130
+ }, 100);
131
+
132
+ // Reset to normal
133
+ setTimeout(() => {
134
+
135
+ input.disabled = false;
136
+ inlineEdit.removeAttribute('data-saving');
137
+
138
+ statusSaving.classList.add('d-none');
139
+ statusSaved.classList.add('d-none');
140
+ statusNotSaved.classList.add('d-none');
141
+ }, 1000);
142
+ });
143
+
144
+ // enter key saves
145
+ if(input.tagName === 'SELECT'){
146
+
147
+ input.addEventListener('change',(event) => {
148
+
149
+ originalValue = input.value;
150
+
151
+ const saveEvent = new CustomEvent("inline-edit-save", { detail: { name: input.getAttribute('name'), value: input.value } });
152
+ inlineEdit.dispatchEvent(saveEvent);
153
+
154
+ inlineEdit.setAttribute('data-saving','true');
155
+ input.disabled = true;
156
+
157
+ input.blur();
158
+ });
159
+ }
160
+
161
+ if(input.tagName != 'SELECT'){
162
+ input.addEventListener('focus',(event) => {
163
+
164
+ input.select();
165
+ });
166
+ }
167
+
168
+ //blur it should autosave
169
+ inlineEdit.addEventListener('blur',(event) => {
170
+
171
+ if(input.value != originalValue){
172
+
173
+ let feedbackText = '(Unsaved)';
174
+
175
+ if(inlineEdit.hasAttribute('data-autosave')) {
176
+
177
+ originalValue = input.value;
178
+
179
+ const saveEvent = new CustomEvent("inline-edit-autosave", { detail: { name: input.getAttribute('name'), value: input.value } });
180
+ inlineEdit.dispatchEvent(saveEvent);
181
+
182
+ statusSaving.classList.remove('d-none');
183
+ }
184
+ else if(!inlineEdit.querySelector('.inline-feedback')){
185
+ statusNotSaved.classList.remove('d-none');
186
+ }
187
+ }
188
+ });
189
+
190
+ // checkboxes
191
+ inlineEdit.addEventListener('change', (event) => {
192
+ if (event && event.target instanceof HTMLElement && event.target.closest('input[type="checkbox"]')){
193
+
194
+ let saveValue = "";
195
+
196
+ Array.from(inlineEdit.querySelectorAll(`label input[type="checkbox"]:checked`)).forEach((checkbox, index) => {
197
+
198
+ if(index != 0)
199
+ saveValue += ", ";
200
+
201
+ saveValue += checkbox.value;
202
+ });
203
+
204
+ const saveEvent = new CustomEvent("inline-edit-save", { detail: { name: event.target.closest('input[type="checkbox"]').getAttribute('name'), value: saveValue } });
205
+ inlineEdit.dispatchEvent(saveEvent);
206
+ }
207
+ });
208
+ }
209
+ }
210
+
211
+ export default iamInlineEdit;
@@ -0,0 +1,35 @@
1
+ **Add the below to your initialise script**
2
+
3
+ ```
4
+ import('../node_modules/@iamproperty/components/assets/js/components/fileupload/fileupload.component.min').then(module => { // Might need to update the path
5
+
6
+ if (!window.customElements.get(`iam-fileupload`))
7
+ window.customElements.define(`iam-fileupload`, module.default);
8
+
9
+ }).catch((err) => {
10
+ console.log(err.message);
11
+ });
12
+ ```
13
+
14
+ **Add the below HTML code to where you want the component to live.**
15
+
16
+ ```
17
+ <iam-multiselect>
18
+ <span class="label" slot="label">Users</span>
19
+ <label class="tag"><input type="checkbox" name="tags" value="IT James Lambert" />James Lambert</label>
20
+ <label class="tag"><input type="checkbox" name="tags" value="IT Amanda Knight"/>Amanda Knight</label>
21
+ <label class="tag"><input type="checkbox" name="tags" value="IT Brian Lord"/>Brian Lord</label>
22
+ <label class="tag"><input type="checkbox" name="tags" value="Claire Lane"/>Claire Lane</label>
23
+ <label class="tag"><input type="checkbox" name="tags" value="John Smith"/>John Smith</label>
24
+ <label class="tag"><input type="checkbox" name="tags" value="James Brown"/>James Brown</label>
25
+ <label class="tag"><input type="checkbox" name="tags" value="Sarah Brown"/>Sarah Brown</label>
26
+ </iam-multiselect>
27
+ ```
28
+
29
+ **Properties**
30
+
31
+ | Option | Type | Default Value | Description |
32
+ | ------ | ---- | ------------- | ----------- |
33
+ | data-min | Int | - | Set's the minimum amout of tags needed for the input field to validate |
34
+ | data-min | Int | - | Set's the maximum amout of tags allowed to be added |
35
+ | data-is-required | flag | - | Makes it so at least one tag must be added for the it to be valid and allow the outer form to be sumitted |
@@ -0,0 +1,304 @@
1
+ // @ts-nocheck
2
+
3
+ // Data layer Web component created
4
+ window.dataLayer = window.dataLayer || [];
5
+ window.dataLayer.push({
6
+ "event": "customElementRegistered",
7
+ "element": "mutliselect"
8
+ });
9
+
10
+ class iamMultiselect extends HTMLElement {
11
+
12
+ constructor(){
13
+ super();
14
+ this.attachShadow({ mode: 'open'});
15
+
16
+ const assetLocation = document.body.hasAttribute('data-assets-location') ? document.body.getAttribute('data-assets-location') : '/assets'
17
+ const coreCSS = document.body.hasAttribute('data-core-css') ? document.body.getAttribute('data-core-css') : `${assetLocation}/css/core.min.css`;
18
+ const loadCSS = `@import "${assetLocation}/css/components/multiselect.css";`;
19
+
20
+ const template = document.createElement('template');
21
+ template.innerHTML = `
22
+ <style>
23
+ @import "${coreCSS}";
24
+ ${loadCSS}
25
+ ${this.hasAttribute('css') ? `@import "${this.getAttribute('css')}";` : ``}
26
+ </style>
27
+ <label for="search"> <slot name="feedback"></slot></label>
28
+ <div class="outer">
29
+ <div class="wrapper">
30
+
31
+ <slot name="checked"></slot>
32
+ <input name="search" id="search" autocomplete="off" required />
33
+ <span class="admin-panel feedback">This field is required</span>
34
+ <div class="admin-panel dropdown">
35
+ <slot></slot>
36
+ </div>
37
+ <button id="clear"><span class="visually-hidden">Clear</span></button>
38
+ </div>
39
+ </div>
40
+ `;
41
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
42
+ }
43
+
44
+ connectedCallback() {
45
+
46
+ let multiselect = this;
47
+ let form = this.closest('form');
48
+ let wrapper = this.shadowRoot.querySelector('.wrapper');
49
+ let search = multiselect.shadowRoot.querySelector('#search');
50
+ let button = multiselect.shadowRoot.querySelector('#clear');
51
+ let order = 0;
52
+ let label = multiselect.shadowRoot.querySelector('label');
53
+
54
+
55
+ label.innerHTML = multiselect.getAttribute('data-label');
56
+
57
+ if(multiselect.hasAttribute('placeholder')){
58
+
59
+ search.setAttribute('placeholder', multiselect.getAttribute('placeholder'));
60
+ }
61
+
62
+ multiselect.setAttribute('data-error','true');
63
+
64
+ // If in form and is required lets watch for the form being submitted
65
+ if(form && multiselect.hasAttribute('data-is-required')){
66
+
67
+ let observer = new MutationObserver(function(mutations) {
68
+ mutations.forEach(function(mutationRecord) {
69
+ const targetElement = mutationRecord.target as HTMLElement;
70
+
71
+ console.log(targetElement);
72
+
73
+ if (targetElement.classList.contains("was-validated")) {
74
+ wrapper.classList.add('was-validated');
75
+ } else {
76
+ wrapper.classList.remove('was-validated');
77
+ };
78
+ })
79
+ });
80
+
81
+ if (form.classList.contains("was-validated")) {
82
+ wrapper.classList.add('was-validated');
83
+ } else {
84
+ wrapper.classList.remove('was-validated');
85
+ };
86
+
87
+ observer.observe(form, {
88
+ attributes : true,
89
+ attributeFilter : ['style', 'class']
90
+ });
91
+ }
92
+
93
+ // Set the correct attributes
94
+ function setItem(inputToSet){
95
+
96
+ if(inputToSet.checked == false){
97
+
98
+ inputToSet.closest('label').removeAttribute('slot');
99
+ inputToSet.closest('label').removeAttribute('style');
100
+ inputToSet.closest('label').removeAttribute('data-order');
101
+ }
102
+ else {
103
+
104
+ order++;
105
+
106
+ inputToSet.closest('label').setAttribute('slot','checked');
107
+ inputToSet.closest('label').setAttribute('style',`--order:${order};`);
108
+ inputToSet.closest('label').setAttribute('data-order',order);
109
+ }
110
+
111
+ // check for errors
112
+ if(multiselect.querySelector('label[slot="checked"]')){
113
+ wrapper.classList.add('filled');
114
+ multiselect.removeAttribute('data-error');
115
+
116
+ search.removeAttribute('placeholder');
117
+ }
118
+ else {
119
+ wrapper.classList.remove('filled');
120
+ multiselect.setAttribute('data-error','true');
121
+
122
+ if(multiselect.hasAttribute('placeholder')){
123
+
124
+ search.setAttribute('placeholder', multiselect.getAttribute('placeholder'));
125
+ }
126
+ }
127
+
128
+
129
+ }
130
+
131
+ // Set on load
132
+ Array.from(multiselect.querySelectorAll(`label input[type="checkbox"]:checked`)).forEach((checkbox, index) => {
133
+
134
+ setItem(checkbox);
135
+ });
136
+
137
+
138
+ // Filter list
139
+ search.addEventListener('input', (event) => {
140
+
141
+ Array.from(multiselect.querySelectorAll(`label:not([slot="checked"])`)).forEach((label, index) => {
142
+
143
+ let checkbox = label.querySelector('input');
144
+ let searchValue = checkbox.value;
145
+
146
+ if(searchValue.toLowerCase().includes(search.value.toLowerCase())){
147
+ label.removeAttribute('slot')
148
+ }
149
+ else {
150
+ label.setAttribute('slot','notmatched');
151
+ }
152
+ });
153
+ });
154
+
155
+ // Set items
156
+ multiselect.addEventListener('change', (event) => {
157
+
158
+ if (event && event.target instanceof HTMLElement && event.target.closest('input[type="checkbox"]')){
159
+ let checkbox = event.target.closest('input[type="checkbox"]');
160
+
161
+ setItem(checkbox);
162
+
163
+ search.focus();
164
+ }
165
+ });
166
+
167
+ // Clear all
168
+ button.addEventListener("click", function(event) {
169
+
170
+ Array.from(multiselect.querySelectorAll(`label input[type="checkbox"]`)).forEach((checkbox, index) => {
171
+
172
+ checkbox.checked = false;
173
+
174
+ setItem(checkbox);
175
+ });
176
+
177
+ search.focus();
178
+ });
179
+
180
+ // Add some keyboard features to keep it accessible
181
+ multiselect.addEventListener("keydown", function(event) {
182
+
183
+ const activeElement = document.activeElement;
184
+
185
+ switch (event.key) { // change to event.key to key to use the above variable
186
+ case "ArrowUp":
187
+ // Up pressed
188
+ event.preventDefault();
189
+
190
+ if(activeElement.hasAttribute('type') && activeElement.getAttribute('type') == "checkbox"){
191
+
192
+ let arrCheckboxes = multiselect.querySelectorAll(`label:not([slot="checked"]):not([slot="checked"])`);
193
+
194
+ let activeIndex = Array.from(arrCheckboxes).indexOf(activeElement.closest('label'));
195
+ let prevCheckbox = Array.from(arrCheckboxes)[activeIndex-1];
196
+
197
+ if(prevCheckbox)
198
+ prevCheckbox.focus();
199
+ else
200
+ search.focus();
201
+ }
202
+
203
+ break;
204
+ case "ArrowDown":
205
+ // Down pressed
206
+ event.preventDefault();
207
+
208
+ if(activeElement == multiselect){
209
+
210
+ multiselect.querySelector('label:not([slot="checked"]):not([slot="checked"])').focus();
211
+ }
212
+ else if(activeElement.hasAttribute('type') && activeElement.getAttribute('type') == "checkbox"){
213
+
214
+ let activeValue = activeElement.value;
215
+
216
+ let nextCheckbox = multiselect.querySelector(`label:has(input[value="${activeValue}"]) ~ label:not([slot="checked"]):not([slot="checked"])`);
217
+
218
+ if(nextCheckbox)
219
+ nextCheckbox.focus();
220
+ }
221
+
222
+ break;
223
+ case "Enter":
224
+
225
+ event.stopPropagation();
226
+ event.preventDefault();
227
+
228
+ if(activeElement.hasAttribute('type') && activeElement.getAttribute('type') == "checkbox"){
229
+
230
+ if(activeElement.checked == false)
231
+ activeElement.checked = true;
232
+ else
233
+ activeElement.checked = false;
234
+ }
235
+
236
+ setItem(activeElement);
237
+ search.focus();
238
+
239
+ break;
240
+ }
241
+ });
242
+
243
+ function checkLastTag(){
244
+
245
+ if(order == 0)
246
+ return false;
247
+
248
+ let lastTag = multiselect.querySelector(`label[data-order="${order}"]`);
249
+
250
+ if(!lastTag){
251
+ lastTag = checkLastTag(order--);
252
+ }
253
+
254
+ return lastTag;
255
+ }
256
+
257
+ search.addEventListener("keydown", function(event) {
258
+
259
+ switch (event.key) { // change to event.key to key to use the above variable
260
+ case "Enter":
261
+
262
+ let match = multiselect.querySelector(`input[value="${search.value}"]:not(:checked)`);
263
+
264
+ if(!match)
265
+ search.value = "";
266
+
267
+ search.focus();
268
+
269
+ break;
270
+ case "Backspace":
271
+
272
+ if(!search.value){
273
+
274
+ let lastTag = checkLastTag(order);
275
+
276
+ if(lastTag){
277
+
278
+ let lastTagInput = lastTag.querySelector('input');
279
+ lastTagInput.checked = false;
280
+ setItem(lastTagInput);
281
+ }
282
+
283
+ search.focus();
284
+ }
285
+
286
+ break;
287
+ }
288
+ });
289
+
290
+
291
+ // Fix for the inline edit multiselect
292
+ multiselect.addEventListener("mousedown", (event) => {
293
+
294
+ wrapper.setAttribute('data-mousedown','true');
295
+ });
296
+
297
+ multiselect.addEventListener("mouseup", (event) => {
298
+
299
+ wrapper.removeAttribute('data-mousedown');
300
+ });
301
+ }
302
+ }
303
+
304
+ export default iamMultiselect;
@@ -0,0 +1,36 @@
1
+ **Add the below to your initialise script**
2
+
3
+ ```
4
+ import('../node_modules/@iamproperty/components/assets/js/components/fileupload/fileupload.component.min').then(module => { // Might need to update the path
5
+
6
+ if (!window.customElements.get(`iam-fileupload`))
7
+ window.customElements.define(`iam-fileupload`, module.default);
8
+
9
+ }).catch((err) => {
10
+ console.log(err.message);
11
+ });
12
+ ```
13
+
14
+ **Add the below HTML code to where you want the component to live.**
15
+
16
+ ```
17
+ <iam-search>
18
+ <label>Search existing transactions
19
+ <span>
20
+ <input type="text" name="client" autocomplete="off" aria-autocomplete="none" required />
21
+ <span class="suffix fa-regular fa-search"></span>
22
+ </span>
23
+ </label>
24
+ <datalist id="properties"></datalist>
25
+ </iam-search>
26
+ ```
27
+
28
+ **Properties**
29
+
30
+ | Option | Type | Default Value | Description |
31
+ | ------ | ---- | ------------- | ----------- |
32
+ | data-url | String | - | Optional value that populates the datalist with extra results from an API |
33
+ | data-schema | String | - | Tells the JavaScript where to look for the array of values in the API JSON |
34
+ | data-value-schema | String | - | Tells the JavaScript where to look for the value within the API JSON |
35
+ | data-display-schema | String | - | Tells the JavaScript where to look for the title within the API JSON |
36
+
@@ -122,10 +122,10 @@ class iamTable extends HTMLElement {
122
122
  tableModule.createSearchDataList(this.table, this.form);
123
123
 
124
124
  if(!this.form.querySelector('[data-pagination]')){
125
- this.form.innerHTML += `<input name="page" type="hidden" value="${this.getAttribute('data-page')}" data-pagination="true" />`
125
+ this.form.insertAdjacentHTML('beforeend',`<input name="page" type="hidden" value="${this.getAttribute('data-page')}" data-pagination="true" />`);
126
126
  }
127
127
  if(!this.form.querySelector('[data-show]')){
128
- this.form.innerHTML += `<input name="show" type="hidden" value="${this.getAttribute('data-show')}" data-show="true" />`
128
+ this.form.insertAdjacentHTML('beforeend',`<input name="show" type="hidden" value="${this.getAttribute('data-show')}" data-show="true" />`);
129
129
  }
130
130
 
131
131
  // Event listeners