@ministryofjustice/frontend 5.0.0 → 5.1.1

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 (114) hide show
  1. package/moj/all.bundle.js +1598 -1062
  2. package/moj/all.bundle.js.map +1 -1
  3. package/moj/all.bundle.mjs +1894 -1054
  4. package/moj/all.bundle.mjs.map +1 -1
  5. package/moj/all.mjs +7 -90
  6. package/moj/all.mjs.map +1 -1
  7. package/moj/all.scss +1 -0
  8. package/moj/all.scss.map +1 -1
  9. package/moj/common/index.mjs +57 -0
  10. package/moj/common/index.mjs.map +1 -0
  11. package/moj/common/moj-frontend-version.mjs +14 -0
  12. package/moj/common/moj-frontend-version.mjs.map +1 -0
  13. package/moj/components/add-another/add-another.bundle.js +105 -76
  14. package/moj/components/add-another/add-another.bundle.js.map +1 -1
  15. package/moj/components/add-another/add-another.bundle.mjs +222 -71
  16. package/moj/components/add-another/add-another.bundle.mjs.map +1 -1
  17. package/moj/components/add-another/add-another.mjs +103 -72
  18. package/moj/components/add-another/add-another.mjs.map +1 -1
  19. package/moj/components/alert/alert.bundle.js +115 -191
  20. package/moj/components/alert/alert.bundle.js.map +1 -1
  21. package/moj/components/alert/alert.bundle.mjs +354 -186
  22. package/moj/components/alert/alert.bundle.mjs.map +1 -1
  23. package/moj/components/alert/alert.mjs +55 -140
  24. package/moj/components/alert/alert.mjs.map +1 -1
  25. package/moj/components/button-menu/README.md +3 -1
  26. package/moj/components/button-menu/button-menu.bundle.js +91 -120
  27. package/moj/components/button-menu/button-menu.bundle.js.map +1 -1
  28. package/moj/components/button-menu/button-menu.bundle.mjs +329 -114
  29. package/moj/components/button-menu/button-menu.bundle.mjs.map +1 -1
  30. package/moj/components/button-menu/button-menu.mjs +89 -116
  31. package/moj/components/button-menu/button-menu.mjs.map +1 -1
  32. package/moj/components/date-picker/date-picker.bundle.js +174 -154
  33. package/moj/components/date-picker/date-picker.bundle.js.map +1 -1
  34. package/moj/components/date-picker/date-picker.bundle.mjs +411 -147
  35. package/moj/components/date-picker/date-picker.bundle.mjs.map +1 -1
  36. package/moj/components/date-picker/date-picker.mjs +172 -150
  37. package/moj/components/date-picker/date-picker.mjs.map +1 -1
  38. package/moj/components/filter/template.njk +1 -1
  39. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.js +133 -44
  40. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.js.map +1 -1
  41. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.mjs +374 -41
  42. package/moj/components/filter-toggle-button/filter-toggle-button.bundle.mjs.map +1 -1
  43. package/moj/components/filter-toggle-button/filter-toggle-button.mjs +131 -40
  44. package/moj/components/filter-toggle-button/filter-toggle-button.mjs.map +1 -1
  45. package/moj/components/form-validator/form-validator.bundle.js +159 -69
  46. package/moj/components/form-validator/form-validator.bundle.js.map +1 -1
  47. package/moj/components/form-validator/form-validator.bundle.mjs +399 -65
  48. package/moj/components/form-validator/form-validator.bundle.mjs.map +1 -1
  49. package/moj/components/form-validator/form-validator.mjs +134 -54
  50. package/moj/components/form-validator/form-validator.mjs.map +1 -1
  51. package/moj/components/multi-file-upload/multi-file-upload.bundle.js +291 -117
  52. package/moj/components/multi-file-upload/multi-file-upload.bundle.js.map +1 -1
  53. package/moj/components/multi-file-upload/multi-file-upload.bundle.mjs +527 -109
  54. package/moj/components/multi-file-upload/multi-file-upload.bundle.mjs.map +1 -1
  55. package/moj/components/multi-file-upload/multi-file-upload.mjs +288 -101
  56. package/moj/components/multi-file-upload/multi-file-upload.mjs.map +1 -1
  57. package/moj/components/multi-file-upload/template.njk +1 -1
  58. package/moj/components/multi-select/multi-select.bundle.js +106 -41
  59. package/moj/components/multi-select/multi-select.bundle.js.map +1 -1
  60. package/moj/components/multi-select/multi-select.bundle.mjs +346 -37
  61. package/moj/components/multi-select/multi-select.bundle.mjs.map +1 -1
  62. package/moj/components/multi-select/multi-select.mjs +104 -37
  63. package/moj/components/multi-select/multi-select.mjs.map +1 -1
  64. package/moj/components/password-reveal/_password-reveal.scss +3 -1
  65. package/moj/components/password-reveal/_password-reveal.scss.map +1 -1
  66. package/moj/components/password-reveal/password-reveal.bundle.js +32 -29
  67. package/moj/components/password-reveal/password-reveal.bundle.js.map +1 -1
  68. package/moj/components/password-reveal/password-reveal.bundle.mjs +149 -24
  69. package/moj/components/password-reveal/password-reveal.bundle.mjs.map +1 -1
  70. package/moj/components/password-reveal/password-reveal.mjs +30 -25
  71. package/moj/components/password-reveal/password-reveal.mjs.map +1 -1
  72. package/moj/components/rich-text-editor/README.md +4 -3
  73. package/moj/components/rich-text-editor/rich-text-editor.bundle.js +127 -62
  74. package/moj/components/rich-text-editor/rich-text-editor.bundle.js.map +1 -1
  75. package/moj/components/rich-text-editor/rich-text-editor.bundle.mjs +367 -58
  76. package/moj/components/rich-text-editor/rich-text-editor.bundle.mjs.map +1 -1
  77. package/moj/components/rich-text-editor/rich-text-editor.mjs +125 -58
  78. package/moj/components/rich-text-editor/rich-text-editor.mjs.map +1 -1
  79. package/moj/components/search-toggle/search-toggle.bundle.js +94 -26
  80. package/moj/components/search-toggle/search-toggle.bundle.js.map +1 -1
  81. package/moj/components/search-toggle/search-toggle.bundle.mjs +334 -22
  82. package/moj/components/search-toggle/search-toggle.bundle.mjs.map +1 -1
  83. package/moj/components/search-toggle/search-toggle.mjs +92 -22
  84. package/moj/components/search-toggle/search-toggle.mjs.map +1 -1
  85. package/moj/components/sortable-table/_sortable-table.scss +3 -42
  86. package/moj/components/sortable-table/_sortable-table.scss.map +1 -1
  87. package/moj/components/sortable-table/sortable-table.bundle.js +200 -83
  88. package/moj/components/sortable-table/sortable-table.bundle.js.map +1 -1
  89. package/moj/components/sortable-table/sortable-table.bundle.mjs +439 -78
  90. package/moj/components/sortable-table/sortable-table.bundle.mjs.map +1 -1
  91. package/moj/components/sortable-table/sortable-table.mjs +198 -79
  92. package/moj/components/sortable-table/sortable-table.mjs.map +1 -1
  93. package/moj/core/_all.scss +3 -0
  94. package/moj/core/_all.scss.map +1 -0
  95. package/moj/core/_moj-frontend-properties.scss +7 -0
  96. package/moj/core/_moj-frontend-properties.scss.map +1 -0
  97. package/moj/filters/prototype-kit-13-filters.js +4 -3
  98. package/moj/helpers.bundle.js +22 -77
  99. package/moj/helpers.bundle.js.map +1 -1
  100. package/moj/helpers.bundle.mjs +23 -74
  101. package/moj/helpers.bundle.mjs.map +1 -1
  102. package/moj/helpers.mjs +23 -74
  103. package/moj/helpers.mjs.map +1 -1
  104. package/moj/moj-frontend.min.css +1 -1
  105. package/moj/moj-frontend.min.css.map +1 -1
  106. package/moj/moj-frontend.min.js +1 -1
  107. package/moj/moj-frontend.min.js.map +1 -1
  108. package/package.json +1 -1
  109. package/moj/version.bundle.js +0 -12
  110. package/moj/version.bundle.js.map +0 -1
  111. package/moj/version.bundle.mjs +0 -4
  112. package/moj/version.bundle.mjs.map +0 -1
  113. package/moj/version.mjs +0 -4
  114. package/moj/version.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"button-menu.bundle.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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"}
