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