@ministryofjustice/frontend 3.3.1 → 3.5.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/README.md +4 -10
- package/govuk-prototype-kit.config.json +5 -16
- package/moj/all.jquery.min.js +15 -4
- package/moj/all.js +2856 -2280
- package/moj/all.scss +2 -0
- package/moj/components/_all.scss +1 -0
- package/moj/components/action-bar/_action-bar.scss +4 -6
- package/moj/components/add-another/_add-another.scss +9 -7
- package/moj/components/add-another/add-another.js +128 -76
- package/moj/components/alert/README.md +0 -0
- package/moj/components/alert/_alert.scss +142 -0
- package/moj/components/alert/alert.js +482 -0
- package/moj/components/alert/alert.spec.helper.js +92 -0
- package/moj/components/alert/macro.njk +3 -0
- package/moj/components/alert/template.njk +83 -0
- package/moj/components/badge/_badge.scss +3 -4
- package/moj/components/banner/_banner.scss +5 -10
- package/moj/components/button-menu/_button-menu.scss +10 -9
- package/moj/components/button-menu/button-menu.js +348 -318
- package/moj/components/cookie-banner/_cookie-banner.scss +6 -5
- package/moj/components/currency-input/_currency-input.scss +4 -4
- package/moj/components/date-picker/README.md +14 -17
- package/moj/components/date-picker/_date-picker.scss +122 -106
- package/moj/components/date-picker/date-picker.js +927 -900
- package/moj/components/filter/README.md +1 -1
- package/moj/components/filter/_filter.scss +53 -75
- package/moj/components/filter-toggle-button/filter-toggle-button.js +122 -87
- package/moj/components/form-validator/form-validator.js +399 -156
- package/moj/components/header/_header.scss +17 -19
- package/moj/components/identity-bar/_identity-bar.scss +5 -5
- package/moj/components/interruption-card/_interruption-card.scss +2 -2
- package/moj/components/messages/_messages.scss +12 -19
- package/moj/components/multi-file-upload/README.md +1 -1
- package/moj/components/multi-file-upload/_multi-file-upload.scss +34 -30
- package/moj/components/multi-file-upload/multi-file-upload.js +454 -183
- package/moj/components/multi-select/_multi-select.scss +4 -3
- package/moj/components/multi-select/multi-select.js +106 -70
- package/moj/components/notification-badge/_notification-badge.scss +12 -12
- package/moj/components/organisation-switcher/_organisation-switcher.scss +1 -1
- package/moj/components/page-header-actions/_page-header-actions.scss +3 -2
- package/moj/components/pagination/_pagination.scss +26 -31
- package/moj/components/password-reveal/_password-reveal.scss +1 -2
- package/moj/components/password-reveal/password-reveal.js +63 -31
- package/moj/components/primary-navigation/_primary-navigation.scss +26 -29
- package/moj/components/progress-bar/_progress-bar.scss +21 -26
- package/moj/components/rich-text-editor/_rich-text-editor.scss +17 -16
- package/moj/components/rich-text-editor/rich-text-editor.js +186 -139
- package/moj/components/search/_search.scss +6 -4
- package/moj/components/search-toggle/search-toggle.js +83 -53
- package/moj/components/search-toggle/search-toggle.scss +21 -15
- package/moj/components/side-navigation/_side-navigation.scss +12 -21
- package/moj/components/sortable-table/_sortable-table.scss +25 -23
- package/moj/components/sortable-table/sortable-table.js +162 -119
- package/moj/components/sub-navigation/_sub-navigation.scss +24 -28
- package/moj/components/tag/_tag.scss +8 -9
- package/moj/components/task-list/_task-list.scss +8 -7
- package/moj/components/ticket-panel/_ticket-panel.scss +14 -6
- package/moj/components/timeline/_timeline.scss +18 -20
- package/moj/filters/all.js +28 -30
- package/moj/filters/prototype-kit-13-filters.js +2 -1
- package/moj/helpers/_all.scss +1 -0
- package/moj/helpers/_hidden.scss +1 -1
- package/moj/helpers/_links.scss +20 -0
- package/moj/helpers.js +218 -51
- package/moj/init.js +2 -2
- package/moj/moj-frontend.min.css +2 -2
- package/moj/moj-frontend.min.js +15 -4
- package/moj/objects/_filter-layout.scss +11 -10
- package/moj/objects/_scrollable-pane.scss +11 -14
- package/moj/settings/_colours.scss +5 -0
- package/moj/settings/_measurements.scss +0 -2
- package/moj/utilities/_hidden.scss +3 -3
- package/moj/utilities/_width-container.scss +1 -1
- package/moj/version.js +28 -1
- package/package.json +1 -1
- package/moj/all.spec.js +0 -22
- package/moj/components/button-menu/button-menu.spec.js +0 -361
- package/moj/components/date-picker/date-picker.spec.js +0 -1130
- package/moj/components/filter-toggle-button/filter-toggle-button.spec.js +0 -304
- package/moj/components/multi-select/multi-select.spec.js +0 -135
- package/moj/components/password-reveal/password-reveal.spec.js +0 -55
- package/moj/components/search-toggle/search-toggle.spec.js +0 -134
- package/moj/namespace.js +0 -1
|
@@ -1,324 +1,354 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.MOJFrontend = factory());
|
|
5
|
+
})(this, (function () { 'use strict';
|
|
6
|
+
|
|
7
|
+
function getDefaultExportFromCjs (x) {
|
|
8
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {object} ButtonMenuConfig
|
|
13
|
+
* @property {string} [buttonText=Actions] - Label for the toggle button
|
|
14
|
+
* @property {"left" | "right"} [alignMenu=left] - the alignment of the menu
|
|
15
|
+
* @property {string} [buttonClasses=govuk-button--secondary] - css classes applied to the toggle button
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
var buttonMenu$1;
|
|
19
|
+
var hasRequiredButtonMenu;
|
|
20
|
+
|
|
21
|
+
function requireButtonMenu () {
|
|
22
|
+
if (hasRequiredButtonMenu) return buttonMenu$1;
|
|
23
|
+
hasRequiredButtonMenu = 1;
|
|
24
|
+
/**
|
|
25
|
+
* @param {HTMLElement} $module
|
|
26
|
+
* @param {ButtonMenuConfig} config
|
|
27
|
+
* @class
|
|
28
|
+
*/
|
|
29
|
+
function ButtonMenu($module, config = {}) {
|
|
30
|
+
if (!$module) {
|
|
31
|
+
return this
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const schema = Object.freeze({
|
|
35
|
+
properties: {
|
|
36
|
+
buttonText: { type: 'string' },
|
|
37
|
+
buttonClasses: { type: 'string' },
|
|
38
|
+
alignMenu: { type: 'string' }
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const defaults = {
|
|
43
|
+
buttonText: 'Actions',
|
|
44
|
+
alignMenu: 'left',
|
|
45
|
+
buttonClasses: ''
|
|
46
|
+
};
|
|
47
|
+
// data attributes override JS config, which overrides defaults
|
|
48
|
+
this.config = this.mergeConfigs(
|
|
49
|
+
defaults,
|
|
50
|
+
config,
|
|
51
|
+
this.parseDataset(schema, $module.dataset)
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
this.$module = $module;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
ButtonMenu.prototype.init = function () {
|
|
58
|
+
// If only one button is provided, don't initiate a menu and toggle button
|
|
59
|
+
// if classes have been provided for the toggleButton, apply them to the single item
|
|
60
|
+
if (this.$module.children.length === 1) {
|
|
61
|
+
const button = this.$module.children[0];
|
|
62
|
+
button.classList.forEach((className) => {
|
|
63
|
+
if (className.startsWith('govuk-button-')) {
|
|
64
|
+
button.classList.remove(className);
|
|
65
|
+
}
|
|
66
|
+
button.classList.remove('moj-button-menu__item');
|
|
67
|
+
});
|
|
68
|
+
if (this.config.buttonClasses) {
|
|
69
|
+
button.classList.add(...this.config.buttonClasses.split(' '));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Otherwise intialise a button menu
|
|
73
|
+
if (this.$module.children.length > 1) {
|
|
74
|
+
this.initMenu();
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
ButtonMenu.prototype.initMenu = function () {
|
|
79
|
+
this.$menu = this.createMenu();
|
|
80
|
+
this.$module.insertAdjacentHTML('afterbegin', this.toggleTemplate());
|
|
81
|
+
this.setupMenuItems();
|
|
82
|
+
|
|
83
|
+
this.$menuToggle = this.$module.querySelector(':scope > button');
|
|
84
|
+
this.items = this.$menu.querySelectorAll('a, button');
|
|
85
|
+
|
|
86
|
+
this.$menuToggle.addEventListener('click', (event) => {
|
|
87
|
+
this.toggleMenu(event);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
this.$module.addEventListener('keydown', (event) => {
|
|
91
|
+
this.handleKeyDown(event);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
document.addEventListener('click', (event) => {
|
|
95
|
+
if (!this.$module.contains(event.target)) {
|
|
96
|
+
this.closeMenu(false);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
ButtonMenu.prototype.createMenu = function () {
|
|
102
|
+
const $menu = document.createElement('ul');
|
|
103
|
+
$menu.setAttribute('role', 'list');
|
|
104
|
+
$menu.hidden = true;
|
|
105
|
+
$menu.classList.add('moj-button-menu__wrapper');
|
|
106
|
+
if (this.config.alignMenu === 'right') {
|
|
107
|
+
$menu.classList.add('moj-button-menu__wrapper--right');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
this.$module.appendChild($menu);
|
|
111
|
+
while (this.$module.firstChild !== $menu) {
|
|
112
|
+
$menu.appendChild(this.$module.firstChild);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return $menu
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
ButtonMenu.prototype.setupMenuItems = function () {
|
|
119
|
+
Array.from(this.$menu.children).forEach((item) => {
|
|
120
|
+
// wrap item in li tag
|
|
121
|
+
const listItem = document.createElement('li');
|
|
122
|
+
this.$menu.insertBefore(listItem, item);
|
|
123
|
+
listItem.appendChild(item);
|
|
124
|
+
|
|
125
|
+
item.setAttribute('tabindex', -1);
|
|
126
|
+
|
|
127
|
+
if (item.tagName === 'BUTTON') {
|
|
128
|
+
item.setAttribute('type', 'button');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
item.classList.forEach((className) => {
|
|
132
|
+
if (className.startsWith('govuk-button')) {
|
|
133
|
+
item.classList.remove(className);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// add a slight delay after click before closing the menu, makes it *feel* better
|
|
138
|
+
item.addEventListener('click', (event) => {
|
|
139
|
+
setTimeout(() => {
|
|
140
|
+
this.closeMenu(false);
|
|
141
|
+
}, 50);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
ButtonMenu.prototype.toggleTemplate = function () {
|
|
147
|
+
return `
|
|
148
|
+
<button type="button" class="govuk-button moj-button-menu__toggle-button ${this.config.buttonClasses || ''}" aria-haspopup="true" aria-expanded="false">
|
|
133
149
|
<span>
|
|
134
150
|
${this.config.buttonText}
|
|
135
151
|
<svg width="11" height="5" viewBox="0 0 11 5" xmlns="http://www.w3.org/2000/svg">
|
|
136
152
|
<path d="M5.5 0L11 5L0 5L5.5 0Z" fill="currentColor"/>
|
|
137
153
|
</svg>
|
|
138
154
|
</span>
|
|
139
|
-
</button
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
155
|
+
</button>`
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @returns {boolean}
|
|
160
|
+
*/
|
|
161
|
+
ButtonMenu.prototype.isOpen = function () {
|
|
162
|
+
return this.$menuToggle.getAttribute('aria-expanded') === 'true'
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
ButtonMenu.prototype.toggleMenu = function (event) {
|
|
166
|
+
event.preventDefault();
|
|
167
|
+
|
|
168
|
+
// If menu is triggered with mouse don't move focus to first item
|
|
169
|
+
const keyboardEvent = event.detail === 0;
|
|
170
|
+
const focusIndex = keyboardEvent ? 0 : -1;
|
|
171
|
+
|
|
172
|
+
if (this.isOpen()) {
|
|
173
|
+
this.closeMenu();
|
|
174
|
+
} else {
|
|
175
|
+
this.openMenu(focusIndex);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Opens the menu and optionally sets the focus to the item with given index
|
|
181
|
+
*
|
|
182
|
+
* @param {number} focusIndex - The index of the item to focus
|
|
183
|
+
*/
|
|
184
|
+
ButtonMenu.prototype.openMenu = function (focusIndex = 0) {
|
|
185
|
+
this.$menu.hidden = false;
|
|
186
|
+
this.$menuToggle.setAttribute('aria-expanded', 'true');
|
|
187
|
+
if (focusIndex !== -1) {
|
|
188
|
+
this.focusItem(focusIndex);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Closes the menu and optionally returns focus back to menuToggle
|
|
194
|
+
*
|
|
195
|
+
* @param {boolean} moveFocus - whether to return focus to the toggle button
|
|
196
|
+
*/
|
|
197
|
+
ButtonMenu.prototype.closeMenu = function (moveFocus = true) {
|
|
198
|
+
this.$menu.hidden = true;
|
|
199
|
+
this.$menuToggle.setAttribute('aria-expanded', 'false');
|
|
200
|
+
if (moveFocus) {
|
|
201
|
+
this.$menuToggle.focus();
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Focuses the menu item at the specified index
|
|
207
|
+
*
|
|
208
|
+
* @param {number} index - the index of the item to focus
|
|
209
|
+
*/
|
|
210
|
+
ButtonMenu.prototype.focusItem = function (index) {
|
|
211
|
+
if (index >= this.items.length) index = 0;
|
|
212
|
+
if (index < 0) index = this.items.length - 1;
|
|
213
|
+
|
|
214
|
+
const menuItem = this.items.item(index);
|
|
215
|
+
if (menuItem) {
|
|
216
|
+
menuItem.focus();
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
ButtonMenu.prototype.currentFocusIndex = function () {
|
|
221
|
+
const activeElement = document.activeElement;
|
|
222
|
+
const menuItems = Array.from(this.items);
|
|
223
|
+
|
|
224
|
+
return menuItems.indexOf(activeElement)
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
ButtonMenu.prototype.handleKeyDown = function (event) {
|
|
228
|
+
if (event.target === this.$menuToggle) {
|
|
229
|
+
switch (event.key) {
|
|
230
|
+
case 'ArrowDown':
|
|
231
|
+
event.preventDefault();
|
|
232
|
+
this.openMenu();
|
|
233
|
+
break
|
|
234
|
+
case 'ArrowUp':
|
|
235
|
+
event.preventDefault();
|
|
236
|
+
this.openMenu(this.items.length - 1);
|
|
237
|
+
break
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (this.$menu.contains(event.target) && this.isOpen()) {
|
|
242
|
+
switch (event.key) {
|
|
243
|
+
case 'ArrowDown':
|
|
244
|
+
event.preventDefault();
|
|
245
|
+
if (this.currentFocusIndex() !== -1) {
|
|
246
|
+
this.focusItem(this.currentFocusIndex() + 1);
|
|
247
|
+
}
|
|
248
|
+
break
|
|
249
|
+
case 'ArrowUp':
|
|
250
|
+
event.preventDefault();
|
|
251
|
+
if (this.currentFocusIndex() !== -1) {
|
|
252
|
+
this.focusItem(this.currentFocusIndex() - 1);
|
|
253
|
+
}
|
|
254
|
+
break
|
|
255
|
+
case 'Home':
|
|
256
|
+
event.preventDefault();
|
|
257
|
+
this.focusItem(0);
|
|
258
|
+
break
|
|
259
|
+
case 'End':
|
|
260
|
+
event.preventDefault();
|
|
261
|
+
this.focusItem(this.items.length - 1);
|
|
262
|
+
break
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (event.key === 'Escape' && this.isOpen()) {
|
|
267
|
+
this.closeMenu();
|
|
268
|
+
}
|
|
269
|
+
if (event.key === 'Tab' && this.isOpen()) {
|
|
270
|
+
this.closeMenu(false);
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Parse dataset
|
|
276
|
+
*
|
|
277
|
+
* Loop over an object and normalise each value using {@link normaliseString},
|
|
278
|
+
* optionally expanding nested `i18n.field`
|
|
279
|
+
*
|
|
280
|
+
* @param {Schema} schema - component schema
|
|
281
|
+
* @param {DOMStringMap} dataset - HTML element dataset
|
|
282
|
+
* @returns {object} Normalised dataset
|
|
283
|
+
*/
|
|
284
|
+
ButtonMenu.prototype.parseDataset = function (schema, dataset) {
|
|
285
|
+
const parsed = {};
|
|
286
|
+
|
|
287
|
+
for (const [field, ,] of Object.entries(schema.properties)) {
|
|
288
|
+
if (field in dataset) {
|
|
289
|
+
if (dataset[field]) {
|
|
290
|
+
parsed[field] = dataset[field];
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return parsed
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Config merging function
|
|
300
|
+
*
|
|
301
|
+
* Takes any number of objects and combines them together, with
|
|
302
|
+
* greatest priority on the LAST item passed in.
|
|
303
|
+
*
|
|
304
|
+
* @param {...{ [key: string]: unknown }} configObjects - Config objects to merge
|
|
305
|
+
* @returns {{ [key: string]: unknown }} A merged config object
|
|
306
|
+
*/
|
|
307
|
+
ButtonMenu.prototype.mergeConfigs = function (...configObjects) {
|
|
308
|
+
const formattedConfigObject = {};
|
|
309
|
+
|
|
310
|
+
// Loop through each of the passed objects
|
|
311
|
+
for (const configObject of configObjects) {
|
|
312
|
+
for (const key of Object.keys(configObject)) {
|
|
313
|
+
const option = formattedConfigObject[key];
|
|
314
|
+
const override = configObject[key];
|
|
315
|
+
|
|
316
|
+
// Push their keys one-by-one into formattedConfigObject. Any duplicate
|
|
317
|
+
// keys with object values will be merged, otherwise the new value will
|
|
318
|
+
// override the existing value.
|
|
319
|
+
if (typeof option === 'object' && typeof override === 'object') {
|
|
320
|
+
// @ts-expect-error Index signature for type 'string' is missing
|
|
321
|
+
formattedConfigObject[key] = this.mergeConfigs(option, override);
|
|
322
|
+
} else {
|
|
323
|
+
formattedConfigObject[key] = override;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return formattedConfigObject
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
buttonMenu$1 = { ButtonMenu };
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Schema for component config
|
|
335
|
+
*
|
|
336
|
+
* @typedef {object} Schema
|
|
337
|
+
* @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
|
|
338
|
+
*/
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Schema property for component config
|
|
342
|
+
*
|
|
343
|
+
* @typedef {object} SchemaProperty
|
|
344
|
+
* @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
|
|
345
|
+
*/
|
|
346
|
+
return buttonMenu$1;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
var buttonMenuExports = requireButtonMenu();
|
|
350
|
+
var buttonMenu = /*@__PURE__*/getDefaultExportFromCjs(buttonMenuExports);
|
|
351
|
+
|
|
352
|
+
return buttonMenu;
|
|
353
|
+
|
|
354
|
+
}));
|