@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.
- package/assets/css/components/actionbar-global.css +1 -0
- package/assets/css/components/actionbar-global.css.map +1 -0
- package/assets/css/components/actionbar.css +1 -0
- package/assets/css/components/actionbar.css.map +1 -0
- package/assets/css/components/collapsible-side.css +1 -0
- package/assets/css/components/collapsible-side.css.map +1 -0
- package/assets/css/components/dialog.css +1 -1
- package/assets/css/components/dialog.css.map +1 -1
- package/assets/css/components/forms.css +1 -1
- package/assets/css/components/forms.css.map +1 -1
- package/assets/css/components/header.css +1 -1
- package/assets/css/components/header.css.map +1 -1
- package/assets/css/components/lists.css.map +1 -1
- package/assets/css/components/nav-global.css +1 -0
- package/assets/css/components/nav-global.css.map +1 -0
- package/assets/css/components/nav.css +1 -1
- package/assets/css/components/nav.css.map +1 -1
- package/assets/css/components/nav.docs.css +1 -0
- package/assets/css/components/nav.docs.css.map +1 -0
- package/assets/css/components/nav.old.css +1 -0
- package/assets/css/components/nav.old.css.map +1 -0
- package/assets/css/components/pagination.css.map +1 -1
- package/assets/css/components/property-searchbar.css +1 -1
- package/assets/css/components/property-searchbar.css.map +1 -1
- package/assets/css/components/table.css +1 -1
- package/assets/css/components/table.css.map +1 -1
- package/assets/css/core.min.css +1 -1
- package/assets/css/core.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.min.js +2 -2
- package/assets/js/components/actionbar/actionbar.component.js +305 -0
- package/assets/js/components/actionbar/actionbar.component.min.js +53 -0
- package/assets/js/components/actionbar/actionbar.component.min.js.map +1 -0
- package/assets/js/components/applied-filters/applied-filters.component.min.js +1 -1
- package/assets/js/components/card/card.component.min.js +1 -1
- package/assets/js/components/collapsible-side/collapsible-side.component.js +96 -0
- package/assets/js/components/collapsible-side/collapsible-side.component.min.js +27 -0
- package/assets/js/components/collapsible-side/collapsible-side.component.min.js.map +1 -0
- package/assets/js/components/filterlist/filterlist.component.min.js +1 -1
- package/assets/js/components/header/header.component.min.js +2 -2
- package/assets/js/components/nav/nav.component.js +294 -0
- package/assets/js/components/nav/nav.component.min.js +51 -0
- package/assets/js/components/nav/nav.component.min.js.map +1 -0
- package/assets/js/components/notification/notification.component.min.js +1 -1
- package/assets/js/components/pagination/pagination.component.min.js +1 -1
- package/assets/js/components/table/table.component.js +33 -0
- package/assets/js/components/table/table.component.min.js +12 -11
- package/assets/js/components/table/table.component.min.js.map +1 -1
- package/assets/js/components/tabs/tabs.component.min.js +1 -1
- package/assets/js/dynamic.min.js +3 -3
- package/assets/js/dynamic.min.js.map +1 -1
- package/assets/js/modules/dialogs.js +3 -0
- package/assets/js/modules/helpers.js +0 -13
- package/assets/js/modules/table.js +1 -1
- package/assets/js/scripts.bundle.js +15 -14
- 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/sass/_corefiles.scss +2 -0
- package/assets/sass/_functions/mixins.scss +25 -0
- package/assets/sass/_functions/variables.scss +1 -1
- package/assets/sass/components/actionbar-global.scss +89 -0
- package/assets/sass/components/actionbar.scss +254 -0
- package/assets/sass/components/collapsible-side.scss +327 -0
- package/assets/sass/components/dialog.scss +10 -0
- package/assets/sass/components/forms.scss +29 -0
- package/assets/sass/components/nav-global.scss +630 -0
- package/assets/sass/components/nav.docs.scss +54 -0
- package/assets/sass/components/nav.old.scss +965 -0
- package/assets/sass/components/nav.scss +450 -782
- package/assets/sass/components/table.scss +9 -1
- package/assets/sass/foundations/buttons.scss +57 -32
- package/assets/sass/foundations/links.scss +1 -1
- package/assets/sass/foundations/reboot.scss +5 -3
- package/assets/ts/components/actionbar/README.md +55 -0
- package/assets/ts/components/actionbar/actionbar.component.ts +396 -0
- package/assets/ts/components/collapsible-side/README.md +38 -0
- package/assets/ts/components/collapsible-side/collapsible-side.component.ts +134 -0
- package/assets/ts/components/nav/README.md +68 -0
- package/assets/ts/components/nav/nav.component.ts +370 -0
- package/assets/ts/components/table/table.component.ts +65 -0
- package/assets/ts/modules/dialogs.ts +6 -0
- package/assets/ts/modules/helpers.ts +0 -17
- package/assets/ts/modules/table.ts +5 -5
- package/dist/components.es.js +1368 -1113
- package/dist/components.umd.js +188 -44
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/Actionbar/Actionbar.vue +20 -0
- package/src/components/Actionbar/README.md +40 -0
- package/src/components/CollapsibleSideMenu/CollapsibleSideMenu.vue +20 -0
- package/src/components/CollapsibleSideMenu/README.md +23 -0
- package/src/components/Nav/Nav.vue +20 -195
- package/src/components/Nav/README.md +43 -13
- package/src/components/Nav-old/Nav.vue +213 -0
- package/src/components/Nav-old/README.md +23 -0
- package/src/index.js +8 -0
- package/src/components/Nav/Nav.spec.js +0 -35
|
@@ -121,7 +121,7 @@ table.border-0 {
|
|
|
121
121
|
--wrapper-padding: #{rem(32)};
|
|
122
122
|
--bg-colour: #ffffff;
|
|
123
123
|
display: block;
|
|
124
|
-
background:
|
|
124
|
+
background: white;
|
|
125
125
|
padding: var(--wrapper-padding);
|
|
126
126
|
box-shadow: 0px 6px 12px rgba(0,0,0,0.11);
|
|
127
127
|
border-radius: rem(8);
|
|
@@ -134,10 +134,17 @@ table.border-0 {
|
|
|
134
134
|
|
|
135
135
|
table {
|
|
136
136
|
margin-bottom: 0;
|
|
137
|
+
|
|
138
|
+
td:has(input[type="checkbox"]) {
|
|
139
|
+
width: rem(30);
|
|
140
|
+
min-width: rem(30);
|
|
141
|
+
max-width: rem(30);
|
|
142
|
+
}
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
@media (forced-colors: active) {
|
|
140
146
|
--wrapper-padding: 0;
|
|
147
|
+
background: var(--colour-canvas-2);
|
|
141
148
|
}
|
|
142
149
|
}
|
|
143
150
|
|
|
@@ -162,6 +169,7 @@ table.border-0 {
|
|
|
162
169
|
margin-left: -1.5rem;
|
|
163
170
|
margin-right: -1.5rem;
|
|
164
171
|
margin-bottom: 0;
|
|
172
|
+
background: white;
|
|
165
173
|
}
|
|
166
174
|
|
|
167
175
|
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
.btn {
|
|
5
5
|
|
|
6
6
|
--btn-margin: #{rem(16)};
|
|
7
|
+
--btn-padding-block: #{rem(12)};
|
|
8
|
+
--btn-padding-inline: #{rem(40)};
|
|
9
|
+
--btn-border-width: 2px;
|
|
7
10
|
|
|
8
11
|
@include media-breakpoint-up(sm) {
|
|
9
12
|
|
|
@@ -29,12 +32,12 @@
|
|
|
29
32
|
user-select: none;
|
|
30
33
|
|
|
31
34
|
background: var(--colour-btn-bg);
|
|
32
|
-
border:
|
|
35
|
+
border: var(--btn-border-width) solid var(--colour-btn-border);
|
|
33
36
|
color: var(--colour-btn);
|
|
34
37
|
|
|
35
38
|
font-size: rem(18);
|
|
36
39
|
line-height: rem(24);
|
|
37
|
-
padding: calc(
|
|
40
|
+
padding: calc(var(--btn-padding-block) - var(--btn-border-width)) calc(var(--btn-padding-inline) - var(--btn-border-width));
|
|
38
41
|
border-radius: rem(24);
|
|
39
42
|
margin-bottom: var(--btn-margin);
|
|
40
43
|
|
|
@@ -92,13 +95,18 @@ a:is(:hover, :focus, .hover, :active, .active):not([disabled]) .btn-secondary,
|
|
|
92
95
|
|
|
93
96
|
// #region Action button
|
|
94
97
|
.btn-action {
|
|
98
|
+
|
|
99
|
+
--btn-border-width: 1px;
|
|
100
|
+
--btn-padding-block: #{rem(6)};
|
|
101
|
+
--btn-padding-inline: #{rem(6)};
|
|
102
|
+
|
|
95
103
|
background-color: var(--colour-canvas-2);
|
|
96
|
-
border:
|
|
104
|
+
border: var(--btn-border-width) solid var(--colour-muted);
|
|
97
105
|
border-radius: rem(4)!important;
|
|
98
106
|
font-weight: 400!important;
|
|
99
107
|
font-size: 1rem;
|
|
100
108
|
line-height: rem(20);
|
|
101
|
-
|
|
109
|
+
|
|
102
110
|
color: var(--colour-heading);
|
|
103
111
|
|
|
104
112
|
&.btn[class*=fa-]:before {
|
|
@@ -128,14 +136,16 @@ a:is(:hover, :focus, .hover, :active, .active):not([disabled]) .btn-secondary,
|
|
|
128
136
|
|
|
129
137
|
font-family: "Font Awesome 6 Pro";
|
|
130
138
|
margin-right: 1rem;
|
|
139
|
+
line-height: 1em;
|
|
131
140
|
}
|
|
132
141
|
|
|
133
|
-
[class*="fa-"]{
|
|
142
|
+
i[class*="fa-"]{
|
|
134
143
|
|
|
135
144
|
font-family: "Font Awesome 6 Pro";
|
|
136
145
|
margin-right: 1rem;
|
|
137
|
-
|
|
146
|
+
line-height: 1em;
|
|
138
147
|
font-style: inherit;
|
|
148
|
+
|
|
139
149
|
&:not(:first-child){
|
|
140
150
|
margin-left: 1rem;
|
|
141
151
|
margin-right: 0;
|
|
@@ -178,41 +188,37 @@ a:is(:hover, :focus, .hover, :active, .active):not([disabled]) .btn-secondary,
|
|
|
178
188
|
// #region button small and tag
|
|
179
189
|
.btn.btn-sm {
|
|
180
190
|
|
|
181
|
-
padding:
|
|
191
|
+
--btn-padding-block: #{rem(8)};
|
|
192
|
+
--btn-padding-inline: #{rem(32)};
|
|
182
193
|
}
|
|
183
194
|
// #endregion
|
|
184
195
|
|
|
185
196
|
// #region btn compact
|
|
186
197
|
.btn-compact {
|
|
187
|
-
padding: calc(rem(12) - 2px)!important;
|
|
188
|
-
margin-bottom: rem(8)!important;
|
|
189
|
-
margin-right: rem(8)!important;
|
|
190
198
|
|
|
199
|
+
--compact-size: #{rem(48)};
|
|
200
|
+
|
|
201
|
+
padding: 0!important;
|
|
202
|
+
margin-bottom: rem(8)!important;
|
|
203
|
+
|
|
204
|
+
&:not(:last-child){
|
|
205
|
+
margin-right: rem(8);
|
|
206
|
+
}
|
|
191
207
|
text-align: center;
|
|
192
|
-
width: calc(rem(48) - 4px);
|
|
193
|
-
min-width: calc(rem(48) - 4px);
|
|
194
|
-
max-width: calc(rem(48) - 4px);
|
|
195
|
-
height: calc(rem(48) - 4px)!important;
|
|
196
|
-
text-indent: -300px;
|
|
197
|
-
overflow: hidden;
|
|
198
|
-
position: relative;
|
|
199
|
-
font-size: rem(20);
|
|
200
208
|
|
|
201
|
-
|
|
209
|
+
width: calc(var(--compact-size));
|
|
210
|
+
min-width: calc(var(--compact-size));
|
|
211
|
+
max-width: calc(var(--compact-size));
|
|
212
|
+
height: calc(var(--compact-size))!important;
|
|
213
|
+
min-height: calc(var(--compact-size))!important;
|
|
214
|
+
max-height: calc(var(--compact-size))!important;
|
|
202
215
|
|
|
203
|
-
|
|
204
|
-
padding: rem(6)!important;
|
|
205
|
-
height: auto!important;
|
|
206
|
-
line-height: rem(20);
|
|
207
|
-
height: rem(20 + 6 + 6);
|
|
208
|
-
width: rem(20 + 6 + 6);
|
|
209
|
-
min-width: rem(20 + 6 + 6);
|
|
210
|
-
|
|
211
|
-
&:before {
|
|
212
|
-
line-height: rem(20 + 6 + 6);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
216
|
+
line-height: calc(var(--compact-size) - var(--btn-border-width) - var(--btn-border-width))!important;
|
|
215
217
|
|
|
218
|
+
text-indent: -500px;
|
|
219
|
+
overflow: hidden;
|
|
220
|
+
position: relative;
|
|
221
|
+
font-size: rem(20);
|
|
216
222
|
|
|
217
223
|
&:before {
|
|
218
224
|
position: absolute;
|
|
@@ -221,10 +227,29 @@ a:is(:hover, :focus, .hover, :active, .active):not([disabled]) .btn-secondary,
|
|
|
221
227
|
width: 100%;
|
|
222
228
|
height: 100%;
|
|
223
229
|
text-indent: 0;
|
|
224
|
-
line-height: calc(
|
|
230
|
+
line-height: calc(var(--compact-size) - var(--btn-border-width) - var(--btn-border-width))!important;
|
|
225
231
|
font-weight: 900;
|
|
226
232
|
}
|
|
227
233
|
|
|
234
|
+
&.btn-sm {
|
|
235
|
+
|
|
236
|
+
--compact-size: #{rem(40)};
|
|
237
|
+
|
|
238
|
+
font-size: 1rem;
|
|
239
|
+
padding: 0!important;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
&.btn-action {
|
|
243
|
+
|
|
244
|
+
--compact-size: #{rem(32)};
|
|
245
|
+
font-size: 1rem;
|
|
246
|
+
|
|
247
|
+
&:before {
|
|
248
|
+
font-size: 1em;
|
|
249
|
+
font-weight: 400;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
228
253
|
&.btn-secondary {
|
|
229
254
|
|
|
230
255
|
--colour-btn-border: transparent;
|
|
@@ -51,7 +51,6 @@ body {
|
|
|
51
51
|
width: 100%;
|
|
52
52
|
line-height: 1.2;
|
|
53
53
|
min-height: 100%;
|
|
54
|
-
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
// #region scrollbars
|
|
@@ -142,7 +141,7 @@ details {
|
|
|
142
141
|
|
|
143
142
|
|
|
144
143
|
// #region Undefined web components
|
|
145
|
-
:is(*):not(:defined) {
|
|
144
|
+
:is(*):not(:defined):not(iam-nav) {
|
|
146
145
|
display: block;
|
|
147
146
|
padding: rem(24);
|
|
148
147
|
margin-bottom: rem(24);
|
|
@@ -178,9 +177,12 @@ main > :is(*):not(:defined) {
|
|
|
178
177
|
|
|
179
178
|
main {
|
|
180
179
|
position: relative;
|
|
180
|
+
|
|
181
|
+
> *:first-child {
|
|
182
|
+
padding-top: 2rem;
|
|
183
|
+
}
|
|
181
184
|
}
|
|
182
185
|
|
|
183
|
-
|
|
184
186
|
.container.notification__holder {
|
|
185
187
|
|
|
186
188
|
position: fixed;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
**Add the below to your initialise script**
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
import('../node_modules/@iamproperty/components/assets/js/components/actionbar/actionbar.component.min').then(module => { // Might need to update the path
|
|
5
|
+
|
|
6
|
+
if (!window.customElements.get(`iam-actionbar`))
|
|
7
|
+
window.customElements.define(`iam-actionbar`, 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-actionbar data-selectall data-search>
|
|
18
|
+
|
|
19
|
+
<div class="dialog__wrapper">
|
|
20
|
+
<button class="btn btn-action mb-0 me-0">Quick filter</button>
|
|
21
|
+
<dialog class="dialog--list">
|
|
22
|
+
<div class="pb-0">
|
|
23
|
+
<input type="radio" name="sorta" data-sort="" id="follow-up-oldesta" value="follow-up-oldest">
|
|
24
|
+
<label for="follow-up-oldesta" class="radio--tick">Option 1</label>
|
|
25
|
+
|
|
26
|
+
<input type="radio" name="sorta" data-sort="" id="follow-up-newesta" value="follow-up-newest">
|
|
27
|
+
<label for="follow-up-newesta" class="radio--tick">Option 2</label>
|
|
28
|
+
|
|
29
|
+
<input type="radio" name="sorta" data-sort="" id="date-instructed-oldesta" value="date-instructed-oldest" checked="" autofocus="true">
|
|
30
|
+
<label for="date-instructed-oldesta" class="radio--tick">Option 3</label>
|
|
31
|
+
|
|
32
|
+
<input type="radio" name="sorta" data-sort="" id="date-instructed-newesta" value="date-instructed-newest">
|
|
33
|
+
<label for="date-instructed-newesta" class="radio--tick mb-0">Option 4</label>
|
|
34
|
+
</div>
|
|
35
|
+
</dialog>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<button class="btn btn-primary btn-sm fa-plus" id="uploadBtn">Upload document</button>
|
|
39
|
+
|
|
40
|
+
<button class="btn btn-action fa-pen-to-square" data-single slot="selected">Edit</button>
|
|
41
|
+
<button class="btn btn-action fa-box-archive" slot="selected">Archive</button>
|
|
42
|
+
<button class="btn btn-action fa-trash-can" slot="selected">Delete</button>
|
|
43
|
+
<hr slot="selected" />
|
|
44
|
+
<button class="btn btn-action" slot="selected">Cancel</button>
|
|
45
|
+
|
|
46
|
+
</iam-actionbar>
|
|
47
|
+
```
|
|
48
|
+
**Properties**
|
|
49
|
+
|
|
50
|
+
| Option | Type | Default Value | Description |
|
|
51
|
+
| ------ | ---- | ------------- | ----------- |
|
|
52
|
+
| data-selectall | - | - | Optional flag to include the select all button |
|
|
53
|
+
| data-search | - | - | Optional flag to include the search button and functionality |
|
|
54
|
+
| data-switchviews | - | - | Optional flag to include the switch views buttons |
|
|
55
|
+
| data-view | String | square | Required if you have the above flag set. Can be set to wither 'square','list' or 'small'. |
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import extendDialogs from "../../modules/dialogs";
|
|
3
|
+
|
|
4
|
+
// Data layer Web component created
|
|
5
|
+
window.dataLayer = window.dataLayer || [];
|
|
6
|
+
window.dataLayer.push({
|
|
7
|
+
"event": "customElementRegistered",
|
|
8
|
+
"element": "action bar"
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
function setSelectAllInput(element, value){
|
|
12
|
+
|
|
13
|
+
if(element && value == "all"){
|
|
14
|
+
|
|
15
|
+
element.querySelector('input').indeterminate = false;
|
|
16
|
+
element.querySelector('input').checked = true;
|
|
17
|
+
element.querySelector('label').textContent = `Select all`;
|
|
18
|
+
}
|
|
19
|
+
else if(element && value == 0){
|
|
20
|
+
|
|
21
|
+
element.querySelector('input').indeterminate = false;
|
|
22
|
+
element.querySelector('input').checked = false;
|
|
23
|
+
element.querySelector('label').textContent = `Select all`;
|
|
24
|
+
}
|
|
25
|
+
else if(element && value){
|
|
26
|
+
|
|
27
|
+
element.querySelector('input').indeterminate = true;
|
|
28
|
+
element.querySelector('input').checked = false;
|
|
29
|
+
element.querySelector('label').textContent = `${value} item${value > 1 ? 's' : ''} selected`;
|
|
30
|
+
}
|
|
31
|
+
else if(element){
|
|
32
|
+
|
|
33
|
+
element.querySelector('input').checked = false;
|
|
34
|
+
element.querySelector('input').indeterminate = false;
|
|
35
|
+
element.querySelector('label').textContent = `Select all`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
class iamActionbar extends HTMLElement {
|
|
40
|
+
|
|
41
|
+
constructor(){
|
|
42
|
+
super();
|
|
43
|
+
this.attachShadow({ mode: 'open'});
|
|
44
|
+
|
|
45
|
+
const assetLocation = document.body.hasAttribute('data-assets-location') ? document.body.getAttribute('data-assets-location') : '/assets'
|
|
46
|
+
const coreCSS = document.body.hasAttribute('data-core-css') ? document.body.getAttribute('data-core-css') : `${assetLocation}/css/core.min.css`;
|
|
47
|
+
const loadCSS = `@import "${assetLocation}/css/components/actionbar.css";`;
|
|
48
|
+
|
|
49
|
+
const template = document.createElement('template');
|
|
50
|
+
template.innerHTML = `
|
|
51
|
+
<style>
|
|
52
|
+
@import "${coreCSS}";
|
|
53
|
+
${loadCSS}
|
|
54
|
+
${this.hasAttribute('css') ? `@import "${this.getAttribute('css')}";` : ``}
|
|
55
|
+
</style>
|
|
56
|
+
<link rel="stylesheet" href="https://kit.fontawesome.com/26fdbf0179.css" crossorigin="anonymous">
|
|
57
|
+
<div class="actionbar__wrapper">
|
|
58
|
+
<div class="actionbar">
|
|
59
|
+
<div class="safe-area">
|
|
60
|
+
<slot></slot>
|
|
61
|
+
<div class="body">
|
|
62
|
+
<div class="dialog__wrapper dialog__wrapper--right dialog-overflow d-none show">
|
|
63
|
+
<button class="btn btn-secondary btn-compact fa-ellipsis-vertical m-0">More actions</button>
|
|
64
|
+
<dialog class="dialog--list">
|
|
65
|
+
<slot name="overflow"></slot>
|
|
66
|
+
<slot name="menu"></slot>
|
|
67
|
+
</dialog>
|
|
68
|
+
</div>
|
|
69
|
+
<button class="btn btn-secondary btn-compact btn-sm fa-search m-0" data-search="">Search</button>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="actionbar--selected">
|
|
74
|
+
<div class="safe-area">
|
|
75
|
+
<slot name="selected"></slot>
|
|
76
|
+
<div class="body">
|
|
77
|
+
<div class="dialog__wrapper dialog__wrapper--right dialog-overflow d-none show">
|
|
78
|
+
<button class="btn btn-secondary btn-compact fa-ellipsis-vertical m-0">More actions</button>
|
|
79
|
+
<dialog class="dialog--list">
|
|
80
|
+
<slot name="selected-overflow"></slot>
|
|
81
|
+
</dialog>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="actionbar--search">
|
|
87
|
+
<button data-search class="btn btn-compact fa-xmark-large btn-secondary m-0" >Close</button>
|
|
88
|
+
|
|
89
|
+
<div class="search-wrapper">
|
|
90
|
+
<label for="search" class="visually-hidden">Input field label</label>
|
|
91
|
+
<button class="suffix"><i class="fa-regular fa-search"></i></button>
|
|
92
|
+
<input type="text" id="search" name="search" required="">
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
`;
|
|
98
|
+
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
connectedCallback() {
|
|
102
|
+
|
|
103
|
+
let that = this;
|
|
104
|
+
const actionbarWrapper = this.shadowRoot.querySelector('.actionbar__wrapper');
|
|
105
|
+
|
|
106
|
+
// #region select all
|
|
107
|
+
if(this.hasAttribute('data-selectall')){
|
|
108
|
+
|
|
109
|
+
actionbarWrapper.insertAdjacentHTML( 'afterbegin', `<div class="selectall pb-0"><input type="checkbox" name="selectall" id="selectall"><label for="selectall" class="m-0">Select all</label></div>` );
|
|
110
|
+
let selectAll = this.shadowRoot.querySelector('.selectall');
|
|
111
|
+
|
|
112
|
+
if(this.hasAttribute('data-selected')){
|
|
113
|
+
setSelectAllInput(selectAll, this.getAttribute('data-selected'));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
selectAll.addEventListener('change', (event) => {
|
|
117
|
+
|
|
118
|
+
if (event && event.target instanceof HTMLElement && event.target.closest('input')){
|
|
119
|
+
|
|
120
|
+
if(event.target.closest('input').checked)
|
|
121
|
+
this.setAttribute('data-selected','all');
|
|
122
|
+
else
|
|
123
|
+
this.setAttribute('data-selected',0);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
let cancelButton = this.querySelector('button[data-cancel]');
|
|
128
|
+
if(cancelButton){
|
|
129
|
+
cancelButton.addEventListener('click', (event) => {
|
|
130
|
+
|
|
131
|
+
this.setAttribute('data-selected',0);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// #endregion
|
|
136
|
+
|
|
137
|
+
// #region switchviews
|
|
138
|
+
if(this.hasAttribute('data-switchviews')){
|
|
139
|
+
|
|
140
|
+
let btns = '';
|
|
141
|
+
let viewList = this.getAttribute('data-switchviews').split(',');
|
|
142
|
+
|
|
143
|
+
viewList.forEach((view,index) => {
|
|
144
|
+
|
|
145
|
+
let icon = 'fa-grid-2';
|
|
146
|
+
|
|
147
|
+
if(view == "list")
|
|
148
|
+
icon = 'fa-grip-lines';
|
|
149
|
+
else if(view == "small")
|
|
150
|
+
icon = 'fa-bars';
|
|
151
|
+
|
|
152
|
+
btns += `<button class="btn btn-action btn-compact mb-0 fa-regular ${icon}">${view}</button>`;
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
actionbarWrapper.insertAdjacentHTML( 'afterbegin', `<div class="views m-0">${btns}</div>` );
|
|
156
|
+
let views = this.shadowRoot.querySelector('.views');
|
|
157
|
+
|
|
158
|
+
views.addEventListener('click', (event) => {
|
|
159
|
+
|
|
160
|
+
if (event && event.target instanceof HTMLElement && event.target.closest('.btn-action')){
|
|
161
|
+
|
|
162
|
+
let btn = event.target.closest('.btn-action');
|
|
163
|
+
|
|
164
|
+
this.setAttribute('data-view',btn.textContent);
|
|
165
|
+
|
|
166
|
+
const switchEvent = new CustomEvent("switch-view", { detail: { view: btn.textContent} });
|
|
167
|
+
this.dispatchEvent(switchEvent);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
// #endregion
|
|
172
|
+
|
|
173
|
+
// #region search
|
|
174
|
+
const searchBar = this.shadowRoot.querySelector('.actionbar--search');
|
|
175
|
+
|
|
176
|
+
if(this.hasAttribute('data-search') && this.getAttribute('data-search') == 'show')
|
|
177
|
+
searchBar.classList.add('show');
|
|
178
|
+
|
|
179
|
+
this.shadowRoot.addEventListener('click', (event) => {
|
|
180
|
+
|
|
181
|
+
if (event && event.target instanceof HTMLElement && event.target.closest('button[data-search]')){
|
|
182
|
+
searchBar.classList.toggle('show');
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
searchBar.addEventListener('keyup', (event) => {
|
|
187
|
+
|
|
188
|
+
const keyupEvent = new CustomEvent("search-keyup", { detail: { search: searchBar.querySelector('input').value } });
|
|
189
|
+
this.dispatchEvent(keyupEvent);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
searchBar.addEventListener('change', (event) => {
|
|
193
|
+
|
|
194
|
+
const changeEvent = new CustomEvent("search-change", { detail: { search: searchBar.querySelector('input').value } });
|
|
195
|
+
this.dispatchEvent(changeEvent);
|
|
196
|
+
});
|
|
197
|
+
searchBar.addEventListener('click', (event) => {
|
|
198
|
+
|
|
199
|
+
if (event && event.target instanceof HTMLElement && event.target.closest('button.suffix')){
|
|
200
|
+
|
|
201
|
+
const submitEvent = new CustomEvent("search-submit", { detail: { search: searchBar.querySelector('input').value } });
|
|
202
|
+
this.dispatchEvent(submitEvent);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
// #endregion
|
|
206
|
+
|
|
207
|
+
// Make sure dialogs created in the shadow dom work
|
|
208
|
+
Array.from(this.shadowRoot.querySelectorAll('.body')).forEach((element,index) => {
|
|
209
|
+
|
|
210
|
+
extendDialogs(element);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// #region Reponsive safe area
|
|
214
|
+
function hideButtons () {
|
|
215
|
+
|
|
216
|
+
const wrapperWidth = actionbarWrapper.scrollWidth;
|
|
217
|
+
const screenWidth = document.documentElement.scrollWidth;
|
|
218
|
+
let safeAreaWidth = 750;
|
|
219
|
+
let elementMargin = 16;
|
|
220
|
+
let mobileSafeWidth = that.hasAttribute('data-switchviews') ? 144 : 210;
|
|
221
|
+
|
|
222
|
+
// We need to modify the widths to mimic the CSS's scaling functionality
|
|
223
|
+
let modifier = 1;
|
|
224
|
+
if (screenWidth >= 992 && screenWidth <= 1280){
|
|
225
|
+
modifier = screenWidth/1280;
|
|
226
|
+
}
|
|
227
|
+
else if (screenWidth >= 576 && screenWidth <= 1280) {
|
|
228
|
+
modifier = screenWidth/768;
|
|
229
|
+
}
|
|
230
|
+
else if (screenWidth < 576) {
|
|
231
|
+
modifier = screenWidth/375;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Work out the safe sapce width depending upon the wrappers width and modifier
|
|
235
|
+
if (wrapperWidth >= 992 && wrapperWidth <= 1280){
|
|
236
|
+
safeAreaWidth = safeAreaWidth*modifier;
|
|
237
|
+
}
|
|
238
|
+
else if (wrapperWidth >= 576 && wrapperWidth <= 1280) {
|
|
239
|
+
safeAreaWidth = 450*modifier;
|
|
240
|
+
}
|
|
241
|
+
else if (wrapperWidth < 576) {
|
|
242
|
+
safeAreaWidth = mobileSafeWidth*modifier;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Margin in between elements
|
|
246
|
+
elementMargin = elementMargin*modifier;
|
|
247
|
+
|
|
248
|
+
// If the wrapper width is small we want to reduce the btn sizes by adding or removing btn-compact classes
|
|
249
|
+
if (wrapperWidth < 576) {
|
|
250
|
+
|
|
251
|
+
Array.from(that.querySelectorAll(':scope > .btn:not(.js-updated)')).forEach((element,index) => {
|
|
252
|
+
|
|
253
|
+
element.className = element.className.replace(' btn-compact',' _btn-compact');
|
|
254
|
+
element.classList.add('btn-compact');
|
|
255
|
+
element.classList.add('js-updated');
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
|
|
260
|
+
Array.from(that.querySelectorAll(':scope > .btn.js-updated')).forEach((element,index) => {
|
|
261
|
+
|
|
262
|
+
element.classList.remove('btn-compact');
|
|
263
|
+
element.classList.remove('js-updated');
|
|
264
|
+
element.className = element.className.replace(' _btn-compact',' btn-compact');
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Reset the elements before we decide what elements become slotted into the overflow
|
|
269
|
+
Array.from(that.querySelectorAll('[slot]')).forEach((element,index) => {
|
|
270
|
+
|
|
271
|
+
if(element.getAttribute("slot") == "overflow")
|
|
272
|
+
element.removeAttribute('slot');
|
|
273
|
+
|
|
274
|
+
if(element.getAttribute("slot") == "selected-overflow")
|
|
275
|
+
element.setAttribute('slot','selected');
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
Array.from(that.querySelectorAll('.show')).forEach((element,index) => {
|
|
279
|
+
|
|
280
|
+
element.classList.remove('show');
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// Foreach safe area lets check what elements are slotted in them and if they need an overflow
|
|
284
|
+
Array.from(that.shadowRoot.querySelectorAll('.safe-area')).forEach((element,index) => {
|
|
285
|
+
|
|
286
|
+
// Decide on which overflow slot to use
|
|
287
|
+
let overflowSlot = "overflow"
|
|
288
|
+
|
|
289
|
+
if(element.querySelector('slot').hasAttribute('name') && element.querySelector('slot').getAttribute('name') == "selected")
|
|
290
|
+
overflowSlot = "selected-overflow";
|
|
291
|
+
|
|
292
|
+
// Get the slotted elements, remember they aren't children of the safe area
|
|
293
|
+
let elements = element.querySelector('slot').assignedElements();
|
|
294
|
+
let tempWidth = 44*modifier; // Allow space for the overflow button
|
|
295
|
+
|
|
296
|
+
// If search then allow for the search button width
|
|
297
|
+
if(that.hasAttribute('data-search'))
|
|
298
|
+
tempWidth += 44*modifier;
|
|
299
|
+
|
|
300
|
+
// Foreach element that isn't an action button or dialog wrapper add to the width, these will not be moved into the overflow slot
|
|
301
|
+
for (let i = 0; i < elements.length; i++) {
|
|
302
|
+
|
|
303
|
+
if(!elements[i].classList.contains('btn-action') && !elements[i].classList.contains('dialog__wrapper')){
|
|
304
|
+
|
|
305
|
+
tempWidth += elements[i].offsetWidth;
|
|
306
|
+
tempWidth += elementMargin;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Foreach dialog wrapper decide if safe in safe area or move into the overflow slot, dialog wrappers have priority over the action buttons
|
|
311
|
+
for (let i = 0; i < elements.length; i++) {
|
|
312
|
+
|
|
313
|
+
if(elements[i].classList.contains('dialog__wrapper')){
|
|
314
|
+
|
|
315
|
+
elements[i].classList.add('show');
|
|
316
|
+
tempWidth += elements[i].offsetWidth;
|
|
317
|
+
tempWidth += (elementMargin/2);
|
|
318
|
+
|
|
319
|
+
// If we have exceeded the safe area then lets break the loop
|
|
320
|
+
if(tempWidth - (elementMargin/2) > safeAreaWidth){
|
|
321
|
+
|
|
322
|
+
elements[i].classList.remove('show');
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Foreach action button
|
|
329
|
+
for (let i = 0; i < elements.length; i++) {
|
|
330
|
+
|
|
331
|
+
if(elements[i].classList.contains('btn-action')){
|
|
332
|
+
|
|
333
|
+
elements[i].classList.add('show');
|
|
334
|
+
tempWidth += elements[i].offsetWidth;
|
|
335
|
+
tempWidth += (elementMargin/2);
|
|
336
|
+
|
|
337
|
+
// If we have exceeded the safe area then lets break the loop
|
|
338
|
+
if(tempWidth - (elementMargin/2) > safeAreaWidth){
|
|
339
|
+
|
|
340
|
+
elements[i].classList.remove('show');
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
let overflowDialog = element.querySelector('.dialog-overflow');
|
|
347
|
+
|
|
348
|
+
if(overflowDialog)
|
|
349
|
+
overflowDialog.classList.add('d-none');
|
|
350
|
+
|
|
351
|
+
// Decide which elements go into the overflow slot
|
|
352
|
+
for (let i = 0; i < elements.length; i++) {
|
|
353
|
+
|
|
354
|
+
if(elements[i].classList.contains('btn-action') || elements[i].classList.contains('dialog__wrapper')){
|
|
355
|
+
if (!elements[i].classList.contains('show')){
|
|
356
|
+
|
|
357
|
+
// Move to the slot by changing the attribute
|
|
358
|
+
elements[i].setAttribute('slot',overflowSlot);
|
|
359
|
+
|
|
360
|
+
// if an element has been added to overflow slot then make sure we show the overflow menu button
|
|
361
|
+
if(overflowDialog)
|
|
362
|
+
overflowDialog.classList.remove('d-none');
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Check buttons on load and when the wrapper element gets resized.
|
|
370
|
+
hideButtons();
|
|
371
|
+
new ResizeObserver(hideButtons).observe(actionbarWrapper);
|
|
372
|
+
// #endregion
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
static get observedAttributes() {
|
|
376
|
+
return ["data-selected"];
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
attributeChangedCallback(attrName, oldVal, newVal) {
|
|
380
|
+
|
|
381
|
+
switch (attrName) {
|
|
382
|
+
case "data-selected": {
|
|
383
|
+
|
|
384
|
+
let selectAll = this.shadowRoot.querySelector('.selectall');
|
|
385
|
+
|
|
386
|
+
if(selectAll)
|
|
387
|
+
setSelectAllInput(selectAll, newVal);
|
|
388
|
+
const event = new CustomEvent("selected", { detail: { selected: newVal } });
|
|
389
|
+
this.dispatchEvent(event);
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
export default iamActionbar;
|