@iamproperty/components 3.8.0 → 4.0.0

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 (99) hide show
  1. package/assets/css/components/actionbar-global.css +1 -0
  2. package/assets/css/components/actionbar-global.css.map +1 -0
  3. package/assets/css/components/actionbar.css +1 -0
  4. package/assets/css/components/actionbar.css.map +1 -0
  5. package/assets/css/components/collapsible-side.css +1 -0
  6. package/assets/css/components/collapsible-side.css.map +1 -0
  7. package/assets/css/components/dialog.css +1 -1
  8. package/assets/css/components/dialog.css.map +1 -1
  9. package/assets/css/components/forms.css +1 -1
  10. package/assets/css/components/forms.css.map +1 -1
  11. package/assets/css/components/header.css +1 -1
  12. package/assets/css/components/header.css.map +1 -1
  13. package/assets/css/components/lists.css.map +1 -1
  14. package/assets/css/components/nav-global.css +1 -0
  15. package/assets/css/components/nav-global.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.docs.css +1 -0
  19. package/assets/css/components/nav.docs.css.map +1 -0
  20. package/assets/css/components/nav.old.css +1 -0
  21. package/assets/css/components/nav.old.css.map +1 -0
  22. package/assets/css/components/pagination.css.map +1 -1
  23. package/assets/css/components/property-searchbar.css +1 -1
  24. package/assets/css/components/property-searchbar.css.map +1 -1
  25. package/assets/css/components/table.css +1 -1
  26. package/assets/css/components/table.css.map +1 -1
  27. package/assets/css/core.min.css +1 -1
  28. package/assets/css/core.min.css.map +1 -1
  29. package/assets/css/style.min.css +1 -1
  30. package/assets/css/style.min.css.map +1 -1
  31. package/assets/js/components/accordion/accordion.component.min.js +2 -2
  32. package/assets/js/components/actionbar/actionbar.component.js +305 -0
  33. package/assets/js/components/actionbar/actionbar.component.min.js +53 -0
  34. package/assets/js/components/actionbar/actionbar.component.min.js.map +1 -0
  35. package/assets/js/components/applied-filters/applied-filters.component.min.js +1 -1
  36. package/assets/js/components/card/card.component.min.js +1 -1
  37. package/assets/js/components/collapsible-side/collapsible-side.component.js +96 -0
  38. package/assets/js/components/collapsible-side/collapsible-side.component.min.js +27 -0
  39. package/assets/js/components/collapsible-side/collapsible-side.component.min.js.map +1 -0
  40. package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
  41. package/assets/js/components/header/header.component.min.js +2 -2
  42. package/assets/js/components/nav/nav.component.js +294 -0
  43. package/assets/js/components/nav/nav.component.min.js +51 -0
  44. package/assets/js/components/nav/nav.component.min.js.map +1 -0
  45. package/assets/js/components/notification/notification.component.min.js +1 -1
  46. package/assets/js/components/pagination/pagination.component.min.js +1 -1
  47. package/assets/js/components/table/table.component.js +33 -0
  48. package/assets/js/components/table/table.component.min.js +12 -11
  49. package/assets/js/components/table/table.component.min.js.map +1 -1
  50. package/assets/js/components/tabs/tabs.component.min.js +1 -1
  51. package/assets/js/dynamic.min.js +3 -3
  52. package/assets/js/dynamic.min.js.map +1 -1
  53. package/assets/js/modules/dialogs.js +3 -0
  54. package/assets/js/modules/helpers.js +0 -13
  55. package/assets/js/modules/table.js +1 -1
  56. package/assets/js/scripts.bundle.js +15 -14
  57. package/assets/js/scripts.bundle.js.map +1 -1
  58. package/assets/js/scripts.bundle.min.js +2 -2
  59. package/assets/js/scripts.bundle.min.js.map +1 -1
  60. package/assets/sass/_corefiles.scss +2 -0
  61. package/assets/sass/_functions/mixins.scss +25 -0
  62. package/assets/sass/_functions/variables.scss +1 -1
  63. package/assets/sass/components/actionbar-global.scss +89 -0
  64. package/assets/sass/components/actionbar.scss +254 -0
  65. package/assets/sass/components/collapsible-side.scss +327 -0
  66. package/assets/sass/components/dialog.scss +10 -0
  67. package/assets/sass/components/forms.scss +29 -0
  68. package/assets/sass/components/nav-global.scss +630 -0
  69. package/assets/sass/components/nav.docs.scss +54 -0
  70. package/assets/sass/components/nav.old.scss +965 -0
  71. package/assets/sass/components/nav.scss +450 -782
  72. package/assets/sass/components/table.scss +9 -1
  73. package/assets/sass/foundations/buttons.scss +57 -32
  74. package/assets/sass/foundations/links.scss +1 -1
  75. package/assets/sass/foundations/reboot.scss +5 -3
  76. package/assets/ts/components/actionbar/README.md +55 -0
  77. package/assets/ts/components/actionbar/actionbar.component.ts +396 -0
  78. package/assets/ts/components/collapsible-side/README.md +38 -0
  79. package/assets/ts/components/collapsible-side/collapsible-side.component.ts +134 -0
  80. package/assets/ts/components/nav/README.md +68 -0
  81. package/assets/ts/components/nav/nav.component.ts +370 -0
  82. package/assets/ts/components/table/table.component.ts +65 -0
  83. package/assets/ts/modules/dialogs.ts +6 -0
  84. package/assets/ts/modules/helpers.ts +0 -17
  85. package/assets/ts/modules/table.ts +5 -5
  86. package/dist/components.es.js +1368 -1113
  87. package/dist/components.umd.js +188 -44
  88. package/dist/style.css +1 -1
  89. package/package.json +1 -1
  90. package/src/components/Actionbar/Actionbar.vue +20 -0
  91. package/src/components/Actionbar/README.md +40 -0
  92. package/src/components/CollapsibleSideMenu/CollapsibleSideMenu.vue +20 -0
  93. package/src/components/CollapsibleSideMenu/README.md +23 -0
  94. package/src/components/Nav/Nav.vue +20 -195
  95. package/src/components/Nav/README.md +43 -13
  96. package/src/components/Nav-old/Nav.vue +213 -0
  97. package/src/components/Nav-old/README.md +23 -0
  98. package/src/index.js +8 -0
  99. package/src/components/Nav/Nav.spec.js +0 -35