1
+ {"version":3,"file":"button-menu.bundle.mjs","sources":["../../../../node_modules/govuk-frontend/dist/govuk/common/index.mjs","../../../../node_modules/govuk-frontend/dist/govuk/errors/index.mjs","../../../../node_modules/govuk-frontend/dist/govuk/component.mjs","../../../../node_modules/govuk-frontend/dist/govuk/common/configuration.mjs","../../../../src/moj/components/button-menu/button-menu.mjs"],"sourcesContent":["function getFragmentFromUrl(url) {\n if (!url.includes('#')) {\n return undefined;\n }\n return url.split('#').pop();\n}\nfunction getBreakpoint(name) {\n const property = `--govuk-frontend-breakpoint-${name}`;\n const value = window.getComputedStyle(document.documentElement).getPropertyValue(property);\n return {\n property,\n value: value || undefined\n };\n}\nfunction setFocus($element, options = {}) {\n var _options$onBeforeFocu;\n const isFocusable = $element.getAttribute('tabindex');\n if (!isFocusable) {\n $element.setAttribute('tabindex', '-1');\n }\n function onFocus() {\n $element.addEventListener('blur', onBlur, {\n once: true\n });\n }\n function onBlur() {\n var _options$onBlur;\n (_options$onBlur = options.onBlur) == null || _options$onBlur.call($element);\n if (!isFocusable) {\n $element.removeAttribute('tabindex');\n }\n }\n $element.addEventListener('focus', onFocus, {\n once: true\n });\n (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);\n $element.focus();\n}\nfunction isInitialised($root, moduleName) {\n return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);\n}\n\n/**\n * Checks if GOV.UK Frontend is supported on this page\n *\n * Some browsers will load and run our JavaScript but GOV.UK Frontend\n * won't be supported.\n *\n * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support\n * @returns {boolean} Whether GOV.UK Frontend is supported on this page\n */\nfunction isSupported($scope = document.body) {\n if (!$scope) {\n return false;\n }\n return $scope.classList.contains('govuk-frontend-supported');\n}\nfunction isArray(option) {\n return Array.isArray(option);\n}\nfunction isObject(option) {\n return !!option && typeof option === 'object' && !isArray(option);\n}\nfunction formatErrorMessage(Component, message) {\n return `${Component.moduleName}: ${message}`;\n}\n/**\n * @typedef ComponentWithModuleName\n * @property {string} moduleName - Name of the component\n */\n/**\n * @import { ObjectNested } from './configuration.mjs'\n */\n\nexport { formatErrorMessage, getBreakpoint, getFragmentFromUrl, isInitialised, isObject, isSupported, setFocus };\n//# sourceMappingURL=index.mjs.map\n","import { formatErrorMessage } from '../common/index.mjs';\n\nclass GOVUKFrontendError extends Error {\n constructor(...args) {\n super(...args);\n this.name = 'GOVUKFrontendError';\n }\n}\nclass SupportError extends GOVUKFrontendError {\n /**\n * Checks if GOV.UK Frontend is supported on this page\n *\n * @param {HTMLElement | null} [$scope] - HTML element `<body>` checked for browser support\n */\n constructor($scope = document.body) {\n const supportMessage = 'noModule' in HTMLScriptElement.prototype ? 'GOV.UK Frontend initialised without `<body class=\"govuk-frontend-supported\">` from template `<script>` snippet' : 'GOV.UK Frontend is not supported in this browser';\n super($scope ? supportMessage : 'GOV.UK Frontend initialised without `<script type=\"module\">`');\n this.name = 'SupportError';\n }\n}\nclass ConfigError extends GOVUKFrontendError {\n constructor(...args) {\n super(...args);\n this.name = 'ConfigError';\n }\n}\nclass ElementError extends GOVUKFrontendError {\n constructor(messageOrOptions) {\n let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';\n if (typeof messageOrOptions === 'object') {\n const {\n component,\n identifier,\n element,\n expectedType\n } = messageOrOptions;\n message = identifier;\n message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';\n message = formatErrorMessage(component, message);\n }\n super(message);\n this.name = 'ElementError';\n }\n}\nclass InitError extends GOVUKFrontendError {\n constructor(componentOrMessage) {\n const message = typeof componentOrMessage === 'string' ? componentOrMessage : formatErrorMessage(componentOrMessage, `Root element (\\`$root\\`) already initialised`);\n super(message);\n this.name = 'InitError';\n }\n}\n/**\n * @import { ComponentWithModuleName } from '../common/index.mjs'\n */\n\nexport { ConfigError, ElementError, GOVUKFrontendError, InitError, SupportError };\n//# sourceMappingURL=index.mjs.map\n","import { isInitialised, isSupported } from './common/index.mjs';\nimport { InitError, ElementError, SupportError } from './errors/index.mjs';\n\nclass Component {\n /**\n * Returns the root element of the component\n *\n * @protected\n * @returns {RootElementType} - the root element of component\n */\n get $root() {\n return this._$root;\n }\n constructor($root) {\n this._$root = void 0;\n const childConstructor = this.constructor;\n if (typeof childConstructor.moduleName !== 'string') {\n throw new InitError(`\\`moduleName\\` not defined in component`);\n }\n if (!($root instanceof childConstructor.elementType)) {\n throw new ElementError({\n element: $root,\n component: childConstructor,\n identifier: 'Root element (`$root`)',\n expectedType: childConstructor.elementType.name\n });\n } else {\n this._$root = $root;\n }\n childConstructor.checkSupport();\n this.checkInitialised();\n const moduleName = childConstructor.moduleName;\n this.$root.setAttribute(`data-${moduleName}-init`, '');\n }\n checkInitialised() {\n const constructor = this.constructor;\n const moduleName = constructor.moduleName;\n if (moduleName && isInitialised(this.$root, moduleName)) {\n throw new InitError(constructor);\n }\n }\n static checkSupport() {\n if (!isSupported()) {\n throw new SupportError();\n }\n }\n}\n\n/**\n * @typedef ChildClass\n * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component\n */\n\n/**\n * @typedef {typeof Component & ChildClass} ChildClassConstructor\n */\nComponent.elementType = HTMLElement;\n\nexport { Component };\n//# sourceMappingURL=component.mjs.map\n","import { Component } from '../component.mjs';\nimport { ConfigError } from '../errors/index.mjs';\nimport { isObject, formatErrorMessage } from './index.mjs';\n\nconst configOverride = Symbol.for('configOverride');\nclass ConfigurableComponent extends Component {\n [configOverride](param) {\n return {};\n }\n\n /**\n * Returns the root element of the component\n *\n * @protected\n * @returns {ConfigurationType} - the root element of component\n */\n get config() {\n return this._config;\n }\n constructor($root, config) {\n super($root);\n this._config = void 0;\n const childConstructor = this.constructor;\n if (!isObject(childConstructor.defaults)) {\n throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));\n }\n const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);\n this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);\n }\n}\nfunction normaliseString(value, property) {\n const trimmedValue = value ? value.trim() : '';\n let output;\n let outputType = property == null ? void 0 : property.type;\n if (!outputType) {\n if (['true', 'false'].includes(trimmedValue)) {\n outputType = 'boolean';\n }\n if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {\n outputType = 'number';\n }\n }\n switch (outputType) {\n case 'boolean':\n output = trimmedValue === 'true';\n break;\n case 'number':\n output = Number(trimmedValue);\n break;\n default:\n output = value;\n }\n return output;\n}\nfunction normaliseDataset(Component, dataset) {\n if (!isObject(Component.schema)) {\n throw new ConfigError(formatErrorMessage(Component, 'Config passed as parameter into constructor but no schema defined'));\n }\n const out = {};\n const entries = Object.entries(Component.schema.properties);\n for (const entry of entries) {\n const [namespace, property] = entry;\n const field = namespace.toString();\n if (field in dataset) {\n out[field] = normaliseString(dataset[field], property);\n }\n if ((property == null ? void 0 : property.type) === 'object') {\n out[field] = extractConfigByNamespace(Component.schema, dataset, namespace);\n }\n }\n return out;\n}\nfunction mergeConfigs(...configObjects) {\n const formattedConfigObject = {};\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 if (isObject(option) && isObject(override)) {\n formattedConfigObject[key] = mergeConfigs(option, override);\n } else {\n formattedConfigObject[key] = override;\n }\n }\n }\n return formattedConfigObject;\n}\nfunction validateConfig(schema, config) {\n const validationErrors = [];\n for (const [name, conditions] of Object.entries(schema)) {\n const errors = [];\n if (Array.isArray(conditions)) {\n for (const {\n required,\n errorMessage\n } of conditions) {\n if (!required.every(key => !!config[key])) {\n errors.push(errorMessage);\n }\n }\n if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {\n validationErrors.push(...errors);\n }\n }\n }\n return validationErrors;\n}\nfunction extractConfigByNamespace(schema, dataset, namespace) {\n const property = schema.properties[namespace];\n if ((property == null ? void 0 : property.type) !== 'object') {\n return;\n }\n const newObject = {\n [namespace]: {}\n };\n for (const [key, value] of Object.entries(dataset)) {\n let current = newObject;\n const keyParts = key.split('.');\n for (const [index, name] of keyParts.entries()) {\n if (isObject(current)) {\n if (index < keyParts.length - 1) {\n if (!isObject(current[name])) {\n current[name] = {};\n }\n current = current[name];\n } else if (key !== namespace) {\n current[name] = normaliseString(value);\n }\n }\n }\n }\n return newObject[namespace];\n}\n/**\n * Schema for component config\n *\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType\n * @typedef {object} Schema\n * @property {Record<keyof ConfigurationType, SchemaProperty | undefined>} properties - Schema properties\n * @property {SchemaCondition<ConfigurationType>[]} [anyOf] - List of schema conditions\n */\n/**\n * Schema property for component config\n *\n * @typedef {object} SchemaProperty\n * @property {'string' | 'boolean' | 'number' | 'object'} type - Property type\n */\n/**\n * Schema condition for component config\n *\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType\n * @typedef {object} SchemaCondition\n * @property {(keyof ConfigurationType)[]} required - List of required config fields\n * @property {string} errorMessage - Error message when required config fields not provided\n */\n/**\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]\n * @typedef ChildClass\n * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component\n * @property {Schema<ConfigurationType>} [schema] - The schema of the component configuration\n * @property {ConfigurationType} [defaults] - The default values of the configuration of the component\n */\n/**\n * @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]\n * @typedef {typeof Component & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>\n */\n\nexport { ConfigurableComponent, configOverride, extractConfigByNamespace, mergeConfigs, normaliseDataset, normaliseString, validateConfig };\n//# sourceMappingURL=configuration.mjs.map\n","import { ConfigurableComponent } from 'govuk-frontend'\n\n/**\n * @augments {ConfigurableComponent<ButtonMenuConfig>}\n */\nexport class ButtonMenu extends ConfigurableComponent {\n /**\n * @param {Element | null} $root - HTML element to use for button menu\n * @param {ButtonMenuConfig} [config] - Button menu config\n */\n constructor($root, config = {}) {\n super($root, config)\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.$root.children.length === 1) {\n const $button = this.$root.children[0]\n\n $button.classList.forEach((className) => {\n if (className.startsWith('govuk-button-')) {\n $button.classList.remove(className)\n }\n\n $button.classList.remove('moj-button-menu__item')\n $button.classList.add('moj-button-menu__single-button')\n })\n\n if (this.config.buttonClasses) {\n $button.classList.add(...this.config.buttonClasses.split(' '))\n }\n }\n // Otherwise initialise a button menu\n if (this.$root.children.length > 1) {\n this.initMenu()\n }\n }\n\n initMenu() {\n this.$menu = this.createMenu()\n this.$root.insertAdjacentHTML('afterbegin', this.toggleTemplate())\n this.setupMenuItems()\n\n this.$menuToggle = this.$root.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.$root.addEventListener('keydown', (event) => {\n this.handleKeyDown(event)\n })\n\n document.addEventListener('click', (event) => {\n if (event.target instanceof Node && !this.$root.contains(event.target)) {\n this.closeMenu(false)\n }\n })\n }\n\n createMenu() {\n const $menu = document.createElement('ul')\n\n $menu.setAttribute('role', 'list')\n $menu.hidden = true\n $menu.classList.add('moj-button-menu__wrapper')\n\n if (this.config.alignMenu === 'right') {\n $menu.classList.add('moj-button-menu__wrapper--right')\n }\n\n this.$root.appendChild($menu)\n\n while (this.$root.firstChild !== $menu) {\n $menu.appendChild(this.$root.firstChild)\n }\n\n return $menu\n }\n\n setupMenuItems() {\n Array.from(this.$menu.children).forEach(($menuItem) => {\n // wrap item in li tag\n const $listItem = document.createElement('li')\n this.$menu.insertBefore($listItem, $menuItem)\n $listItem.appendChild($menuItem)\n\n $menuItem.setAttribute('tabindex', '-1')\n\n if ($menuItem.tagName === 'BUTTON') {\n $menuItem.setAttribute('type', 'button')\n }\n\n $menuItem.classList.forEach((className) => {\n if (className.startsWith('govuk-button')) {\n $menuItem.classList.remove(className)\n }\n })\n\n // add a slight delay after click before closing the menu, makes it *feel* better\n $menuItem.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 /**\n * @param {MouseEvent} event - Click event\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 (\n ($activeElement instanceof HTMLAnchorElement ||\n $activeElement instanceof HTMLButtonElement) &&\n $menuItems.indexOf($activeElement)\n )\n }\n\n /**\n * @param {KeyboardEvent} event - Keydown event\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 (\n event.target instanceof Node &&\n this.$menu.contains(event.target) &&\n this.isOpen()\n ) {\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 * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'moj-button-menu'\n\n /**\n * Button menu config\n *\n * @type {ButtonMenuConfig}\n */\n static defaults = Object.freeze({\n buttonText: 'Actions',\n alignMenu: 'left',\n buttonClasses: ''\n })\n\n /**\n * Button menu config schema\n *\n * @type {Schema<ButtonMenuConfig>}\n */\n static schema = Object.freeze(\n /** @type {const} */ ({\n properties: {\n buttonText: { type: 'string' },\n buttonClasses: { type: 'string' },\n alignMenu: { type: 'string' }\n }\n })\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\n/**\n * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'\n */\n"],"names":["isInitialised","$root","moduleName","HTMLElement","hasAttribute","isSupported","$scope","document","body","classList","contains","isArray","option","Array","isObject","formatErrorMessage","Component","message","GOVUKFrontendError","Error","constructor","args","name","SupportError","supportMessage","HTMLScriptElement","prototype","ConfigError","ElementError","messageOrOptions","component","identifier","element","expectedType","InitError","componentOrMessage","_$root","childConstructor","elementType","checkSupport","checkInitialised","setAttribute","configOverride","Symbol","for","ConfigurableComponent","param","config","_config","defaults","datasetConfig","normaliseDataset","dataset","mergeConfigs","normaliseString","value","property","trimmedValue","trim","output","outputType","type","includes","length","isFinite","Number","schema","out","entries","Object","properties","entry","namespace","field","toString","extractConfigByNamespace","configObjects","formattedConfigObject","configObject","key","keys","override","newObject","current","keyParts","split","index","ButtonMenu","children","$button","forEach","className","startsWith","remove","add","buttonClasses","initMenu","$menu","createMenu","insertAdjacentHTML","toggleTemplate","setupMenuItems","$menuToggle","querySelector","$items","querySelectorAll","addEventListener","event","toggleMenu","handleKeyDown","target","Node","closeMenu","createElement","hidden","alignMenu","appendChild","firstChild","from","$menuItem","$listItem","insertBefore","tagName","setTimeout","buttonText","isOpen","getAttribute","preventDefault","keyboardEvent","detail","focusIndex","openMenu","focusItem","moveFocus","focus","item","currentFocusIndex","$activeElement","activeElement","$menuItems","HTMLAnchorElement","HTMLButtonElement","indexOf","freeze"],"mappings":"AAqGO,SAASA,aAAaA,CAACC,KAAK,EAAEC,UAAU,EAAE;EAC/C,OACED,KAAK,YAAYE,WAAW,IAC5BF,KAAK,CAACG,YAAY,CAAC,CAAA,KAAA,EAAQF,UAAU,CAAA,KAAA,CAAO,CAAC;AAEjD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASG,WAAWA,CAACC,MAAM,GAAGC,QAAQ,CAACC,IAAI,EAAE;EAClD,IAAI,CAACF,MAAM,EAAE;AACX,IAAA,OAAO,KAAK;AACd;AAEA,EAAA,OAAOA,MAAM,CAACG,SAAS,CAACC,QAAQ,CAAC,0BAA0B,CAAC;AAC9D;AASA,SAASC,OAAOA,CAACC,MAAM,EAAE;AACvB,EAAA,OAAOC,KAAK,CAACF,OAAO,CAACC,MAAM,CAAC;AAC9B;AAUO,SAASE,QAAQA,CAACF,MAAM,EAAE;AAC/B,EAAA,OAAO,CAAC,CAACA,MAAM,IAAI,OAAOA,MAAM,KAAK,QAAQ,IAAI,CAACD,OAAO,CAACC,MAAM,CAAC;AACnE;AAUO,SAASG,kBAAkBA,CAACC,SAAS,EAAEC,OAAO,EAAE;AACrD,EAAA,OAAO,GAAGD,SAAS,CAACd,UAAU,CAAA,EAAA,EAAKe,OAAO,CAAE,CAAA;AAC9C;;ACxIO,MAAMC,kBAAkB,SAASC,KAAK,CAAC;AAAAC,EAAAA,WAAAA,CAAA,GAAAC,IAAA,EAAA;AAAA,IAAA,KAAA,CAAA,GAAAA,IAAA,CAAA;IAAA,IAC5C,CAAAC,IAAI,GAAG,oBAAoB;AAAA;AAC7B;AAKO,MAAMC,YAAY,SAASL,kBAAkB,CAAC;AAGnD;AACF;AACA;AACA;AACA;AACEE,EAAAA,WAAWA,CAACd,MAAM,GAAGC,QAAQ,CAACC,IAAI,EAAE;IAClC,MAAMgB,cAAc,GAClB,UAAU,IAAIC,iBAAiB,CAACC,SAAS,GACrC,gHAAgH,GAChH,kDAAkD;AAExD,IAAA,KAAK,CACHpB,MAAM,GACFkB,cAAc,GACd,8DACN,CAAC;IAAA,IAjBH,CAAAF,IAAI,GAAG,cAAc;AAkBrB;AACF;AAKO,MAAMK,WAAW,SAAST,kBAAkB,CAAC;AAAAE,EAAAA,WAAAA,CAAA,GAAAC,IAAA,EAAA;AAAA,IAAA,KAAA,CAAA,GAAAA,IAAA,CAAA;IAAA,IAClD,CAAAC,IAAI,GAAG,aAAa;AAAA;AACtB;AAKO,MAAMM,YAAY,SAASV,kBAAkB,CAAC;EAmBnDE,WAAWA,CAACS,gBAAgB,EAAE;IAC5B,IAAIZ,OAAO,GAAG,OAAOY,gBAAgB,KAAK,QAAQ,GAAGA,gBAAgB,GAAG,EAAE;AAG1E,IAAA,IAAI,OAAOA,gBAAgB,KAAK,QAAQ,EAAE;MACxC,MAAM;QAAEC,SAAS;QAAEC,UAAU;QAAEC,OAAO;AAAEC,QAAAA;AAAa,OAAC,GAAGJ,gBAAgB;AAEzEZ,MAAAA,OAAO,GAAGc,UAAU;AAGpBd,MAAAA,OAAO,IAAIe,OAAO,GACd,CAAA,gBAAA,EAAmBC,YAAY,IAAZ,IAAAA,GAAAA,YAAY,GAAI,aAAa,CAAE,CAAA,GAClD,YAAY;AAEhBhB,MAAAA,OAAO,GAAGF,kBAAkB,CAACe,SAAS,EAAEb,OAAO,CAAC;AAClD;IAEA,KAAK,CAACA,OAAO,CAAC;IAAA,IAnChB,CAAAK,IAAI,GAAG,cAAc;AAoCrB;AACF;AAKO,MAAMY,SAAS,SAAShB,kBAAkB,CAAC;EAOhDE,WAAWA,CAACe,kBAAkB,EAAE;AAC9B,IAAA,MAAMlB,OAAO,GACX,OAAOkB,kBAAkB,KAAK,QAAQ,GAClCA,kBAAkB,GAClBpB,kBAAkB,CAChBoB,kBAAkB,EAClB,8CACF,CAAC;IAEP,KAAK,CAAClB,OAAO,CAAC;IAAA,IAfhB,CAAAK,IAAI,GAAG,WAAW;AAgBlB;AACF;;AC/GO,MAAMN,SAAS,CAAC;AASrB;AACF;AACA;AACA;AACA;AACA;EACE,IAAIf,KAAKA,GAAG;IACV,OAAO,IAAI,CAACmC,MAAM;AACpB;EAcAhB,WAAWA,CAACnB,KAAK,EAAE;AAAA,IAAA,IAAA,CARnBmC,MAAM,GAAA,MAAA;AASJ,IAAA,MAAMC,gBAAgB,GACpB,IAAI,CAACjB,WACN;AASD,IAAA,IAAI,OAAOiB,gBAAgB,CAACnC,UAAU,KAAK,QAAQ,EAAE;AACnD,MAAA,MAAM,IAAIgC,SAAS,CAAC,CAAA,uCAAA,CAAyC,CAAC;AAChE;AAEA,IAAA,IAAI,EAAEjC,KAAK,YAAYoC,gBAAgB,CAACC,WAAW,CAAC,EAAE;MACpD,MAAM,IAAIV,YAAY,CAAC;AACrBI,QAAAA,OAAO,EAAE/B,KAAK;AACd6B,QAAAA,SAAS,EAAEO,gBAAgB;AAC3BN,QAAAA,UAAU,EAAE,wBAAwB;AACpCE,QAAAA,YAAY,EAAEI,gBAAgB,CAACC,WAAW,CAAChB;AAC7C,OAAC,CAAC;AACJ,KAAC,MAAM;MACL,IAAI,CAACc,MAAM,GAAmCnC,KAAM;AACtD;IAEAoC,gBAAgB,CAACE,YAAY,EAAE;IAE/B,IAAI,CAACC,gBAAgB,EAAE;AAEvB,IAAA,MAAMtC,UAAU,GAAGmC,gBAAgB,CAACnC,UAAU;IAE9C,IAAI,CAACD,KAAK,CAACwC,YAAY,CAAC,QAAQvC,UAAU,CAAA,KAAA,CAAO,EAAE,EAAE,CAAC;AACxD;AAQAsC,EAAAA,gBAAgBA,GAAG;AACjB,IAAA,MAAMpB,WAAW,GAAyC,IAAI,CAACA,WAAY;AAC3E,IAAA,MAAMlB,UAAU,GAAGkB,WAAW,CAAClB,UAAU;IAEzC,IAAIA,UAAU,IAAIF,aAAa,CAAC,IAAI,CAACC,KAAK,EAAEC,UAAU,CAAC,EAAE;AACvD,MAAA,MAAM,IAAIgC,SAAS,CAACd,WAAW,CAAC;AAClC;AACF;EAOA,OAAOmB,YAAYA,GAAG;IACpB,IAAI,CAAClC,WAAW,EAAE,EAAE;MAClB,MAAM,IAAIkB,YAAY,EAAE;AAC1B;AACF;AACF;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AArGaP,SAAS,CAIbsB,WAAW,GAAGnC,WAAW;;ACV3B,MAAMuC,cAAc,GAAGC,MAAM,CAACC,GAAG,CAAC,gBAAgB,CAAA;AAYlD,MAAMC,qBAAqB,SAAS7B,SAAS,CAAC;EAkBnD,CAAC0B,cAAc,CAAEI,CAAAA,KAAK,EAAE;AACtB,IAAA,OAAO,EAAE;AACX;;AAEA;AACF;AACA;AACA;AACA;AACA;EACE,IAAIC,MAAMA,GAAG;IACX,OAAO,IAAI,CAACC,OAAO;AACrB;AAeA5B,EAAAA,WAAWA,CAACnB,KAAK,EAAE8C,MAAM,EAAE;IACzB,KAAK,CAAC9C,KAAK,CAAC;AAAA,IAAA,IAAA,CAVd+C,OAAO,GAAA,MAAA;AAYL,IAAA,MAAMX,gBAAgB,GACqC,IAAI,CAACjB,WAAY;AAE5E,IAAA,IAAI,CAACN,QAAQ,CAACuB,gBAAgB,CAACY,QAAQ,CAAC,EAAE;MACxC,MAAM,IAAItB,WAAW,CACnBZ,kBAAkB,CAChBsB,gBAAgB,EAChB,qEACF,CACF,CAAC;AACH;IAEA,MAAMa,aAAa,GACjBC,gBAAgB,CAACd,gBAAgB,EAAE,IAAI,CAACD,MAAM,CAACgB,OAAO,CACvD;IAED,IAAI,CAACJ,OAAO,GACVK,YAAY,CACVhB,gBAAgB,CAACY,QAAQ,EACzBF,MAAM,IAAN,IAAA,GAAAA,MAAM,GAAI,EAAE,EACZ,IAAI,CAACL,cAAc,CAAC,CAACQ,aAAa,CAAC,EACnCA,aACF,CACD;AACH;AACF;AAkBO,SAASI,eAAeA,CAACC,KAAK,EAAEC,QAAQ,EAAE;EAC/C,MAAMC,YAAY,GAAGF,KAAK,GAAGA,KAAK,CAACG,IAAI,EAAE,GAAG,EAAE;AAE9C,EAAA,IAAIC,MAAM;AACV,EAAA,IAAIC,UAAU,GAAGJ,QAAQ,IAAR,IAAAA,GAAAA,MAAAA,GAAAA,QAAQ,CAAEK,IAAI;EAG/B,IAAI,CAACD,UAAU,EAAE;IACf,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAACE,QAAQ,CAACL,YAAY,CAAC,EAAE;AAC5CG,MAAAA,UAAU,GAAG,SAAS;AACxB;AAIA,IAAA,IAAIH,YAAY,CAACM,MAAM,GAAG,CAAC,IAAIC,QAAQ,CAACC,MAAM,CAACR,YAAY,CAAC,CAAC,EAAE;AAC7DG,MAAAA,UAAU,GAAG,QAAQ;AACvB;AACF;AAEA,EAAA,QAAQA,UAAU;AAChB,IAAA,KAAK,SAAS;MACZD,MAAM,GAAGF,YAAY,KAAK,MAAM;AAChC,MAAA;AAEF,IAAA,KAAK,QAAQ;AACXE,MAAAA,MAAM,GAAGM,MAAM,CAACR,YAAY,CAAC;AAC7B,MAAA;AAEF,IAAA;AACEE,MAAAA,MAAM,GAAGJ,KAAK;AAClB;AAEA,EAAA,OAAOI,MAAM;AACf;AAeO,SAASR,gBAAgBA,CAACnC,SAAS,EAAEoC,OAAO,EAAE;AACnD,EAAA,IAAI,CAACtC,QAAQ,CAACE,SAAS,CAACkD,MAAM,CAAC,EAAE;IAC/B,MAAM,IAAIvC,WAAW,CACnBZ,kBAAkB,CAChBC,SAAS,EACT,mEACF,CACF,CAAC;AACH;EAEA,MAAMmD,GAAG,GAAgC,EAAG;EAC5C,MAAMC,OAAO,GACXC,MAAM,CAACD,OAAO,CAACpD,SAAS,CAACkD,MAAM,CAACI,UAAU,CAC3C;AAGD,EAAA,KAAK,MAAMC,KAAK,IAAIH,OAAO,EAAE;AAC3B,IAAA,MAAM,CAACI,SAAS,EAAEhB,QAAQ,CAAC,GAAGe,KAAK;AAGnC,IAAA,MAAME,KAAK,GAAGD,SAAS,CAACE,QAAQ,EAAE;IAElC,IAAID,KAAK,IAAIrB,OAAO,EAAE;AACpBe,MAAAA,GAAG,CAACM,KAAK,CAAC,GAAGnB,eAAe,CAACF,OAAO,CAACqB,KAAK,CAAC,EAAEjB,QAAQ,CAAC;AACxD;IAMA,IAAI,CAAAA,QAAQ,IAAR,IAAA,GAAA,MAAA,GAAAA,QAAQ,CAAEK,IAAI,MAAK,QAAQ,EAAE;AAC/BM,MAAAA,GAAG,CAACM,KAAK,CAAC,GAAGE,wBAAwB,CACnC3D,SAAS,CAACkD,MAAM,EAChBd,OAAO,EACPoB,SACF,CAAC;AACH;AACF;AAEA,EAAA,OAAOL,GAAG;AACZ;AAYO,SAASd,YAAYA,CAAC,GAAGuB,aAAa,EAAE;EAG7C,MAAMC,qBAAqB,GAAG,EAAE;AAGhC,EAAA,KAAK,MAAMC,YAAY,IAAIF,aAAa,EAAE;IACxC,KAAK,MAAMG,GAAG,IAAIV,MAAM,CAACW,IAAI,CAACF,YAAY,CAAC,EAAE;AAC3C,MAAA,MAAMlE,MAAM,GAAGiE,qBAAqB,CAACE,GAAG,CAAC;AACzC,MAAA,MAAME,QAAQ,GAAGH,YAAY,CAACC,GAAG,CAAC;MAKlC,IAAIjE,QAAQ,CAACF,MAAM,CAAC,IAAIE,QAAQ,CAACmE,QAAQ,CAAC,EAAE;QAC1CJ,qBAAqB,CAACE,GAAG,CAAC,GAAG1B,YAAY,CAACzC,MAAM,EAAEqE,QAAQ,CAAC;AAC7D,OAAC,MAAM;AAELJ,QAAAA,qBAAqB,CAACE,GAAG,CAAC,GAAGE,QAAQ;AACvC;AACF;AACF;AAEA,EAAA,OAAOJ,qBAAqB;AAC9B;AAoDO,SAASF,wBAAwBA,CAACT,MAAM,EAAEd,OAAO,EAAEoB,SAAS,EAAE;AACnE,EAAA,MAAMhB,QAAQ,GAAGU,MAAM,CAACI,UAAU,CAACE,SAAS,CAAC;EAG7C,IAAI,CAAAhB,QAAQ,IAAR,IAAA,GAAA,MAAA,GAAAA,QAAQ,CAAEK,IAAI,MAAK,QAAQ,EAAE;AAC/B,IAAA;AACF;AAGA,EAAA,MAAMqB,SAAS,GAA0D;AACvE,IAAA,CAACV,SAAS,GAAG;AACb,GAAA;AAEF,EAAA,KAAK,MAAM,CAACO,GAAG,EAAExB,KAAK,CAAC,IAAIc,MAAM,CAACD,OAAO,CAAChB,OAAO,CAAC,EAAE;IAElD,IAAI+B,OAAO,GAAGD,SAAS;AAGvB,IAAA,MAAME,QAAQ,GAAGL,GAAG,CAACM,KAAK,CAAC,GAAG,CAAC;IAQ/B,KAAK,MAAM,CAACC,KAAK,EAAEhE,IAAI,CAAC,IAAI8D,QAAQ,CAAChB,OAAO,EAAE,EAAE;AAC9C,MAAA,IAAItD,QAAQ,CAACqE,OAAO,CAAC,EAAE;AAErB,QAAA,IAAIG,KAAK,GAAGF,QAAQ,CAACrB,MAAM,GAAG,CAAC,EAAE;UAE/B,IAAI,CAACjD,QAAQ,CAACqE,OAAO,CAAC7D,IAAI,CAAC,CAAC,EAAE;AAC5B6D,YAAAA,OAAO,CAAC7D,IAAI,CAAC,GAAG,EAAE;AACpB;AAGA6D,UAAAA,OAAO,GAAGA,OAAO,CAAC7D,IAAI,CAAC;AACzB,SAAC,MAAM,IAAIyD,GAAG,KAAKP,SAAS,EAAE;AAE5BW,UAAAA,OAAO,CAAC7D,IAAI,CAAC,GAAGgC,eAAe,CAACC,KAAK,CAAC;AACxC;AACF;AACF;AACF;EAEA,OAAO2B,SAAS,CAACV,SAAS,CAAC;AAC7B;;ACxUA;AACA;AACA;AACO,MAAMe,UAAU,SAAS1C,qBAAqB,CAAC;AACpD;AACF;AACA;AACA;AACEzB,EAAAA,WAAWA,CAACnB,KAAK,EAAE8C,MAAM,GAAG,EAAE,EAAE;AAC9B,IAAA,KAAK,CAAC9C,KAAK,EAAE8C,MAAM,CAAC;;AAEpB;AACA;IACA,IAAI,IAAI,CAAC9C,KAAK,CAACuF,QAAQ,CAACzB,MAAM,KAAK,CAAC,EAAE;MACpC,MAAM0B,OAAO,GAAG,IAAI,CAACxF,KAAK,CAACuF,QAAQ,CAAC,CAAC,CAAC;AAEtCC,MAAAA,OAAO,CAAChF,SAAS,CAACiF,OAAO,CAAEC,SAAS,IAAK;AACvC,QAAA,IAAIA,SAAS,CAACC,UAAU,CAAC,eAAe,CAAC,EAAE;AACzCH,UAAAA,OAAO,CAAChF,SAAS,CAACoF,MAAM,CAACF,SAAS,CAAC;AACrC;AAEAF,QAAAA,OAAO,CAAChF,SAAS,CAACoF,MAAM,CAAC,uBAAuB,CAAC;AACjDJ,QAAAA,OAAO,CAAChF,SAAS,CAACqF,GAAG,CAAC,gCAAgC,CAAC;AACzD,OAAC,CAAC;AAEF,MAAA,IAAI,IAAI,CAAC/C,MAAM,CAACgD,aAAa,EAAE;AAC7BN,QAAAA,OAAO,CAAChF,SAAS,CAACqF,GAAG,CAAC,GAAG,IAAI,CAAC/C,MAAM,CAACgD,aAAa,CAACV,KAAK,CAAC,GAAG,CAAC,CAAC;AAChE;AACF;AACA;IACA,IAAI,IAAI,CAACpF,KAAK,CAACuF,QAAQ,CAACzB,MAAM,GAAG,CAAC,EAAE;MAClC,IAAI,CAACiC,QAAQ,EAAE;AACjB;AACF;AAEAA,EAAAA,QAAQA,GAAG;AACT,IAAA,IAAI,CAACC,KAAK,GAAG,IAAI,CAACC,UAAU,EAAE;AAC9B,IAAA,IAAI,CAACjG,KAAK,CAACkG,kBAAkB,CAAC,YAAY,EAAE,IAAI,CAACC,cAAc,EAAE,CAAC;IAClE,IAAI,CAACC,cAAc,EAAE;IAErB,IAAI,CAACC,WAAW,GAAG,IAAI,CAACrG,KAAK,CAACsG,aAAa,CAAC,iBAAiB,CAAC;IAC9D,IAAI,CAACC,MAAM,GAAG,IAAI,CAACP,KAAK,CAACQ,gBAAgB,CAAC,WAAW,CAAC;IAEtD,IAAI,CAACH,WAAW,CAACI,gBAAgB,CAAC,OAAO,EAAGC,KAAK,IAAK;AACpD,MAAA,IAAI,CAACC,UAAU,CAACD,KAAK,CAAC;AACxB,KAAC,CAAC;IAEF,IAAI,CAAC1G,KAAK,CAACyG,gBAAgB,CAAC,SAAS,EAAGC,KAAK,IAAK;AAChD,MAAA,IAAI,CAACE,aAAa,CAACF,KAAK,CAAC;AAC3B,KAAC,CAAC;AAEFpG,IAAAA,QAAQ,CAACmG,gBAAgB,CAAC,OAAO,EAAGC,KAAK,IAAK;AAC5C,MAAA,IAAIA,KAAK,CAACG,MAAM,YAAYC,IAAI,IAAI,CAAC,IAAI,CAAC9G,KAAK,CAACS,QAAQ,CAACiG,KAAK,CAACG,MAAM,CAAC,EAAE;AACtE,QAAA,IAAI,CAACE,SAAS,CAAC,KAAK,CAAC;AACvB;AACF,KAAC,CAAC;AACJ;AAEAd,EAAAA,UAAUA,GAAG;AACX,IAAA,MAAMD,KAAK,GAAG1F,QAAQ,CAAC0G,aAAa,CAAC,IAAI,CAAC;AAE1ChB,IAAAA,KAAK,CAACxD,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC;IAClCwD,KAAK,CAACiB,MAAM,GAAG,IAAI;AACnBjB,IAAAA,KAAK,CAACxF,SAAS,CAACqF,GAAG,CAAC,0BAA0B,CAAC;AAE/C,IAAA,IAAI,IAAI,CAAC/C,MAAM,CAACoE,SAAS,KAAK,OAAO,EAAE;AACrClB,MAAAA,KAAK,CAACxF,SAAS,CAACqF,GAAG,CAAC,iCAAiC,CAAC;AACxD;AAEA,IAAA,IAAI,CAAC7F,KAAK,CAACmH,WAAW,CAACnB,KAAK,CAAC;AAE7B,IAAA,OAAO,IAAI,CAAChG,KAAK,CAACoH,UAAU,KAAKpB,KAAK,EAAE;MACtCA,KAAK,CAACmB,WAAW,CAAC,IAAI,CAACnH,KAAK,CAACoH,UAAU,CAAC;AAC1C;AAEA,IAAA,OAAOpB,KAAK;AACd;AAEAI,EAAAA,cAAcA,GAAG;AACfxF,IAAAA,KAAK,CAACyG,IAAI,CAAC,IAAI,CAACrB,KAAK,CAACT,QAAQ,CAAC,CAACE,OAAO,CAAE6B,SAAS,IAAK;AACrD;AACA,MAAA,MAAMC,SAAS,GAAGjH,QAAQ,CAAC0G,aAAa,CAAC,IAAI,CAAC;MAC9C,IAAI,CAAChB,KAAK,CAACwB,YAAY,CAACD,SAAS,EAAED,SAAS,CAAC;AAC7CC,MAAAA,SAAS,CAACJ,WAAW,CAACG,SAAS,CAAC;AAEhCA,MAAAA,SAAS,CAAC9E,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC;AAExC,MAAA,IAAI8E,SAAS,CAACG,OAAO,KAAK,QAAQ,EAAE;AAClCH,QAAAA,SAAS,CAAC9E,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC;AAC1C;AAEA8E,MAAAA,SAAS,CAAC9G,SAAS,CAACiF,OAAO,CAAEC,SAAS,IAAK;AACzC,QAAA,IAAIA,SAAS,CAACC,UAAU,CAAC,cAAc,CAAC,EAAE;AACxC2B,UAAAA,SAAS,CAAC9G,SAAS,CAACoF,MAAM,CAACF,SAAS,CAAC;AACvC;AACF,OAAC,CAAC;;AAEF;AACA4B,MAAAA,SAAS,CAACb,gBAAgB,CAAC,OAAO,EAAE,MAAM;AACxCiB,QAAAA,UAAU,CAAC,MAAM;AACf,UAAA,IAAI,CAACX,SAAS,CAAC,KAAK,CAAC;SACtB,EAAE,EAAE,CAAC;AACR,OAAC,CAAC;AACJ,KAAC,CAAC;AACJ;AAEAZ,EAAAA,cAAcA,GAAG;IACf,OAAO;AACX,6EAAA,EAA+E,IAAI,CAACrD,MAAM,CAACgD,aAAa,IAAI,EAAE,CAAA;AAC9G;AACA,OAAA,EAAS,IAAI,CAAChD,MAAM,CAAC6E,UAAU;AAC/B;AACA;AACA;AACA;AACA,aAAc,CAAA;AACZ;;AAEA;AACF;AACA;AACEC,EAAAA,MAAMA,GAAG;IACP,OAAO,IAAI,CAACvB,WAAW,CAACwB,YAAY,CAAC,eAAe,CAAC,KAAK,MAAM;AAClE;;AAEA;AACF;AACA;EACElB,UAAUA,CAACD,KAAK,EAAE;IAChBA,KAAK,CAACoB,cAAc,EAAE;;AAEtB;AACA,IAAA,MAAMC,aAAa,GAAGrB,KAAK,CAACsB,MAAM,KAAK,CAAC;AACxC,IAAA,MAAMC,UAAU,GAAGF,aAAa,GAAG,CAAC,GAAG,EAAE;AAEzC,IAAA,IAAI,IAAI,CAACH,MAAM,EAAE,EAAE;MACjB,IAAI,CAACb,SAAS,EAAE;AAClB,KAAC,MAAM;AACL,MAAA,IAAI,CAACmB,QAAQ,CAACD,UAAU,CAAC;AAC3B;AACF;;AAEA;AACF;AACA;AACA;AACA;AACEC,EAAAA,QAAQA,CAACD,UAAU,GAAG,CAAC,EAAE;AACvB,IAAA,IAAI,CAACjC,KAAK,CAACiB,MAAM,GAAG,KAAK;IACzB,IAAI,CAACZ,WAAW,CAAC7D,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC;AACtD,IAAA,IAAIyF,UAAU,KAAK,EAAE,EAAE;AACrB,MAAA,IAAI,CAACE,SAAS,CAACF,UAAU,CAAC;AAC5B;AACF;;AAEA;AACF;AACA;AACA;AACA;AACElB,EAAAA,SAASA,CAACqB,SAAS,GAAG,IAAI,EAAE;AAC1B,IAAA,IAAI,CAACpC,KAAK,CAACiB,MAAM,GAAG,IAAI;IACxB,IAAI,CAACZ,WAAW,CAAC7D,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC;AACvD,IAAA,IAAI4F,SAAS,EAAE;AACb,MAAA,IAAI,CAAC/B,WAAW,CAACgC,KAAK,EAAE;AAC1B;AACF;;AAEA;AACF;AACA;AACA;AACA;EACEF,SAASA,CAAC9C,KAAK,EAAE;IACf,IAAIA,KAAK,IAAI,IAAI,CAACkB,MAAM,CAACzC,MAAM,EAAEuB,KAAK,GAAG,CAAC;AAC1C,IAAA,IAAIA,KAAK,GAAG,CAAC,EAAEA,KAAK,GAAG,IAAI,CAACkB,MAAM,CAACzC,MAAM,GAAG,CAAC;IAE7C,MAAMwD,SAAS,GAAG,IAAI,CAACf,MAAM,CAAC+B,IAAI,CAACjD,KAAK,CAAC;AACzC,IAAA,IAAIiC,SAAS,EAAE;MACbA,SAAS,CAACe,KAAK,EAAE;AACnB;AACF;AAEAE,EAAAA,iBAAiBA,GAAG;AAClB,IAAA,MAAMC,cAAc,GAAGlI,QAAQ,CAACmI,aAAa;IAC7C,MAAMC,UAAU,GAAG9H,KAAK,CAACyG,IAAI,CAAC,IAAI,CAACd,MAAM,CAAC;AAE1C,IAAA,OACE,CAACiC,cAAc,YAAYG,iBAAiB,IAC1CH,cAAc,YAAYI,iBAAiB,KAC7CF,UAAU,CAACG,OAAO,CAACL,cAAc,CAAC;AAEtC;;AAEA;AACF;AACA;EACE5B,aAAaA,CAACF,KAAK,EAAE;AACnB,IAAA,IAAIA,KAAK,CAACG,MAAM,KAAK,IAAI,CAACR,WAAW,EAAE;MACrC,QAAQK,KAAK,CAAC5B,GAAG;AACf,QAAA,KAAK,WAAW;UACd4B,KAAK,CAACoB,cAAc,EAAE;UACtB,IAAI,CAACI,QAAQ,EAAE;AACf,UAAA;AACF,QAAA,KAAK,SAAS;UACZxB,KAAK,CAACoB,cAAc,EAAE;UACtB,IAAI,CAACI,QAAQ,CAAC,IAAI,CAAC3B,MAAM,CAACzC,MAAM,GAAG,CAAC,CAAC;AACrC,UAAA;AACJ;AACF;IAEA,IACE4C,KAAK,CAACG,MAAM,YAAYC,IAAI,IAC5B,IAAI,CAACd,KAAK,CAACvF,QAAQ,CAACiG,KAAK,CAACG,MAAM,CAAC,IACjC,IAAI,CAACe,MAAM,EAAE,EACb;MACA,QAAQlB,KAAK,CAAC5B,GAAG;AACf,QAAA,KAAK,WAAW;UACd4B,KAAK,CAACoB,cAAc,EAAE;UACtB,IAAI,IAAI,CAACS,iBAAiB,EAAE,KAAK,EAAE,EAAE;YACnC,IAAI,CAACJ,SAAS,CAAC,IAAI,CAACI,iBAAiB,EAAE,GAAG,CAAC,CAAC;AAC9C;AACA,UAAA;AACF,QAAA,KAAK,SAAS;UACZ7B,KAAK,CAACoB,cAAc,EAAE;UACtB,IAAI,IAAI,CAACS,iBAAiB,EAAE,KAAK,EAAE,EAAE;YACnC,IAAI,CAACJ,SAAS,CAAC,IAAI,CAACI,iBAAiB,EAAE,GAAG,CAAC,CAAC;AAC9C;AACA,UAAA;AACF,QAAA,KAAK,MAAM;UACT7B,KAAK,CAACoB,cAAc,EAAE;AACtB,UAAA,IAAI,CAACK,SAAS,CAAC,CAAC,CAAC;AACjB,UAAA;AACF,QAAA,KAAK,KAAK;UACRzB,KAAK,CAACoB,cAAc,EAAE;UACtB,IAAI,CAACK,SAAS,CAAC,IAAI,CAAC5B,MAAM,CAACzC,MAAM,GAAG,CAAC,CAAC;AACtC,UAAA;AACJ;AACF;IAEA,IAAI4C,KAAK,CAAC5B,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC8C,MAAM,EAAE,EAAE;MAC3C,IAAI,CAACb,SAAS,EAAE;AAClB;IACA,IAAIL,KAAK,CAAC5B,GAAG,KAAK,KAAK,IAAI,IAAI,CAAC8C,MAAM,EAAE,EAAE;AACxC,MAAA,IAAI,CAACb,SAAS,CAAC,KAAK,CAAC;AACvB;AACF;;AAEA;AACF;AACA;AA4BA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AA9RazB,UAAU,CAwPdrF,UAAU,GAAG,iBAAiB;AAErC;AACF;AACA;AACA;AACA;AA9PaqF,UAAU,CA+PdtC,QAAQ,GAAGoB,MAAM,CAAC0E,MAAM,CAAC;AAC9BnB,EAAAA,UAAU,EAAE,SAAS;AACrBT,EAAAA,SAAS,EAAE,MAAM;AACjBpB,EAAAA,aAAa,EAAE;AACjB,CAAC,CAAC;AAEF;AACF;AACA;AACA;AACA;AAzQaR,UAAU,CA0QdrB,MAAM,GAAGG,MAAM,CAAC0E,MAAM,qBACL;AACpBzE,EAAAA,UAAU,EAAE;AACVsD,IAAAA,UAAU,EAAE;AAAE/D,MAAAA,IAAI,EAAE;KAAU;AAC9BkC,IAAAA,aAAa,EAAE;AAAElC,MAAAA,IAAI,EAAE;KAAU;AACjCsD,IAAAA,SAAS,EAAE;AAAEtD,MAAAA,IAAI,EAAE;AAAS;AAC9B;AACF,CACF,CAAC;;;;","x_google_ignoreList":[0,1,2,3]}
@@ -1,68 +1,50 @@
1
- class ButtonMenu {
1
+ import { ConfigurableComponent } from 'govuk-frontend';
2
+
3
+ /**
4
+ * @augments {ConfigurableComponent<ButtonMenuConfig>}
5
+ */
6
+ class ButtonMenu extends ConfigurableComponent {
2
7
  /**
3
- * @param {Element | null} $module - HTML element to use for button menu
8
+ * @param {Element | null} $root - HTML element to use for button menu
4
9
  * @param {ButtonMenuConfig} [config] - Button menu config
5
10
  */
6
- constructor($module, config = {}) {
7
- if (!$module || !($module instanceof HTMLElement)) {
8
- return this;
9
- }
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
- }
21
- }
22
- });
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;
11
+ constructor($root, config = {}) {
12
+ super($root, config);
31
13
 
32
14
  // If only one button is provided, don't initiate a menu and toggle button
33
15
  // 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 => {
16
+ if (this.$root.children.length === 1) {
17
+ const $button = this.$root.children[0];
18
+ $button.classList.forEach(className => {
37
19
  if (className.startsWith('govuk-button-')) {
38
- button.classList.remove(className);
20
+ $button.classList.remove(className);
39
21
  }
40
- button.classList.remove('moj-button-menu__item');
41
- button.classList.add('moj-button-menu__single-button');
22
+ $button.classList.remove('moj-button-menu__item');
23
+ $button.classList.add('moj-button-menu__single-button');
42
24
  });
43
25
  if (this.config.buttonClasses) {
44
- button.classList.add(...this.config.buttonClasses.split(' '));
26
+ $button.classList.add(...this.config.buttonClasses.split(' '));
45
27
  }
46
28
  }
47
- // Otherwise intialise a button menu
48
- if (this.$module.children.length > 1) {
29
+ // Otherwise initialise a button menu
30
+ if (this.$root.children.length > 1) {
49
31
  this.initMenu();
50
32
  }
51
33
  }
52
34
  initMenu() {
53
35
  this.$menu = this.createMenu();
54
- this.$module.insertAdjacentHTML('afterbegin', this.toggleTemplate());
36
+ this.$root.insertAdjacentHTML('afterbegin', this.toggleTemplate());
55
37
  this.setupMenuItems();
56
- this.$menuToggle = this.$module.querySelector(':scope > button');
57
- this.items = this.$menu.querySelectorAll('a, button');
38
+ this.$menuToggle = this.$root.querySelector(':scope > button');
39
+ this.$items = this.$menu.querySelectorAll('a, button');
58
40
  this.$menuToggle.addEventListener('click', event => {
59
41
  this.toggleMenu(event);
60
42
  });
61
- this.$module.addEventListener('keydown', event => {
43
+ this.$root.addEventListener('keydown', event => {
62
44
  this.handleKeyDown(event);
63
45
  });
64
46
  document.addEventListener('click', event => {
65
- if (!this.$module.contains(event.target)) {
47
+ if (event.target instanceof Node && !this.$root.contains(event.target)) {
66
48
  this.closeMenu(false);
67
49
  }
68
50
  });
@@ -75,30 +57,30 @@ class ButtonMenu {
75
57
  if (this.config.alignMenu === 'right') {
76
58
  $menu.classList.add('moj-button-menu__wrapper--right');
77
59
  }
78
- this.$module.appendChild($menu);
79
- while (this.$module.firstChild !== $menu) {
80
- $menu.appendChild(this.$module.firstChild);
60
+ this.$root.appendChild($menu);
61
+ while (this.$root.firstChild !== $menu) {
62
+ $menu.appendChild(this.$root.firstChild);
81
63
  }
82
64
  return $menu;
83
65
  }
84
66
  setupMenuItems() {
85
- Array.from(this.$menu.children).forEach(item => {
67
+ Array.from(this.$menu.children).forEach($menuItem => {
86
68
  // 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');
69
+ const $listItem = document.createElement('li');
70
+ this.$menu.insertBefore($listItem, $menuItem);
71
+ $listItem.appendChild($menuItem);
72
+ $menuItem.setAttribute('tabindex', '-1');
73
+ if ($menuItem.tagName === 'BUTTON') {
74
+ $menuItem.setAttribute('type', 'button');
93
75
  }
94
- item.classList.forEach(className => {
76
+ $menuItem.classList.forEach(className => {
95
77
  if (className.startsWith('govuk-button')) {
96
- item.classList.remove(className);
78
+ $menuItem.classList.remove(className);
97
79
  }
98
80
  });
99
81
 
100
82
  // add a slight delay after click before closing the menu, makes it *feel* better
101
- item.addEventListener('click', () => {
83
+ $menuItem.addEventListener('click', () => {
102
84
  setTimeout(() => {
103
85
  this.closeMenu(false);
104
86
  }, 50);
@@ -123,6 +105,10 @@ class ButtonMenu {
123
105
  isOpen() {
124
106
  return this.$menuToggle.getAttribute('aria-expanded') === 'true';
125
107
  }
108
+
109
+ /**
110
+ * @param {MouseEvent} event - Click event
111
+ */
126
112
  toggleMenu(event) {
127
113
  event.preventDefault();
128
114
 
@@ -168,18 +154,22 @@ class ButtonMenu {
168
154
  * @param {number} index - the index of the item to focus
169
155
  */
170
156
  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();
157
+ if (index >= this.$items.length) index = 0;
158
+ if (index < 0) index = this.$items.length - 1;
159
+ const $menuItem = this.$items.item(index);
160
+ if ($menuItem) {
161
+ $menuItem.focus();
176
162
  }
177
163
  }
178
164
  currentFocusIndex() {
179
- const activeElement = document.activeElement;
180
- const menuItems = Array.from(this.items);
181
- return menuItems.indexOf(activeElement);
165
+ const $activeElement = document.activeElement;
166
+ const $menuItems = Array.from(this.$items);
167
+ return ($activeElement instanceof HTMLAnchorElement || $activeElement instanceof HTMLButtonElement) && $menuItems.indexOf($activeElement);
182
168
  }
169
+
170
+ /**
171
+ * @param {KeyboardEvent} event - Keydown event
172
+ */
183
173
  handleKeyDown(event) {
184
174
  if (event.target === this.$menuToggle) {
185
175
  switch (event.key) {
@@ -189,11 +179,11 @@ class ButtonMenu {
189
179
  break;
190
180
  case 'ArrowUp':
191
181
  event.preventDefault();
192
- this.openMenu(this.items.length - 1);
182
+ this.openMenu(this.$items.length - 1);
193
183
  break;
194
184
  }
195
185
  }
196
- if (this.$menu.contains(event.target) && this.isOpen()) {
186
+ if (event.target instanceof Node && this.$menu.contains(event.target) && this.isOpen()) {
197
187
  switch (event.key) {
198
188
  case 'ArrowDown':
199
189
  event.preventDefault();
@@ -213,7 +203,7 @@ class ButtonMenu {
213
203
  break;
214
204
  case 'End':
215
205
  event.preventDefault();
216
- this.focusItem(this.items.length - 1);
206
+ this.focusItem(this.$items.length - 1);
217
207
  break;
218
208
  }
219
209
  }
@@ -226,58 +216,8 @@ class ButtonMenu {
226
216
  }
227
217
 
228
218
  /**
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
219
+ * Name for the component used when initialising using data-module attributes.
237
220
  */
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
- }
245
- }
246
- }
247
- return parsed;
248
- }
249
-
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
- }
277
- }
278
- }
279
- return formattedConfigObject;
280
- }
281
221
  }
282
222
 
283
223
  /**
@@ -287,5 +227,38 @@ class ButtonMenu {
287
227
  * @property {string} [buttonClasses='govuk-button--secondary'] - css classes applied to the toggle button
288
228
  */
289
229
 
230
+ /**
231
+ * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'
232
+ */
233
+ ButtonMenu.moduleName = 'moj-button-menu';
234
+ /**
235
+ * Button menu config
236
+ *
237
+ * @type {ButtonMenuConfig}
238
+ */
239
+ ButtonMenu.defaults = Object.freeze({
240
+ buttonText: 'Actions',
241
+ alignMenu: 'left',
242
+ buttonClasses: ''
243
+ });
244
+ /**
245
+ * Button menu config schema
246
+ *
247
+ * @type {Schema<ButtonMenuConfig>}
248
+ */
249
+ ButtonMenu.schema = Object.freeze(/** @type {const} */{
250
+ properties: {
251
+ buttonText: {
252
+ type: 'string'
253
+ },
254
+ buttonClasses: {
255
+ type: 'string'
256
+ },
257
+ alignMenu: {
258
+ type: 'string'
259
+ }
260
+ }
261
+ });
262
+
290
263
  export { ButtonMenu };
291
264
  //# sourceMappingURL=button-menu.mjs.map
@@ -1 +1 @@
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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"}
1
+ {"version":3,"file":"button-menu.mjs","sources":["../../../../src/moj/components/button-menu/button-menu.mjs"],"sourcesContent":["import { ConfigurableComponent } from 'govuk-frontend'\n\n/**\n * @augments {ConfigurableComponent<ButtonMenuConfig>}\n */\nexport class ButtonMenu extends ConfigurableComponent {\n /**\n * @param {Element | null} $root - HTML element to use for button menu\n * @param {ButtonMenuConfig} [config] - Button menu config\n */\n constructor($root, config = {}) {\n super($root, config)\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.$root.children.length === 1) {\n const $button = this.$root.children[0]\n\n $button.classList.forEach((className) => {\n if (className.startsWith('govuk-button-')) {\n $button.classList.remove(className)\n }\n\n $button.classList.remove('moj-button-menu__item')\n $button.classList.add('moj-button-menu__single-button')\n })\n\n if (this.config.buttonClasses) {\n $button.classList.add(...this.config.buttonClasses.split(' '))\n }\n }\n // Otherwise initialise a button menu\n if (this.$root.children.length > 1) {\n this.initMenu()\n }\n }\n\n initMenu() {\n this.$menu = this.createMenu()\n this.$root.insertAdjacentHTML('afterbegin', this.toggleTemplate())\n this.setupMenuItems()\n\n this.$menuToggle = this.$root.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.$root.addEventListener('keydown', (event) => {\n this.handleKeyDown(event)\n })\n\n document.addEventListener('click', (event) => {\n if (event.target instanceof Node && !this.$root.contains(event.target)) {\n this.closeMenu(false)\n }\n })\n }\n\n createMenu() {\n const $menu = document.createElement('ul')\n\n $menu.setAttribute('role', 'list')\n $menu.hidden = true\n $menu.classList.add('moj-button-menu__wrapper')\n\n if (this.config.alignMenu === 'right') {\n $menu.classList.add('moj-button-menu__wrapper--right')\n }\n\n this.$root.appendChild($menu)\n\n while (this.$root.firstChild !== $menu) {\n $menu.appendChild(this.$root.firstChild)\n }\n\n return $menu\n }\n\n setupMenuItems() {\n Array.from(this.$menu.children).forEach(($menuItem) => {\n // wrap item in li tag\n const $listItem = document.createElement('li')\n this.$menu.insertBefore($listItem, $menuItem)\n $listItem.appendChild($menuItem)\n\n $menuItem.setAttribute('tabindex', '-1')\n\n if ($menuItem.tagName === 'BUTTON') {\n $menuItem.setAttribute('type', 'button')\n }\n\n $menuItem.classList.forEach((className) => {\n if (className.startsWith('govuk-button')) {\n $menuItem.classList.remove(className)\n }\n })\n\n // add a slight delay after click before closing the menu, makes it *feel* better\n $menuItem.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 /**\n * @param {MouseEvent} event - Click event\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 (\n ($activeElement instanceof HTMLAnchorElement ||\n $activeElement instanceof HTMLButtonElement) &&\n $menuItems.indexOf($activeElement)\n )\n }\n\n /**\n * @param {KeyboardEvent} event - Keydown event\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 (\n event.target instanceof Node &&\n this.$menu.contains(event.target) &&\n this.isOpen()\n ) {\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 * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'moj-button-menu'\n\n /**\n * Button menu config\n *\n * @type {ButtonMenuConfig}\n */\n static defaults = Object.freeze({\n buttonText: 'Actions',\n alignMenu: 'left',\n buttonClasses: ''\n })\n\n /**\n * Button menu config schema\n *\n * @type {Schema<ButtonMenuConfig>}\n */\n static schema = Object.freeze(\n /** @type {const} */ ({\n properties: {\n buttonText: { type: 'string' },\n buttonClasses: { type: 'string' },\n alignMenu: { type: 'string' }\n }\n })\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\n/**\n * @import { Schema } from 'govuk-frontend/dist/govuk/common/configuration.mjs'\n */\n"],"names":["ButtonMenu","ConfigurableComponent","constructor","$root","config","children","length","$button","classList","forEach","className","startsWith","remove","add","buttonClasses","split","initMenu","$menu","createMenu","insertAdjacentHTML","toggleTemplate","setupMenuItems","$menuToggle","querySelector","$items","querySelectorAll","addEventListener","event","toggleMenu","handleKeyDown","document","target","Node","contains","closeMenu","createElement","setAttribute","hidden","alignMenu","appendChild","firstChild","Array","from","$menuItem","$listItem","insertBefore","tagName","setTimeout","buttonText","isOpen","getAttribute","preventDefault","keyboardEvent","detail","focusIndex","openMenu","focusItem","moveFocus","focus","index","item","currentFocusIndex","$activeElement","activeElement","$menuItems","HTMLAnchorElement","HTMLButtonElement","indexOf","key","moduleName","defaults","Object","freeze","schema","properties","type"],"mappings":"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"}