@@ -0,0 +1,38 @@
1
+ **Add the below to your initialise script**
2
+
3
+ ```
4
+ import('../node_modules/@iamproperty/components/assets/js/components/collapsible-side/collapsible-side.component.min').then(module => { // Might need to update the path
5
+
6
+ if (!window.customElements.get(`iam-collapsible-side`))
7
+ window.customElements.define(`iam-collapsible-side`, 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-collapsible-side data-title="Configuration">
18
+
19
+ <div slot="menu">
20
+ <label for="test1">Active branch</label>
21
+ <select class="form-select" name="test1" id="test1">
22
+ <option value="1" selected>Newcastle</option>
23
+ <option value="2">Two</option>
24
+ <option value="2">Three</option>
25
+ <option value="2">Four</option>
26
+ </select>
27
+ </div>
28
+
29
+ <hr slot="menu"/>
30
+ <a href="/" slot="menu">Agency settings</a>
31
+ <a href="/" slot="menu">Control panel</a>
32
+ <a href="/" slot="menu" class="selected">Contact us</a>
33
+
34
+ <h1>Inspections</h1>
35
+ <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
36
+
37
+ </iam-collapsible-side>
38
+ ```
@@ -0,0 +1,134 @@
1
+ // @ts-nocheck
2
+ // Data layer Web component created
3
+ window.dataLayer = window.dataLayer || [];
4
+ window.dataLayer.push({
5
+ "event": "customElementRegistered",
6
+ "element": "collapsible side menu"
7
+ });
8
+
9
+ class iamCollapsibleSideMenu extends HTMLElement {
10
+
11
+ constructor(){
12
+ super();
13
+ this.attachShadow({ mode: 'open'});
14
+
15
+ const assetLocation = document.body.hasAttribute('data-assets-location') ? document.body.getAttribute('data-assets-location') : '/assets'
16
+ const coreCSS = document.body.hasAttribute('data-core-css') ? document.body.getAttribute('data-core-css') : `${assetLocation}/css/core.min.css`;
17
+ const loadCSS = `@import "${assetLocation}/css/components/collapsible-side.css";`;
18
+
19
+ const template = document.createElement('template');
20
+ template.innerHTML = `
21
+ <style class="styles">
22
+ @import "${coreCSS}";
23
+ ${loadCSS}
24
+ ${this.hasAttribute('css') ? `@import "${this.getAttribute('css')}";` : ``}
25
+ </style>
26
+ <link rel="stylesheet" href="https://kit.fontawesome.com/26fdbf0179.css" crossorigin="anonymous">
27
+ <div class="container">
28
+
29
+ <div class="side-menu">
30
+ <button class="btn btn-compact fa-chevron-right btn-secondary btn-sm">Open or close Collapsible menu</button>
31
+ <div class="side-menu-content closed">
32
+ <slot name="menu"></slot>
33
+ </div>
34
+ </div>
35
+
36
+ <div class="main-content">
37
+ <slot></slot>
38
+ </div>
39
+
40
+ </div>
41
+ `;
42
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
43
+ }
44
+
45
+ connectedCallback() {
46
+
47
+ const sideMenu = this.shadowRoot.querySelector('.side-menu');
48
+ const sideMenuContent = this.shadowRoot.querySelector('.side-menu-content');
49
+ const mainContent = this.shadowRoot.querySelector('.main-content')
50
+ const button = this.shadowRoot.querySelector('.side-menu > .btn');
51
+
52
+ // Load external CSS if needed
53
+ if(this.hasAttribute('data-css'))
54
+ this.shadowRoot.querySelector('.styles').insertAdjacentHTML('beforeend', `@import "${this.getAttribute('data-css')}";`);
55
+
56
+ // Set sde nav title
57
+ if(!this.hasAttribute('data-title'))
58
+ this.setAttribute('data-title','configuration')
59
+
60
+ sideMenuContent.insertAdjacentHTML('afterbegin',`<span class="h3">${this.getAttribute('data-title')}</span>`);
61
+ mainContent.insertAdjacentHTML('afterbegin',`<span class="h3">${this.getAttribute('data-title')}</span>`);
62
+
63
+
64
+ if(this.querySelector(':scope > :is(h1,h2,h3,h4,h5,h6)')){
65
+ this.querySelector(':scope > :is(h1,h2,h3,h4,h5,h6)').classList.add('h4');
66
+ this.querySelector(':scope > :is(h1,h2,h3,h4,h5,h6)').classList.add('main-content__title');
67
+ }
68
+
69
+ // Open the menu
70
+ button.addEventListener('click', (event) => {
71
+
72
+
73
+ if(!sideMenu.classList.contains('open')){
74
+
75
+ sideMenuContent.classList.remove('closed');
76
+
77
+
78
+ setTimeout(function(){
79
+ sideMenu.classList.add('open');
80
+ }, 100);
81
+
82
+
83
+ }
84
+ else {
85
+
86
+ sideMenu.classList.remove('open');
87
+ setTimeout(function(){ sideMenuContent.classList.add('closed') }, 1000); // Delay until its close so the animation is broken
88
+
89
+ // While the menu is closing dont allow the hover to re-open it until its fully closed.
90
+ sideMenu.classList.add('pe-none');
91
+ setTimeout(function(){ sideMenu.classList.remove('pe-none')}, 1000);
92
+ }
93
+ });
94
+
95
+ // Mimic hover event on desktop so that we can control when classes are set and which order
96
+ sideMenu.addEventListener('mouseenter', (event) => {
97
+
98
+ if(window.innerWidth > 992){
99
+
100
+ if(!sideMenu.classList.contains('open'))
101
+ sideMenuContent.classList.remove('closed');
102
+
103
+ sideMenu.classList.add('hover');
104
+
105
+ }
106
+ });
107
+
108
+ sideMenu.addEventListener('mousemove', (event) => {
109
+
110
+ if(window.innerWidth > 992){
111
+
112
+ if(!sideMenu.classList.contains('open'))
113
+ sideMenuContent.classList.remove('closed');
114
+ }
115
+ });
116
+
117
+ sideMenu.addEventListener('mouseleave', (event) => {
118
+
119
+ if(window.innerWidth > 992){
120
+
121
+ sideMenu.classList.remove('hover');
122
+
123
+ if(!sideMenu.classList.contains('open'))
124
+ setTimeout(function(){ sideMenuContent.classList.add('closed') }, 1000); // Delay until its close so the animation is broken
125
+ }
126
+ });
127
+
128
+
129
+
130
+ }
131
+
132
+ }
133
+
134
+ export default iamCollapsibleSideMenu;
@@ -0,0 +1,68 @@
1
+ **Add the below to your initialise script**
2
+
3
+ ```
4
+ import('../node_modules/@iamproperty/components/assets/js/components/nav/nav.component.min').then(module => { // Might need to update the path
5
+
6
+ if (!window.customElements.get(`iam-nav`))
7
+ window.customElements.define(`iam-nav`, 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
+ <nav>
18
+ <iam-nav>
19
+ <a href="/" class="brand brand--property" slot="logo">
20
+ <svg>
21
+ <title>iamproperty</title>
22
+ <use xlink:href="/svg/logo.svg#logo-property"></use>
23
+ </svg>
24
+ </a>
25
+
26
+ <a href="/" class="selected">Lorem ipsum</a>
27
+ <a href="/">Lorem ipsum</a>
28
+ <a href="/">Lorem ipsum</a>
29
+ <a href="/">Lorem ipsum</a>
30
+
31
+ <button class="btn btn-primary">Lorem ipsum</button>
32
+ </iam-nav>
33
+ </nav>
34
+ ```
35
+
36
+ **Properties**
37
+
38
+ | Option | Type | Default Value | Description |
39
+ | ------ | ---- | ------------- | ----------- |
40
+ | data-search | String | - | Optional, displays a search button and form. The value passed through is used for the forms action attribute. |
41
+ | data-list | String | - | Optional string with an ID of a datalist, note this list needs to be added as an element in the component |
42
+ | data-prevent-search | String | - | Flag that prevents the search form submitting allowing it to used purely with JavaScript |
43
+ | data-searcd-open | String | - | Flag that opens the search bar on desktop on page load. |
44
+
45
+ **Slots**
46
+
47
+ | Option | Default Value | Description |
48
+ | ------ | ------------- | ----------- |
49
+ | default | - | Populates the main nav area |
50
+ | logo | - | A place to add the logo to the site |
51
+ | secondary | - | Moves the link upto the top of the navbar on desktop |
52
+ | actions | - | A place to add buttons |
53
+ | dual | - | Plave the link or list to the right of the nav, forcing the default slot to the left. |
54
+
55
+ **Class modifiers**
56
+
57
+ - Adding a class of **.bg-primary** will change the background of the navbar without chaning the menu background.
58
+ - Adding a class of **.nav--sticky** will add etxra styling to make the navbar stick to the top of the page
59
+ - Adding a class of **.nav--xs-sticky** will add etxra styling to make the navbar stick to the top of the page BUT only on the mobile view.
60
+
61
+ **Dispatched events**
62
+
63
+ | Event | Dispatched when | Details passed|
64
+ | ------ | ------------- | ----------- |
65
+ | search-keydown | When a user uses the search input field and triggers the keydown event. | { search: $inputValue } |
66
+ | search-keyup | When a user uses the search input field and triggers the keyup event. | { search: $inputValue } |
67
+ | search-change | When a user uses the search input field and triggers the change event. | { search: $inputValue } |
68
+ | search-submit | When a user uses the search form and triggers the submit event. | { search: $inputValue } |
@@ -0,0 +1,370 @@
1
+ // @ts-nocheck
2
+
3
+ // Data layer Web component created
4
+ window.dataLayer = window.dataLayer || [];
5
+ window.dataLayer.push({
6
+ "event": "customElementRegistered",
7
+ "element": "nav"
8
+ });
9
+
10
+ class iamNav 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/nav.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
+ <div class="container">
28
+ <slot name="logo"></slot>
29
+ <div class="buttons-holder"></div>
30
+ <button class="btn-menu">Menu<i class="fa-regular fa-bars"></i><i class="fa-regular fa-xmark-large"></i></button>
31
+
32
+ <div class="menu__outer">
33
+ <div class="menu closed">
34
+
35
+ <div class="menu__primary">
36
+ <slot></slot>
37
+ <slot name="dual"></slot>
38
+ </div>
39
+ <div class="dialog__wrapper d-none" id="search-wrapper"></div>
40
+ <slot name="actions"></slot>
41
+ <div class="menu__secondary">
42
+ <div class="container">
43
+ <slot name="secondary"></slot>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ <slot name="menus"></slot>
48
+ </div>
49
+ </div>
50
+ <div class="lists"></div>
51
+ <div class="backdrop" part="backdrop"></div>
52
+ `;
53
+
54
+ shadowRoot.appendChild(template.content.cloneNode(true));
55
+ }
56
+
57
+ connectedCallback() {
58
+
59
+ // Load external CSS if needed
60
+ if(this.hasAttribute('data-css'))
61
+ this.shadowRoot.querySelector('.styles').insertAdjacentHTML('beforeend', `@import "${this.getAttribute('data-css')}";`);
62
+
63
+ const menuButton = this.shadowRoot.querySelector('.btn-menu');
64
+ const menu = this.shadowRoot.querySelector('.menu');
65
+ const iamNav = this;
66
+ const backdrop = this.shadowRoot.querySelector('.backdrop');
67
+ const buttonsHolder = this.shadowRoot.querySelector('.buttons-holder');
68
+
69
+ // Check the content
70
+ this.querySelectorAll(':scope > *').forEach(function(element){
71
+ let tagname = element.tagName;
72
+
73
+ switch(tagname){
74
+ case "BUTTON":
75
+ element.setAttribute('slot','actions');
76
+ menu.classList.add('has-actions')
77
+ break;
78
+ }
79
+
80
+ // Create menu button
81
+ if(element.classList.contains('nav--menu') && element.hasAttribute('data-title') && element.hasAttribute('data-icon')){
82
+
83
+ const title = element.getAttribute('data-title');
84
+ const iconClass = element.getAttribute('data-icon');
85
+
86
+ // Create the menu button that sits seperately to the menu
87
+ const button = document.createElement('button');
88
+ button.setAttribute('slot',title);
89
+ button.classList.add('btn-menu');
90
+ button.innerHTML = `<span class="btn btn-primary"><span>${title}</span><i class="${iconClass}"></i><i class="fa-regular fa-xmark-large"></i></span>`;
91
+ buttonsHolder.insertAdjacentElement('beforeend',button);
92
+
93
+ const mdButton = button.querySelector('.btn-primary');
94
+
95
+ // Make sure the menu is added to the right part of the component
96
+ element.setAttribute('slot','menus');
97
+
98
+ // If open we need to make sure the main mobile menu is closed, the new button has the right state and the backdrop is shown
99
+ if(element.classList.contains('open')){
100
+ button.classList.add('selected');
101
+ mdButton.classList.toggle('active');
102
+ iamNav.classList.add('open');
103
+ backdrop.classList.add('show');
104
+ }
105
+ else {
106
+ element.classList.add('closed'); // closed class is added to prevent the elements being tabbed into, this causes visual issues
107
+ }
108
+
109
+ // Click event
110
+ button.addEventListener('click', function(e){
111
+
112
+ e.preventDefault();
113
+ button.classList.toggle('selected');
114
+ element.classList.toggle('open');
115
+ mdButton.classList.toggle('active');
116
+
117
+ // Close desktop menus
118
+ let openMenu = iamNav.querySelector(':scope > details[open]');
119
+
120
+ if(openMenu)
121
+ openMenu.removeAttribute('open')
122
+
123
+ // Close the main menu and fix states on the button, iamNav component and backdrop
124
+ if(element.classList.contains('open')){
125
+
126
+ menu.classList.remove('open');
127
+ menuButton.classList.remove('selected');
128
+ setTimeout(function(){ menu.classList.add('closed') }, 1000); // Delay until its close so the animation is broken
129
+ iamNav.classList.add('open');
130
+ backdrop.classList.add('show');
131
+ element.classList.remove('closed');
132
+ }
133
+ else{
134
+ iamNav.classList.remove('open');
135
+ backdrop.classList.remove('show');
136
+ setTimeout(function(){ element.classList.add('closed') }, 1000);
137
+ }
138
+
139
+ // Close any open menus
140
+ iamNav.querySelectorAll('.nav--menu.open').forEach(function(openmenu){
141
+ if(openmenu != element) {
142
+ openmenu.classList.remove('open');
143
+ }
144
+ });
145
+
146
+ iamNav.shadowRoot.querySelectorAll('.buttons-holder .btn-menu.selected').forEach(function(selectedButton){
147
+
148
+ if(selectedButton != button){
149
+
150
+ selectedButton.classList.remove('selected');
151
+ let innerBtn = selectedButton.querySelector('.btn-primary');
152
+ innerBtn.classList.remove('active');
153
+ }
154
+ });
155
+
156
+ }, false);
157
+ }
158
+ });
159
+
160
+ // Has secondary link
161
+ if(this.querySelector('a[slot="secondary"]')){
162
+ menu.classList.add('has-secondary');
163
+ }
164
+
165
+ // Create a scroll width variable to help with the sizing of the menu with in the CSS
166
+ document.documentElement.style.setProperty('--scrollbar-width', (window.innerWidth - document.documentElement.offsetWidth) + 'px');
167
+
168
+ // Open and close the menu
169
+ menuButton.addEventListener('click', function(e){
170
+
171
+ e.preventDefault();
172
+ menuButton.classList.toggle('selected');
173
+ menu.classList.toggle('open');
174
+
175
+ // Close any other menus
176
+ iamNav.querySelectorAll('.nav--menu.open').forEach(function(element){
177
+ element.classList.remove('open');
178
+ setTimeout(function(){ element.classList.add('closed') }, 1000);
179
+ });
180
+ iamNav.shadowRoot.querySelectorAll('.buttons-holder .btn-menu.selected').forEach(function(element){
181
+ element.classList.remove('selected');
182
+ let innerBtn = element.querySelector('.btn-primary');
183
+ innerBtn.classList.remove('active');
184
+ });
185
+
186
+ if(menu.classList.contains('open')){
187
+ iamNav.classList.add('open');
188
+ menu.classList.remove('closed');
189
+ }
190
+ else {
191
+ iamNav.classList.remove('open');
192
+ setTimeout(function(){ menu.classList.add('closed') }, 1000);
193
+ }
194
+
195
+ }, false);
196
+
197
+ // Allow outside JS to close the menu
198
+ this.addEventListener("request-close", (event) => {
199
+
200
+ menuButton.classList.remove('selected');
201
+ menu.classList.remove('open');
202
+ iamNav.classList.remove('open');
203
+ });
204
+
205
+ // Close the menu on the click of the backdrop on desktop
206
+ backdrop.addEventListener("click", (event) => {
207
+
208
+ let openMenu = this.querySelector('details[open] summary');
209
+
210
+ if(openMenu)
211
+ openMenu.click();
212
+
213
+ iamNav.querySelectorAll('.nav--menu.open').forEach(function(element){
214
+ element.classList.remove('open');
215
+ });
216
+ iamNav.shadowRoot.querySelectorAll('.buttons-holder .btn-menu.selected').forEach(function(element){
217
+ element.classList.remove('selected');
218
+ let innerBtn = element.querySelector('.btn-primary');
219
+ innerBtn.classList.remove('active');
220
+ });
221
+
222
+ backdrop.classList.remove('show');
223
+ });
224
+
225
+ // On desktop close other menu's (details) when one is clicked
226
+ this.addEventListener("click", (event) => {
227
+
228
+ if (event && event.target instanceof HTMLElement && event.target.closest('summary')){
229
+
230
+ if(window.innerWidth > 992){
231
+
232
+ let summary = event.target.closest('summary');
233
+ let details = summary.closest('details');
234
+ let wrapper = details.parentNode;
235
+
236
+ if(details.hasAttribute('open'))
237
+ details.removeAttribute('open');
238
+ else
239
+ details.setAttribute('open','true');
240
+
241
+ // Close any bespoke menus
242
+ iamNav.querySelectorAll('.nav--menu.open').forEach(function(element){
243
+ element.classList.remove('open');
244
+ setTimeout(function(){ menu.classList.add('closed') }, 1000);
245
+ });
246
+ iamNav.shadowRoot.querySelectorAll('.buttons-holder .btn-menu.selected').forEach(function(element){
247
+ element.classList.remove('selected');
248
+ let innerBtn = element.querySelector('.btn-primary');
249
+ innerBtn.classList.remove('active');
250
+ });
251
+
252
+ // Close any other dropdowns on the same level
253
+ Array.from(wrapper.querySelectorAll(':scope > details')).forEach((detailsArrayElement, index) => {
254
+
255
+ if(detailsArrayElement != details)
256
+ detailsArrayElement.removeAttribute('open')
257
+ });
258
+
259
+ if(this.querySelectorAll(':scope > details[open]').length){
260
+ backdrop.classList.add('show');
261
+ iamNav.classList.add('open');
262
+ }
263
+ else {
264
+ backdrop.classList.remove('show');
265
+ iamNav.classList.remove('open');
266
+ }
267
+
268
+ event.preventDefault();
269
+ }
270
+ };
271
+ });
272
+
273
+ // Mega menu title
274
+ this.querySelectorAll('details').forEach((detailsElement) => {
275
+
276
+ let summary = detailsElement.querySelector('summary');
277
+ let containerDiv = detailsElement.querySelector(':Scope > div');
278
+
279
+ containerDiv.setAttribute('data-title', summary.textContent);
280
+ });
281
+
282
+ // Search
283
+ if(this.hasAttribute('data-search')){
284
+ menu.classList.add('has-search');
285
+ let searchWrapper = this.shadowRoot.querySelector('#search-wrapper');
286
+
287
+ searchWrapper.classList.remove('d-none');
288
+ searchWrapper.insertAdjacentHTML('afterbegin',`<button class="btn btn-secondary btn-compact fa-search me-0 mb-0" id="search-button">Open Search field</button>
289
+ <dialog id="search-dialog">
290
+ <div class="container">
291
+ <form action="${this.hasAttribute('data-search') ? this.getAttribute('data-search') : ''}" class="row" id="search-form">
292
+ <div class="col mb-0 ms-auto col-md-7">
293
+ <label for="search" class="visually-hidden">Search</label>
294
+ <button class="suffix me-0 mb-0"><i class="fa-regular fa-search"></i></button>
295
+ <input type="search" class="" id="search" name="search" required="" autocomplete="off" data-list="${this.hasAttribute('data-list') ? this.getAttribute('data-list') : ''}" />
296
+ </div>
297
+ <div class="col d-none d-md-block mw-fit-content ms-3">
298
+ <button class="btn btn-compact btn-secondary fa-xmark-large m-0 mb-0" type="button" id="search-close"></button>
299
+ </div>
300
+ </form>
301
+ </div>
302
+ </dialog>`);
303
+
304
+ let searchButton = this.shadowRoot.querySelector('#search-button');
305
+ let searchClose = this.shadowRoot.querySelector('#search-close');
306
+ let searchDialog = this.shadowRoot.querySelector('#search-dialog');
307
+ let searchInput = this.shadowRoot.querySelector('#search');
308
+ let searchForm = this.shadowRoot.querySelector('#search-form');
309
+
310
+ if(this.hasAttribute('data-search-open')){
311
+
312
+ searchDialog.setAttribute('open','open');
313
+ this.classList.add('search-open');
314
+ }
315
+
316
+ searchButton.addEventListener("click", (event) => {
317
+
318
+ searchDialog.setAttribute('open','open');
319
+ this.classList.add('search-open');
320
+ });
321
+
322
+ searchClose.addEventListener("click", (event) => {
323
+
324
+ searchDialog.removeAttribute('open');
325
+ this.classList.remove('search-open');
326
+ });
327
+
328
+ // Search events
329
+ searchInput.addEventListener('keydown', (event) => {
330
+
331
+ const keyupEvent = new CustomEvent("search-keydown", { detail: { search: searchInput.value } });
332
+ this.dispatchEvent(keyupEvent);
333
+ });
334
+
335
+ searchInput.addEventListener('keyup', (event) => {
336
+
337
+ if (searchInput.value.length >= 3 && searchInput.hasAttribute('data-list'))
338
+ searchInput.setAttribute("list", searchInput.getAttribute('data-list'));
339
+ else
340
+ searchInput.removeAttribute("list");
341
+
342
+ const keyupEvent = new CustomEvent("search-keyup", { detail: { search: searchInput.value } });
343
+ this.dispatchEvent(keyupEvent);
344
+ });
345
+
346
+ searchInput.addEventListener('change', (event) => {
347
+
348
+ const changeEvent = new CustomEvent("search-change", { detail: { search: searchInput.value } });
349
+ this.dispatchEvent(changeEvent);
350
+ });
351
+
352
+ searchForm.addEventListener('submit', (event) => {
353
+
354
+ if(this.hasAttribute('data-prevent-search'))
355
+ event.preventDefault();
356
+
357
+ const submitEvent = new CustomEvent("search-submit", { detail: { search: searchInput.value } });
358
+ this.dispatchEvent(submitEvent);
359
+ });
360
+
361
+ // Make sure any child lists are available to the search input
362
+ this.querySelectorAll('datalist').forEach((list) => {
363
+
364
+ iamNav.shadowRoot.querySelector('.lists').insertAdjacentElement('beforeend',list);
365
+ });
366
+ }
367
+ }
368
+ }
369
+
370
+ export default iamNav;
@@ -27,6 +27,7 @@ class iamTable extends HTMLElement {
27
27
 
28
28
  ${this.hasAttribute('css') ? `@import "${this.getAttribute('css')}";` : ``}
29
29
  </style>
30
+ <slot name="before"></slot>
30
31
  <div class="table--cta">
31
32
  <div class="table__wrapper">
32
33
  <slot></slot>
@@ -124,6 +125,70 @@ class iamTable extends HTMLElement {
124
125
  }
125
126
 
126
127
  });
128
+
129
+
130
+ // Add in the checkboxes
131
+
132
+ if(this.querySelector('iam-actionbar[data-selectall]')){
133
+
134
+ const actionbar = this.querySelector('iam-actionbar[data-selectall]');
135
+
136
+ Array.from(this.table.querySelectorAll('thead tr')).forEach((row,index) => {
137
+
138
+ row.insertAdjacentHTML(
139
+ 'afterbegin',
140
+ "<th></th>"
141
+ );
142
+ });
143
+
144
+ Array.from(this.table.querySelectorAll('tbody tr')).forEach((row,index) => {
145
+
146
+ row.insertAdjacentHTML(
147
+ 'afterbegin',
148
+ `<td class="selectrow"><input type="checkbox" name="row" id="row${index}"/><label for="row${index}"><span class="visually-hidden">Select row</span></label></td>`
149
+ );
150
+ });
151
+
152
+ this.table.addEventListener('change',(event) => {
153
+
154
+ if (event && event.target instanceof HTMLElement && event.target.closest('.selectrow input')){
155
+
156
+
157
+ let count = this.table.querySelectorAll('.selectrow input[type="checkbox"]').length;
158
+ let countChecked = this.table.querySelectorAll('.selectrow input[type="checkbox"]:checked').length;
159
+
160
+ actionbar.setAttribute('data-selected', count == countChecked ? "all" : countChecked);
161
+
162
+ console.log(countChecked);
163
+ };
164
+
165
+ });
166
+
167
+ actionbar.addEventListener('selected', (event) => {
168
+
169
+ console.log(event.detail.selected);
170
+
171
+
172
+ if(event.detail.selected == '0'){
173
+
174
+ Array.from(this.table.querySelectorAll('.selectrow input[type="checkbox"]')).forEach((input,index) => {
175
+
176
+ input.checked = false;
177
+ });
178
+
179
+ }
180
+ else if(event.detail.selected == 'all'){
181
+
182
+ Array.from(this.table.querySelectorAll('.selectrow input[type="checkbox"]')).forEach((input,index) => {
183
+
184
+ input.checked = true;
185
+ });
186
+
187
+ }
188
+
189
+ });
190
+
191
+ }
127
192
  }
128
193
 
129
194