govuk_publishing_components 44.1.0 → 44.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/govuk_publishing_components/components/_share-links.scss +32 -0
  3. data/app/views/govuk_publishing_components/components/_share_links.html.erb +4 -1
  4. data/app/views/govuk_publishing_components/components/docs/share_links.yml +36 -0
  5. data/lib/govuk_publishing_components/version.rb +1 -1
  6. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +336 -225
  7. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js.map +1 -1
  8. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +334 -226
  9. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs.map +1 -1
  10. data/node_modules/govuk-frontend/dist/govuk/all.mjs +3 -0
  11. data/node_modules/govuk-frontend/dist/govuk/all.mjs.map +1 -1
  12. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest.svg +1 -0
  13. data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs +1 -1
  14. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs +21 -1
  15. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs.map +1 -1
  16. data/node_modules/govuk-frontend/dist/govuk/components/_index.scss +1 -0
  17. data/node_modules/govuk-frontend/dist/govuk/components/_index.scss.map +1 -1
  18. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +92 -26
  19. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js.map +1 -1
  20. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +92 -26
  21. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs.map +1 -1
  22. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +12 -21
  23. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs.map +1 -1
  24. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +86 -20
  25. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js.map +1 -1
  26. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +86 -20
  27. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs.map +1 -1
  28. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs +6 -16
  29. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs.map +1 -1
  30. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +89 -23
  31. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js.map +1 -1
  32. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +89 -23
  33. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs.map +1 -1
  34. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +10 -19
  35. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs.map +1 -1
  36. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +113 -47
  37. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js.map +1 -1
  38. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +113 -47
  39. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs.map +1 -1
  40. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs +7 -16
  41. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs.map +1 -1
  42. data/node_modules/govuk-frontend/dist/govuk/components/details/_index.scss +7 -2
  43. data/node_modules/govuk-frontend/dist/govuk/components/details/_index.scss.map +1 -1
  44. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +86 -20
  45. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js.map +1 -1
  46. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +86 -20
  47. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs.map +1 -1
  48. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs +6 -16
  49. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs.map +1 -1
  50. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +87 -21
  51. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js.map +1 -1
  52. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +87 -21
  53. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs.map +1 -1
  54. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs +7 -16
  55. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs.map +1 -1
  56. data/node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss +8 -10
  57. data/node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss.map +1 -1
  58. data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss +8 -0
  59. data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss.map +1 -1
  60. data/node_modules/govuk-frontend/dist/govuk/components/header/fixtures.json +12 -0
  61. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js +87 -21
  62. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js.map +1 -1
  63. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs +87 -21
  64. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs.map +1 -1
  65. data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs +7 -16
  66. data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs.map +1 -1
  67. data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-full-width-border.html +24 -0
  68. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +86 -20
  69. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js.map +1 -1
  70. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +86 -20
  71. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs.map +1 -1
  72. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs +6 -16
  73. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs.map +1 -1
  74. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +89 -23
  75. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js.map +1 -1
  76. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +89 -23
  77. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs.map +1 -1
  78. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs +9 -18
  79. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs.map +1 -1
  80. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +113 -47
  81. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js.map +1 -1
  82. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +113 -47
  83. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs.map +1 -1
  84. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs +7 -16
  85. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs.map +1 -1
  86. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/README.md +15 -0
  87. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_index.scss +168 -0
  88. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_index.scss.map +1 -0
  89. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_service-navigation.scss +4 -0
  90. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_service-navigation.scss.map +1 -0
  91. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/fixtures.json +464 -0
  92. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/macro-options.json +138 -0
  93. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/macro.njk +3 -0
  94. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +249 -0
  95. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js.map +1 -0
  96. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +241 -0
  97. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs.map +1 -0
  98. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs +85 -0
  99. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs.map +1 -0
  100. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-default.html +57 -0
  101. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-html-navigation-items.html +49 -0
  102. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-large-navigation.html +153 -0
  103. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-long-service-name.html +20 -0
  104. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-navigation-with-a-current-item.html +58 -0
  105. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-navigation-with-an-active-item.html +58 -0
  106. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-non-link-navigation-items.html +49 -0
  107. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-link.html +20 -0
  108. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-name-and-navigation.html +63 -0
  109. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-name.html +18 -0
  110. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template.njk +102 -0
  111. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +93 -26
  112. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js.map +1 -1
  113. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +93 -26
  114. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs.map +1 -1
  115. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs +13 -21
  116. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs.map +1 -1
  117. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +93 -27
  118. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js.map +1 -1
  119. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +93 -27
  120. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs.map +1 -1
  121. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs +13 -22
  122. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs.map +1 -1
  123. data/node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss +4 -3
  124. data/node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss.map +1 -1
  125. data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss +1 -1
  126. data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs +16 -3
  127. data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs.map +1 -1
  128. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend-component.mjs +49 -5
  129. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend-component.mjs.map +1 -1
  130. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css +2 -2
  131. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css.map +1 -1
  132. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
  133. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js.map +1 -1
  134. data/node_modules/govuk-frontend/dist/govuk/init.mjs +72 -10
  135. data/node_modules/govuk-frontend/dist/govuk/init.mjs.map +1 -1
  136. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss +3 -0
  137. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss.map +1 -1
  138. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +5 -1
  139. data/node_modules/govuk-frontend/package.json +8 -8
  140. metadata +29 -4
  141. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest-2x.png +0 -0
  142. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest.png +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.bundle.js","sources":["../../../../src/govuk/common/index.mjs","../../../../src/govuk/errors/index.mjs","../../../../src/govuk/govuk-frontend-component.mjs","../../../../src/govuk/components/tabs/tabs.mjs"],"sourcesContent":["import { normaliseString } from './normalise-string.mjs'\n\n/**\n * Common helpers which do not require polyfill.\n *\n * IMPORTANT: If a helper require a polyfill, please isolate it in its own module\n * so that the polyfill can be properly tree-shaken and does not burden\n * the components that do not need that helper\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 * @internal\n * @param {...{ [key: string]: unknown }} configObjects - Config objects to merge\n * @returns {{ [key: string]: unknown }} A merged config object\n */\nexport function mergeConfigs(...configObjects) {\n // Start with an empty object as our base\n /** @type {{ [key: string]: unknown }} */\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 (isObject(option) && isObject(override)) {\n // @ts-expect-error Index signature for type 'string' is missing\n formattedConfigObject[key] = mergeConfigs(option, override)\n } else {\n // Apply override\n formattedConfigObject[key] = override\n }\n }\n }\n\n return formattedConfigObject\n}\n\n/**\n * Extracts keys starting with a particular namespace from dataset ('data-*')\n * object, removing the namespace in the process, normalising all values\n *\n * @internal\n * @param {{ schema: Schema }} Component - Component class\n * @param {DOMStringMap} dataset - The object to extract key-value pairs from\n * @param {string} namespace - The namespace to filter keys with\n * @returns {ObjectNested | undefined} Nested object with dot-separated key namespace removed\n */\nexport function extractConfigByNamespace(Component, dataset, namespace) {\n const property = Component.schema.properties[namespace]\n\n // Only extract configs for object schema properties\n if (property?.type !== 'object') {\n return\n }\n\n // Add default empty config\n const newObject = {\n [namespace]: /** @type {ObjectNested} */ ({})\n }\n\n for (const [key, value] of Object.entries(dataset)) {\n /** @type {ObjectNested | ObjectNested[NestedKey]} */\n let current = newObject\n\n // Split the key into parts, using . as our namespace separator\n const keyParts = key.split('.')\n\n /**\n * Create new level per part\n *\n * e.g. 'i18n.textareaDescription.other' becomes\n * `{ i18n: { textareaDescription: { other } } }`\n */\n for (const [index, name] of keyParts.entries()) {\n if (typeof current === 'object') {\n // Drop down to nested object until the last part\n if (index < keyParts.length - 1) {\n // New nested object (optionally) replaces existing value\n if (!isObject(current[name])) {\n current[name] = {}\n }\n\n // Drop down into new or existing nested object\n current = current[name]\n } else if (key !== namespace) {\n // Normalised value (optionally) replaces existing value\n current[name] = normaliseString(value)\n }\n }\n }\n }\n\n return newObject[namespace]\n}\n\n/**\n * Get hash fragment from URL\n *\n * Extract the hash fragment (everything after the hash) from a URL,\n * but not including the hash symbol\n *\n * @private\n * @param {string} url - URL\n * @returns {string | undefined} Fragment from URL, without the hash\n */\nexport function getFragmentFromUrl(url) {\n if (!url.includes('#')) {\n return undefined\n }\n\n return url.split('#').pop()\n}\n\n/**\n * Get GOV.UK Frontend breakpoint value from CSS custom property\n *\n * @private\n * @param {string} name - Breakpoint name\n * @returns {{ property: string, value?: string }} Breakpoint object\n */\nexport function getBreakpoint(name) {\n const property = `--govuk-frontend-breakpoint-${name}`\n\n // Get value from `<html>` with breakpoints on CSS :root\n const value = window\n .getComputedStyle(document.documentElement)\n .getPropertyValue(property)\n\n return {\n property,\n value: value || undefined\n }\n}\n\n/**\n * Move focus to element\n *\n * Sets tabindex to -1 to make the element programmatically focusable,\n * but removes it on blur as the element doesn't need to be focused again.\n *\n * @private\n * @template {HTMLElement} FocusElement\n * @param {FocusElement} $element - HTML element\n * @param {object} [options] - Handler options\n * @param {function(this: FocusElement): void} [options.onBeforeFocus] - Callback before focus\n * @param {function(this: FocusElement): void} [options.onBlur] - Callback on blur\n */\nexport function setFocus($element, options = {}) {\n const isFocusable = $element.getAttribute('tabindex')\n\n if (!isFocusable) {\n $element.setAttribute('tabindex', '-1')\n }\n\n /**\n * Handle element focus\n */\n function onFocus() {\n $element.addEventListener('blur', onBlur, { once: true })\n }\n\n /**\n * Handle element blur\n */\n function onBlur() {\n options.onBlur?.call($element)\n\n if (!isFocusable) {\n $element.removeAttribute('tabindex')\n }\n }\n\n // Add listener to reset element on blur, after focus\n $element.addEventListener('focus', onFocus, { once: true })\n\n // Focus element\n options.onBeforeFocus?.call($element)\n $element.focus()\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 * @internal\n * @param {HTMLElement | null} [$scope] - HTML element `<body>` checked for browser support\n * @returns {boolean} Whether GOV.UK Frontend is supported on this page\n */\nexport function isSupported($scope = document.body) {\n if (!$scope) {\n return false\n }\n\n return $scope.classList.contains('govuk-frontend-supported')\n}\n\n/**\n * Validate component config by schema\n *\n * Follows limited examples in JSON schema for wider support in future\n *\n * {@link https://ajv.js.org/json-schema.html#compound-keywords}\n * {@link https://ajv.js.org/packages/ajv-errors.html#single-message}\n *\n * @internal\n * @param {Schema} schema - Config schema\n * @param {{ [key: string]: unknown }} config - Component config\n * @returns {string[]} List of validation errors\n */\nexport function validateConfig(schema, config) {\n const validationErrors = []\n\n // Check errors for each schema\n for (const [name, conditions] of Object.entries(schema)) {\n const errors = []\n\n // Check errors for each schema condition\n if (Array.isArray(conditions)) {\n for (const { required, errorMessage } of conditions) {\n if (!required.every((key) => !!config[key])) {\n errors.push(errorMessage) // Missing config key value\n }\n }\n\n // Check one condition passes or add errors\n if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {\n validationErrors.push(...errors)\n }\n }\n }\n\n return validationErrors\n}\n\n/**\n * Check for an array\n *\n * @internal\n * @param {unknown} option - Option to check\n * @returns {boolean} Whether the option is an array\n */\nfunction isArray(option) {\n return Array.isArray(option)\n}\n\n/**\n * Check for an object\n *\n * @internal\n * @param {unknown} option - Option to check\n * @returns {boolean} Whether the option is an object\n */\nfunction isObject(option) {\n return !!option && typeof option === 'object' && !isArray(option)\n}\n\n/**\n * Schema for component config\n *\n * @typedef {object} Schema\n * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties\n * @property {SchemaCondition[]} [anyOf] - List of schema conditions\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\n/**\n * Schema condition for component config\n *\n * @typedef {object} SchemaCondition\n * @property {string[]} required - List of required config fields\n * @property {string} errorMessage - Error message when required config fields not provided\n */\n\n/**\n * @internal\n * @typedef {keyof ObjectNested} NestedKey\n * @typedef {{ [key: string]: string | boolean | number | ObjectNested | undefined }} ObjectNested\n */\n","/**\n * GOV.UK Frontend error\n *\n * A base class for `Error`s thrown by GOV.UK Frontend.\n *\n * It is meant to be extended into specific types of errors\n * to be thrown by our code.\n *\n * @example\n * ```js\n * class MissingRootError extends GOVUKFrontendError {\n * // Setting an explicit name is important as extending the class will not\n * // set a new `name` on the subclass. The `name` property is important\n * // to ensure intelligible error names even if the class name gets\n * // mangled by a minifier\n * name = \"MissingRootError\"\n * }\n * ```\n * @abstract\n */\nexport class GOVUKFrontendError extends Error {\n name = 'GOVUKFrontendError'\n}\n\n/**\n * Indicates that GOV.UK Frontend is not supported\n */\nexport class SupportError extends GOVUKFrontendError {\n name = 'SupportError'\n\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 =\n 'noModule' in HTMLScriptElement.prototype\n ? 'GOV.UK Frontend initialised without `<body class=\"govuk-frontend-supported\">` from template `<script>` snippet'\n : 'GOV.UK Frontend is not supported in this browser'\n\n super(\n $scope\n ? supportMessage\n : 'GOV.UK Frontend initialised without `<script type=\"module\">`'\n )\n }\n}\n\n/**\n * Indicates that a component has received an illegal configuration\n */\nexport class ConfigError extends GOVUKFrontendError {\n name = 'ConfigError'\n}\n\n/**\n * Indicates an issue with an element (possibly `null` or `undefined`)\n */\nexport class ElementError extends GOVUKFrontendError {\n name = 'ElementError'\n\n /**\n * @internal\n * @overload\n * @param {string} message - Element error message\n */\n\n /**\n * @internal\n * @overload\n * @param {ElementErrorOptions} options - Element error options\n */\n\n /**\n * @internal\n * @param {string | ElementErrorOptions} messageOrOptions - Element error message or options\n */\n constructor(messageOrOptions) {\n let message = typeof messageOrOptions === 'string' ? messageOrOptions : ''\n\n // Build message from options\n if (typeof messageOrOptions === 'object') {\n const { componentName, identifier, element, expectedType } =\n messageOrOptions\n\n // Add prefix and identifier\n message = `${componentName}: ${identifier}`\n\n // Append reason\n message += element\n ? ` is not of type ${expectedType ?? 'HTMLElement'}`\n : ' not found'\n }\n\n super(message)\n }\n}\n\n/**\n * Element error options\n *\n * @internal\n * @typedef {object} ElementErrorOptions\n * @property {string} componentName - The name of the component throwing the error\n * @property {string} identifier - An identifier that'll let the user understand which element has an error. This is whatever makes the most sense\n * @property {Element | null} [element] - The element in error\n * @property {string} [expectedType] - The type that was expected for the identifier\n */\n","import { isSupported } from './common/index.mjs'\nimport { SupportError } from './errors/index.mjs'\n\n/**\n * Base Component class\n *\n * Centralises the behaviours shared by our components\n *\n * @internal\n * @abstract\n */\nexport class GOVUKFrontendComponent {\n /**\n * Constructs a new component, validating that GOV.UK Frontend is supported\n *\n * @internal\n */\n constructor() {\n this.checkSupport()\n }\n\n /**\n * Validates whether GOV.UK Frontend is supported\n *\n * @private\n * @throws {SupportError} when GOV.UK Frontend is not supported\n */\n checkSupport() {\n if (!isSupported()) {\n throw new SupportError()\n }\n }\n}\n","import { getBreakpoint, getFragmentFromUrl } from '../../common/index.mjs'\nimport { ElementError } from '../../errors/index.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\n\n/**\n * Tabs component\n *\n * @preserve\n */\nexport class Tabs extends GOVUKFrontendComponent {\n /** @private */\n $module\n\n /** @private */\n $tabs\n\n /** @private */\n $tabList\n\n /** @private */\n $tabListItems\n\n /** @private */\n jsHiddenClass = 'govuk-tabs__panel--hidden'\n\n /** @private */\n changingHash = false\n\n /** @private */\n boundTabClick\n\n /** @private */\n boundTabKeydown\n\n /** @private */\n boundOnHashChange\n\n /**\n * @private\n * @type {MediaQueryList | null}\n */\n mql = null\n\n /**\n * @param {Element | null} $module - HTML element to use for tabs\n */\n constructor($module) {\n super()\n\n if (!$module) {\n throw new ElementError({\n componentName: 'Tabs',\n element: $module,\n identifier: 'Root element (`$module`)'\n })\n }\n\n const $tabs = $module.querySelectorAll('a.govuk-tabs__tab')\n if (!$tabs.length) {\n throw new ElementError({\n componentName: 'Tabs',\n identifier: 'Links (`<a class=\"govuk-tabs__tab\">`)'\n })\n }\n\n this.$module = $module\n this.$tabs = $tabs\n\n // Save bound functions so we can remove event listeners during teardown\n this.boundTabClick = this.onTabClick.bind(this)\n this.boundTabKeydown = this.onTabKeydown.bind(this)\n this.boundOnHashChange = this.onHashChange.bind(this)\n\n const $tabList = this.$module.querySelector('.govuk-tabs__list')\n const $tabListItems = this.$module.querySelectorAll(\n 'li.govuk-tabs__list-item'\n )\n\n if (!$tabList) {\n throw new ElementError({\n componentName: 'Tabs',\n identifier: 'List (`<ul class=\"govuk-tabs__list\">`)'\n })\n }\n\n if (!$tabListItems.length) {\n throw new ElementError({\n componentName: 'Tabs',\n identifier: 'List items (`<li class=\"govuk-tabs__list-item\">`)'\n })\n }\n\n this.$tabList = $tabList\n this.$tabListItems = $tabListItems\n\n this.setupResponsiveChecks()\n }\n\n /**\n * Setup viewport resize check\n *\n * @private\n */\n setupResponsiveChecks() {\n const breakpoint = getBreakpoint('tablet')\n\n if (!breakpoint.value) {\n throw new ElementError({\n componentName: 'Tabs',\n identifier: `CSS custom property (\\`${breakpoint.property}\\`) on pseudo-class \\`:root\\``\n })\n }\n\n // Media query list for GOV.UK Frontend tablet breakpoint\n this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`)\n\n // MediaQueryList.addEventListener isn't supported by Safari < 14 so we need\n // to be able to fall back to the deprecated MediaQueryList.addListener\n if ('addEventListener' in this.mql) {\n this.mql.addEventListener('change', () => this.checkMode())\n } else {\n // @ts-expect-error Property 'addListener' does not exist\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n this.mql.addListener(() => this.checkMode())\n }\n\n this.checkMode()\n }\n\n /**\n * Setup or teardown handler for viewport resize check\n *\n * @private\n */\n checkMode() {\n if (this.mql?.matches) {\n this.setup()\n } else {\n this.teardown()\n }\n }\n\n /**\n * Setup tab component\n *\n * @private\n */\n setup() {\n this.$tabList.setAttribute('role', 'tablist')\n\n this.$tabListItems.forEach(($item) => {\n $item.setAttribute('role', 'presentation')\n })\n\n this.$tabs.forEach(($tab) => {\n // Set HTML attributes\n this.setAttributes($tab)\n\n // Handle events\n $tab.addEventListener('click', this.boundTabClick, true)\n $tab.addEventListener('keydown', this.boundTabKeydown, true)\n\n // Remove old active panels\n this.hideTab($tab)\n })\n\n // Show either the active tab according to the URL's hash or the first tab\n const $activeTab = this.getTab(window.location.hash) ?? this.$tabs[0]\n\n this.showTab($activeTab)\n\n // Handle hashchange events\n window.addEventListener('hashchange', this.boundOnHashChange, true)\n }\n\n /**\n * Teardown tab component\n *\n * @private\n */\n teardown() {\n this.$tabList.removeAttribute('role')\n\n this.$tabListItems.forEach(($item) => {\n $item.removeAttribute('role')\n })\n\n this.$tabs.forEach(($tab) => {\n // Remove events\n $tab.removeEventListener('click', this.boundTabClick, true)\n $tab.removeEventListener('keydown', this.boundTabKeydown, true)\n\n // Unset HTML attributes\n this.unsetAttributes($tab)\n })\n\n // Remove hashchange event handler\n window.removeEventListener('hashchange', this.boundOnHashChange, true)\n }\n\n /**\n * Handle hashchange event\n *\n * @private\n * @returns {void | undefined} Returns void, or undefined when prevented\n */\n onHashChange() {\n const hash = window.location.hash\n const $tabWithHash = this.getTab(hash)\n if (!$tabWithHash) {\n return\n }\n\n // Prevent changing the hash\n if (this.changingHash) {\n this.changingHash = false\n return\n }\n\n // Show either the active tab according to the URL's hash or the first tab\n const $previousTab = this.getCurrentTab()\n if (!$previousTab) {\n return\n }\n\n this.hideTab($previousTab)\n this.showTab($tabWithHash)\n $tabWithHash.focus()\n }\n\n /**\n * Hide panel for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n hideTab($tab) {\n this.unhighlightTab($tab)\n this.hidePanel($tab)\n }\n\n /**\n * Show panel for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n showTab($tab) {\n this.highlightTab($tab)\n this.showPanel($tab)\n }\n\n /**\n * Get tab link by hash\n *\n * @private\n * @param {string} hash - Hash fragment including #\n * @returns {HTMLAnchorElement | null} Tab link\n */\n getTab(hash) {\n return this.$module.querySelector(`a.govuk-tabs__tab[href=\"${hash}\"]`)\n }\n\n /**\n * Set tab link and panel attributes\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n setAttributes($tab) {\n const panelId = getFragmentFromUrl($tab.href)\n if (!panelId) {\n return\n }\n\n // Set tab attributes\n $tab.setAttribute('id', `tab_${panelId}`)\n $tab.setAttribute('role', 'tab')\n $tab.setAttribute('aria-controls', panelId)\n $tab.setAttribute('aria-selected', 'false')\n $tab.setAttribute('tabindex', '-1')\n\n // Set panel attributes\n const $panel = this.getPanel($tab)\n if (!$panel) {\n return\n }\n\n $panel.setAttribute('role', 'tabpanel')\n $panel.setAttribute('aria-labelledby', $tab.id)\n $panel.classList.add(this.jsHiddenClass)\n }\n\n /**\n * Unset tab link and panel attributes\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n unsetAttributes($tab) {\n // unset tab attributes\n $tab.removeAttribute('id')\n $tab.removeAttribute('role')\n $tab.removeAttribute('aria-controls')\n $tab.removeAttribute('aria-selected')\n $tab.removeAttribute('tabindex')\n\n // unset panel attributes\n const $panel = this.getPanel($tab)\n if (!$panel) {\n return\n }\n\n $panel.removeAttribute('role')\n $panel.removeAttribute('aria-labelledby')\n $panel.classList.remove(this.jsHiddenClass)\n }\n\n /**\n * Handle tab link clicks\n *\n * @private\n * @param {MouseEvent} event - Mouse click event\n * @returns {void} Returns void\n */\n onTabClick(event) {\n const $currentTab = this.getCurrentTab()\n const $nextTab = event.currentTarget\n\n if (!$currentTab || !($nextTab instanceof HTMLAnchorElement)) {\n return\n }\n\n event.preventDefault()\n\n this.hideTab($currentTab)\n this.showTab($nextTab)\n this.createHistoryEntry($nextTab)\n }\n\n /**\n * Update browser URL hash fragment for tab\n *\n * - Allows back/forward to navigate tabs\n * - Avoids page jump when hash changes\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n createHistoryEntry($tab) {\n const $panel = this.getPanel($tab)\n if (!$panel) {\n return\n }\n\n // Save and restore the id so the page doesn't jump when a user clicks a tab\n // (which changes the hash)\n const panelId = $panel.id\n $panel.id = ''\n this.changingHash = true\n window.location.hash = panelId\n $panel.id = panelId\n }\n\n /**\n * Handle tab keydown event\n *\n * - Press right arrow for next tab\n * - Press left arrow for previous tab\n *\n * @private\n * @param {KeyboardEvent} event - Keydown event\n */\n onTabKeydown(event) {\n switch (event.key) {\n // 'Left' and 'Right' required for Edge 16 support.\n case 'ArrowLeft':\n case 'Left':\n this.activatePreviousTab()\n event.preventDefault()\n break\n case 'ArrowRight':\n case 'Right':\n this.activateNextTab()\n event.preventDefault()\n break\n }\n }\n\n /**\n * Activate next tab\n *\n * @private\n */\n activateNextTab() {\n const $currentTab = this.getCurrentTab()\n if (!$currentTab?.parentElement) {\n return\n }\n\n const $nextTabListItem = $currentTab.parentElement.nextElementSibling\n if (!$nextTabListItem) {\n return\n }\n\n const $nextTab = $nextTabListItem.querySelector('a.govuk-tabs__tab')\n if (!$nextTab) {\n return\n }\n\n this.hideTab($currentTab)\n this.showTab($nextTab)\n $nextTab.focus()\n this.createHistoryEntry($nextTab)\n }\n\n /**\n * Activate previous tab\n *\n * @private\n */\n activatePreviousTab() {\n const $currentTab = this.getCurrentTab()\n if (!$currentTab?.parentElement) {\n return\n }\n\n const $previousTabListItem =\n $currentTab.parentElement.previousElementSibling\n if (!$previousTabListItem) {\n return\n }\n\n const $previousTab = $previousTabListItem.querySelector('a.govuk-tabs__tab')\n if (!$previousTab) {\n return\n }\n\n this.hideTab($currentTab)\n this.showTab($previousTab)\n $previousTab.focus()\n this.createHistoryEntry($previousTab)\n }\n\n /**\n * Get tab panel for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n * @returns {Element | null} Tab panel\n */\n getPanel($tab) {\n const panelId = getFragmentFromUrl($tab.href)\n if (!panelId) {\n return null\n }\n\n return this.$module.querySelector(`#${panelId}`)\n }\n\n /**\n * Show tab panel for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n showPanel($tab) {\n const $panel = this.getPanel($tab)\n if (!$panel) {\n return\n }\n\n $panel.classList.remove(this.jsHiddenClass)\n }\n\n /**\n * Hide tab panel for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n hidePanel($tab) {\n const $panel = this.getPanel($tab)\n if (!$panel) {\n return\n }\n\n $panel.classList.add(this.jsHiddenClass)\n }\n\n /**\n * Unset 'selected' state for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n unhighlightTab($tab) {\n if (!$tab.parentElement) {\n return\n }\n\n $tab.setAttribute('aria-selected', 'false')\n $tab.parentElement.classList.remove('govuk-tabs__list-item--selected')\n $tab.setAttribute('tabindex', '-1')\n }\n\n /**\n * Set 'selected' state for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n highlightTab($tab) {\n if (!$tab.parentElement) {\n return\n }\n\n $tab.setAttribute('aria-selected', 'true')\n $tab.parentElement.classList.add('govuk-tabs__list-item--selected')\n $tab.setAttribute('tabindex', '0')\n }\n\n /**\n * Get current tab link\n *\n * @private\n * @returns {HTMLAnchorElement | null} Tab link\n */\n getCurrentTab() {\n return this.$module.querySelector(\n '.govuk-tabs__list-item--selected a.govuk-tabs__tab'\n )\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-tabs'\n}\n"],"names":["getFragmentFromUrl","url","includes","undefined","split","pop","getBreakpoint","name","property","value","window","getComputedStyle","document","documentElement","getPropertyValue","isSupported","$scope","body","classList","contains","GOVUKFrontendError","Error","constructor","args","SupportError","supportMessage","HTMLScriptElement","prototype","ElementError","messageOrOptions","message","componentName","identifier","element","expectedType","GOVUKFrontendComponent","checkSupport","Tabs","$module","$tabs","$tabList","$tabListItems","jsHiddenClass","changingHash","boundTabClick","boundTabKeydown","boundOnHashChange","mql","querySelectorAll","length","onTabClick","bind","onTabKeydown","onHashChange","querySelector","setupResponsiveChecks","breakpoint","matchMedia","addEventListener","checkMode","addListener","_this$mql","matches","setup","teardown","_this$getTab","setAttribute","forEach","$item","$tab","setAttributes","hideTab","$activeTab","getTab","location","hash","showTab","removeAttribute","removeEventListener","unsetAttributes","$tabWithHash","$previousTab","getCurrentTab","focus","unhighlightTab","hidePanel","highlightTab","showPanel","panelId","href","$panel","getPanel","id","add","remove","event","$currentTab","$nextTab","currentTarget","HTMLAnchorElement","preventDefault","createHistoryEntry","key","activatePreviousTab","activateNextTab","parentElement","$nextTabListItem","nextElementSibling","$previousTabListItem","previousElementSibling","moduleName"],"mappings":"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"}
1
+ {"version":3,"file":"tabs.bundle.js","sources":["../../../../src/govuk/common/index.mjs","../../../../src/govuk/errors/index.mjs","../../../../src/govuk/govuk-frontend-component.mjs","../../../../src/govuk/components/tabs/tabs.mjs"],"sourcesContent":["import { normaliseString } from './normalise-string.mjs'\n\n/**\n * Common helpers which do not require polyfill.\n *\n * IMPORTANT: If a helper require a polyfill, please isolate it in its own module\n * so that the polyfill can be properly tree-shaken and does not burden\n * the components that do not need that helper\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 * @internal\n * @param {...{ [key: string]: unknown }} configObjects - Config objects to merge\n * @returns {{ [key: string]: unknown }} A merged config object\n */\nexport function mergeConfigs(...configObjects) {\n // Start with an empty object as our base\n /** @type {{ [key: string]: unknown }} */\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 (isObject(option) && isObject(override)) {\n // @ts-expect-error Index signature for type 'string' is missing\n formattedConfigObject[key] = mergeConfigs(option, override)\n } else {\n // Apply override\n formattedConfigObject[key] = override\n }\n }\n }\n\n return formattedConfigObject\n}\n\n/**\n * Extracts keys starting with a particular namespace from dataset ('data-*')\n * object, removing the namespace in the process, normalising all values\n *\n * @internal\n * @param {{ schema: Schema }} Component - Component class\n * @param {DOMStringMap} dataset - The object to extract key-value pairs from\n * @param {string} namespace - The namespace to filter keys with\n * @returns {ObjectNested | undefined} Nested object with dot-separated key namespace removed\n */\nexport function extractConfigByNamespace(Component, dataset, namespace) {\n const property = Component.schema.properties[namespace]\n\n // Only extract configs for object schema properties\n if (property?.type !== 'object') {\n return\n }\n\n // Add default empty config\n const newObject = {\n [namespace]: /** @type {ObjectNested} */ ({})\n }\n\n for (const [key, value] of Object.entries(dataset)) {\n /** @type {ObjectNested | ObjectNested[NestedKey]} */\n let current = newObject\n\n // Split the key into parts, using . as our namespace separator\n const keyParts = key.split('.')\n\n /**\n * Create new level per part\n *\n * e.g. 'i18n.textareaDescription.other' becomes\n * `{ i18n: { textareaDescription: { other } } }`\n */\n for (const [index, name] of keyParts.entries()) {\n if (typeof current === 'object') {\n // Drop down to nested object until the last part\n if (index < keyParts.length - 1) {\n // New nested object (optionally) replaces existing value\n if (!isObject(current[name])) {\n current[name] = {}\n }\n\n // Drop down into new or existing nested object\n current = current[name]\n } else if (key !== namespace) {\n // Normalised value (optionally) replaces existing value\n current[name] = normaliseString(value)\n }\n }\n }\n }\n\n return newObject[namespace]\n}\n\n/**\n * Get hash fragment from URL\n *\n * Extract the hash fragment (everything after the hash) from a URL,\n * but not including the hash symbol\n *\n * @private\n * @param {string} url - URL\n * @returns {string | undefined} Fragment from URL, without the hash\n */\nexport function getFragmentFromUrl(url) {\n if (!url.includes('#')) {\n return undefined\n }\n\n return url.split('#').pop()\n}\n\n/**\n * Get GOV.UK Frontend breakpoint value from CSS custom property\n *\n * @private\n * @param {string} name - Breakpoint name\n * @returns {{ property: string, value?: string }} Breakpoint object\n */\nexport function getBreakpoint(name) {\n const property = `--govuk-frontend-breakpoint-${name}`\n\n // Get value from `<html>` with breakpoints on CSS :root\n const value = window\n .getComputedStyle(document.documentElement)\n .getPropertyValue(property)\n\n return {\n property,\n value: value || undefined\n }\n}\n\n/**\n * Move focus to element\n *\n * Sets tabindex to -1 to make the element programmatically focusable,\n * but removes it on blur as the element doesn't need to be focused again.\n *\n * @private\n * @template {HTMLElement} FocusElement\n * @param {FocusElement} $element - HTML element\n * @param {object} [options] - Handler options\n * @param {function(this: FocusElement): void} [options.onBeforeFocus] - Callback before focus\n * @param {function(this: FocusElement): void} [options.onBlur] - Callback on blur\n */\nexport function setFocus($element, options = {}) {\n const isFocusable = $element.getAttribute('tabindex')\n\n if (!isFocusable) {\n $element.setAttribute('tabindex', '-1')\n }\n\n /**\n * Handle element focus\n */\n function onFocus() {\n $element.addEventListener('blur', onBlur, { once: true })\n }\n\n /**\n * Handle element blur\n */\n function onBlur() {\n options.onBlur?.call($element)\n\n if (!isFocusable) {\n $element.removeAttribute('tabindex')\n }\n }\n\n // Add listener to reset element on blur, after focus\n $element.addEventListener('focus', onFocus, { once: true })\n\n // Focus element\n options.onBeforeFocus?.call($element)\n $element.focus()\n}\n\n/**\n * Checks if component is already initialised\n *\n * @internal\n * @param {Element} $root - HTML element to be checked\n * @param {string} moduleName - name of component module\n * @returns {boolean} Whether component is already initialised\n */\nexport function isInitialised($root, moduleName) {\n return (\n $root instanceof HTMLElement &&\n $root.hasAttribute(`data-${moduleName}-init`)\n )\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 */\nexport function isSupported($scope = document.body) {\n if (!$scope) {\n return false\n }\n\n return $scope.classList.contains('govuk-frontend-supported')\n}\n\n/**\n * Validate component config by schema\n *\n * Follows limited examples in JSON schema for wider support in future\n *\n * {@link https://ajv.js.org/json-schema.html#compound-keywords}\n * {@link https://ajv.js.org/packages/ajv-errors.html#single-message}\n *\n * @internal\n * @param {Schema} schema - Config schema\n * @param {{ [key: string]: unknown }} config - Component config\n * @returns {string[]} List of validation errors\n */\nexport function validateConfig(schema, config) {\n const validationErrors = []\n\n // Check errors for each schema\n for (const [name, conditions] of Object.entries(schema)) {\n const errors = []\n\n // Check errors for each schema condition\n if (Array.isArray(conditions)) {\n for (const { required, errorMessage } of conditions) {\n if (!required.every((key) => !!config[key])) {\n errors.push(errorMessage) // Missing config key value\n }\n }\n\n // Check one condition passes or add errors\n if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {\n validationErrors.push(...errors)\n }\n }\n }\n\n return validationErrors\n}\n\n/**\n * Check for an array\n *\n * @internal\n * @param {unknown} option - Option to check\n * @returns {boolean} Whether the option is an array\n */\nfunction isArray(option) {\n return Array.isArray(option)\n}\n\n/**\n * Check for an object\n *\n * @internal\n * @param {unknown} option - Option to check\n * @returns {boolean} Whether the option is an object\n */\nfunction isObject(option) {\n return !!option && typeof option === 'object' && !isArray(option)\n}\n\n/**\n * Format error message\n *\n * @internal\n * @param {ComponentWithModuleName} Component - Component that threw the error\n * @param {string} message - Error message\n * @returns {string} - Formatted error message\n */\nexport function formatErrorMessage(Component, message) {\n return `${Component.moduleName}: ${message}`\n}\n\n/**\n * Schema for component config\n *\n * @typedef {object} Schema\n * @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties\n * @property {SchemaCondition[]} [anyOf] - List of schema conditions\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\n/**\n * Schema condition for component config\n *\n * @typedef {object} SchemaCondition\n * @property {string[]} required - List of required config fields\n * @property {string} errorMessage - Error message when required config fields not provided\n */\n\n/**\n * @internal\n * @typedef {keyof ObjectNested} NestedKey\n * @typedef {{ [key: string]: string | boolean | number | ObjectNested | undefined }} ObjectNested\n */\n\n/* eslint-disable jsdoc/valid-types --\n * `{new(...args: any[] ): object}` is not recognised as valid\n * https://github.com/gajus/eslint-plugin-jsdoc/issues/145#issuecomment-1308722878\n * https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/131\n **/\n\n/**\n * @typedef ComponentWithModuleName\n * @property {string} moduleName - Name of the component\n */\n\n/* eslint-enable jsdoc/valid-types */\n","import { formatErrorMessage } from '../common/index.mjs'\n\n/**\n * GOV.UK Frontend error\n *\n * A base class for `Error`s thrown by GOV.UK Frontend.\n *\n * It is meant to be extended into specific types of errors\n * to be thrown by our code.\n *\n * @example\n * ```js\n * class MissingRootError extends GOVUKFrontendError {\n * // Setting an explicit name is important as extending the class will not\n * // set a new `name` on the subclass. The `name` property is important\n * // to ensure intelligible error names even if the class name gets\n * // mangled by a minifier\n * name = \"MissingRootError\"\n * }\n * ```\n * @virtual\n */\nexport class GOVUKFrontendError extends Error {\n name = 'GOVUKFrontendError'\n}\n\n/**\n * Indicates that GOV.UK Frontend is not supported\n */\nexport class SupportError extends GOVUKFrontendError {\n name = 'SupportError'\n\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 =\n 'noModule' in HTMLScriptElement.prototype\n ? 'GOV.UK Frontend initialised without `<body class=\"govuk-frontend-supported\">` from template `<script>` snippet'\n : 'GOV.UK Frontend is not supported in this browser'\n\n super(\n $scope\n ? supportMessage\n : 'GOV.UK Frontend initialised without `<script type=\"module\">`'\n )\n }\n}\n\n/**\n * Indicates that a component has received an illegal configuration\n */\nexport class ConfigError extends GOVUKFrontendError {\n name = 'ConfigError'\n}\n\n/**\n * Indicates an issue with an element (possibly `null` or `undefined`)\n */\nexport class ElementError extends GOVUKFrontendError {\n name = 'ElementError'\n\n /**\n * @internal\n * @overload\n * @param {string} message - Element error message\n */\n\n /**\n * @internal\n * @overload\n * @param {ElementErrorOptions} options - Element error options\n */\n\n /**\n * @internal\n * @param {string | ElementErrorOptions} messageOrOptions - Element error message or options\n */\n constructor(messageOrOptions) {\n let message = typeof messageOrOptions === 'string' ? messageOrOptions : ''\n\n // Build message from options\n if (typeof messageOrOptions === 'object') {\n const { component, identifier, element, expectedType } = messageOrOptions\n\n message = identifier\n\n // Append reason\n message += element\n ? ` is not of type ${expectedType ?? 'HTMLElement'}`\n : ' not found'\n\n message = formatErrorMessage(component, message)\n }\n\n super(message)\n }\n}\n\n/**\n * Indicates that a component is already initialised\n */\nexport class InitError extends GOVUKFrontendError {\n name = 'InitError'\n\n /**\n * @internal\n * @param {ComponentWithModuleName | string} componentOrMessage - name of the component module\n */\n constructor(componentOrMessage) {\n const message =\n typeof componentOrMessage === 'string'\n ? componentOrMessage\n : formatErrorMessage(\n componentOrMessage,\n `Root element (\\`$root\\`) already initialised`\n )\n\n super(message)\n }\n}\n\n/**\n * Element error options\n *\n * @internal\n * @typedef {object} ElementErrorOptions\n * @property {string} identifier - An identifier that'll let the user understand which element has an error. This is whatever makes the most sense\n * @property {Element | null} [element] - The element in error\n * @property {string} [expectedType] - The type that was expected for the identifier\n * @property {ComponentWithModuleName} component - Component throwing the error\n */\n\n/**\n * @typedef {import('../common/index.mjs').ComponentWithModuleName} ComponentWithModuleName\n */\n","import { isInitialised, isSupported } from './common/index.mjs'\nimport { ElementError, InitError, SupportError } from './errors/index.mjs'\n\n/**\n * Base Component class\n *\n * Centralises the behaviours shared by our components\n *\n * @virtual\n * @template {Element} [RootElementType=HTMLElement]\n */\nexport class GOVUKFrontendComponent {\n /**\n * @type {typeof Element}\n */\n static elementType = HTMLElement\n\n // allows Typescript user to work around the lack of types\n // in GOVUKFrontend package, Typescript is not aware of $root\n // in components that extend GOVUKFrontendComponent\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\n /**\n * @protected\n * @type {RootElementType}\n */\n _$root\n\n /**\n * Constructs a new component, validating that GOV.UK Frontend is supported\n *\n * @internal\n * @param {Element | null} [$root] - HTML element to use for component\n */\n constructor($root) {\n const childConstructor = /** @type {ChildClassConstructor} */ (\n this.constructor\n )\n\n // TypeScript does not enforce that inheriting classes will define a `moduleName`\n // (even if we add a `@virtual` `static moduleName` property to this class).\n // While we trust users to do this correctly, we do a little check to provide them\n // a helpful error message.\n //\n // After this, we'll be sure that `childConstructor` has a `moduleName`\n // as expected of the `ChildClassConstructor` we've cast `this.constructor` to.\n if (typeof childConstructor.moduleName !== 'string') {\n throw new InitError(`\\`moduleName\\` not defined in component`)\n }\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 = /** @type {RootElementType} */ ($root)\n }\n\n childConstructor.checkSupport()\n\n this.checkInitialised()\n\n const moduleName = childConstructor.moduleName\n\n this.$root.setAttribute(`data-${moduleName}-init`, '')\n }\n\n /**\n * Validates whether component is already initialised\n *\n * @private\n * @throws {InitError} when component is already initialised\n */\n checkInitialised() {\n const constructor = /** @type {ChildClassConstructor} */ (this.constructor)\n const moduleName = constructor.moduleName\n\n if (moduleName && isInitialised(this.$root, moduleName)) {\n throw new InitError(constructor)\n }\n }\n\n /**\n * Validates whether components are supported\n *\n * @throws {SupportError} when the components are not supported\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 GOVUKFrontendComponent & ChildClass} ChildClassConstructor\n */\n","import { getBreakpoint, getFragmentFromUrl } from '../../common/index.mjs'\nimport { ElementError } from '../../errors/index.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\n\n/**\n * Tabs component\n *\n * @preserve\n */\nexport class Tabs extends GOVUKFrontendComponent {\n /** @private */\n $tabs\n\n /** @private */\n $tabList\n\n /** @private */\n $tabListItems\n\n /** @private */\n jsHiddenClass = 'govuk-tabs__panel--hidden'\n\n /** @private */\n changingHash = false\n\n /** @private */\n boundTabClick\n\n /** @private */\n boundTabKeydown\n\n /** @private */\n boundOnHashChange\n\n /**\n * @private\n * @type {MediaQueryList | null}\n */\n mql = null\n\n /**\n * @param {Element | null} $root - HTML element to use for tabs\n */\n constructor($root) {\n super($root)\n\n const $tabs = this.$root.querySelectorAll('a.govuk-tabs__tab')\n if (!$tabs.length) {\n throw new ElementError({\n component: Tabs,\n identifier: 'Links (`<a class=\"govuk-tabs__tab\">`)'\n })\n }\n\n this.$tabs = $tabs\n\n // Save bound functions so we can remove event listeners during teardown\n this.boundTabClick = this.onTabClick.bind(this)\n this.boundTabKeydown = this.onTabKeydown.bind(this)\n this.boundOnHashChange = this.onHashChange.bind(this)\n\n const $tabList = this.$root.querySelector('.govuk-tabs__list')\n const $tabListItems = this.$root.querySelectorAll(\n 'li.govuk-tabs__list-item'\n )\n\n if (!$tabList) {\n throw new ElementError({\n component: Tabs,\n identifier: 'List (`<ul class=\"govuk-tabs__list\">`)'\n })\n }\n\n if (!$tabListItems.length) {\n throw new ElementError({\n component: Tabs,\n identifier: 'List items (`<li class=\"govuk-tabs__list-item\">`)'\n })\n }\n\n this.$tabList = $tabList\n this.$tabListItems = $tabListItems\n\n this.setupResponsiveChecks()\n }\n\n /**\n * Setup viewport resize check\n *\n * @private\n */\n setupResponsiveChecks() {\n const breakpoint = getBreakpoint('tablet')\n\n if (!breakpoint.value) {\n throw new ElementError({\n component: Tabs,\n identifier: `CSS custom property (\\`${breakpoint.property}\\`) on pseudo-class \\`:root\\``\n })\n }\n\n // Media query list for GOV.UK Frontend tablet breakpoint\n this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`)\n\n // MediaQueryList.addEventListener isn't supported by Safari < 14 so we need\n // to be able to fall back to the deprecated MediaQueryList.addListener\n if ('addEventListener' in this.mql) {\n this.mql.addEventListener('change', () => this.checkMode())\n } else {\n // @ts-expect-error Property 'addListener' does not exist\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n this.mql.addListener(() => this.checkMode())\n }\n\n this.checkMode()\n }\n\n /**\n * Setup or teardown handler for viewport resize check\n *\n * @private\n */\n checkMode() {\n if (this.mql?.matches) {\n this.setup()\n } else {\n this.teardown()\n }\n }\n\n /**\n * Setup tab component\n *\n * @private\n */\n setup() {\n this.$tabList.setAttribute('role', 'tablist')\n\n this.$tabListItems.forEach(($item) => {\n $item.setAttribute('role', 'presentation')\n })\n\n this.$tabs.forEach(($tab) => {\n // Set HTML attributes\n this.setAttributes($tab)\n\n // Handle events\n $tab.addEventListener('click', this.boundTabClick, true)\n $tab.addEventListener('keydown', this.boundTabKeydown, true)\n\n // Remove old active panels\n this.hideTab($tab)\n })\n\n // Show either the active tab according to the URL's hash or the first tab\n const $activeTab = this.getTab(window.location.hash) ?? this.$tabs[0]\n\n this.showTab($activeTab)\n\n // Handle hashchange events\n window.addEventListener('hashchange', this.boundOnHashChange, true)\n }\n\n /**\n * Teardown tab component\n *\n * @private\n */\n teardown() {\n this.$tabList.removeAttribute('role')\n\n this.$tabListItems.forEach(($item) => {\n $item.removeAttribute('role')\n })\n\n this.$tabs.forEach(($tab) => {\n // Remove events\n $tab.removeEventListener('click', this.boundTabClick, true)\n $tab.removeEventListener('keydown', this.boundTabKeydown, true)\n\n // Unset HTML attributes\n this.unsetAttributes($tab)\n })\n\n // Remove hashchange event handler\n window.removeEventListener('hashchange', this.boundOnHashChange, true)\n }\n\n /**\n * Handle hashchange event\n *\n * @private\n * @returns {void | undefined} Returns void, or undefined when prevented\n */\n onHashChange() {\n const hash = window.location.hash\n const $tabWithHash = this.getTab(hash)\n if (!$tabWithHash) {\n return\n }\n\n // Prevent changing the hash\n if (this.changingHash) {\n this.changingHash = false\n return\n }\n\n // Show either the active tab according to the URL's hash or the first tab\n const $previousTab = this.getCurrentTab()\n if (!$previousTab) {\n return\n }\n\n this.hideTab($previousTab)\n this.showTab($tabWithHash)\n $tabWithHash.focus()\n }\n\n /**\n * Hide panel for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n hideTab($tab) {\n this.unhighlightTab($tab)\n this.hidePanel($tab)\n }\n\n /**\n * Show panel for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n showTab($tab) {\n this.highlightTab($tab)\n this.showPanel($tab)\n }\n\n /**\n * Get tab link by hash\n *\n * @private\n * @param {string} hash - Hash fragment including #\n * @returns {HTMLAnchorElement | null} Tab link\n */\n getTab(hash) {\n return this.$root.querySelector(`a.govuk-tabs__tab[href=\"${hash}\"]`)\n }\n\n /**\n * Set tab link and panel attributes\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n setAttributes($tab) {\n const panelId = getFragmentFromUrl($tab.href)\n if (!panelId) {\n return\n }\n\n // Set tab attributes\n $tab.setAttribute('id', `tab_${panelId}`)\n $tab.setAttribute('role', 'tab')\n $tab.setAttribute('aria-controls', panelId)\n $tab.setAttribute('aria-selected', 'false')\n $tab.setAttribute('tabindex', '-1')\n\n // Set panel attributes\n const $panel = this.getPanel($tab)\n if (!$panel) {\n return\n }\n\n $panel.setAttribute('role', 'tabpanel')\n $panel.setAttribute('aria-labelledby', $tab.id)\n $panel.classList.add(this.jsHiddenClass)\n }\n\n /**\n * Unset tab link and panel attributes\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n unsetAttributes($tab) {\n // unset tab attributes\n $tab.removeAttribute('id')\n $tab.removeAttribute('role')\n $tab.removeAttribute('aria-controls')\n $tab.removeAttribute('aria-selected')\n $tab.removeAttribute('tabindex')\n\n // unset panel attributes\n const $panel = this.getPanel($tab)\n if (!$panel) {\n return\n }\n\n $panel.removeAttribute('role')\n $panel.removeAttribute('aria-labelledby')\n $panel.classList.remove(this.jsHiddenClass)\n }\n\n /**\n * Handle tab link clicks\n *\n * @private\n * @param {MouseEvent} event - Mouse click event\n * @returns {void} Returns void\n */\n onTabClick(event) {\n const $currentTab = this.getCurrentTab()\n const $nextTab = event.currentTarget\n\n if (!$currentTab || !($nextTab instanceof HTMLAnchorElement)) {\n return\n }\n\n event.preventDefault()\n\n this.hideTab($currentTab)\n this.showTab($nextTab)\n this.createHistoryEntry($nextTab)\n }\n\n /**\n * Update browser URL hash fragment for tab\n *\n * - Allows back/forward to navigate tabs\n * - Avoids page jump when hash changes\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n createHistoryEntry($tab) {\n const $panel = this.getPanel($tab)\n if (!$panel) {\n return\n }\n\n // Save and restore the id so the page doesn't jump when a user clicks a tab\n // (which changes the hash)\n const panelId = $panel.id\n $panel.id = ''\n this.changingHash = true\n window.location.hash = panelId\n $panel.id = panelId\n }\n\n /**\n * Handle tab keydown event\n *\n * - Press right arrow for next tab\n * - Press left arrow for previous tab\n *\n * @private\n * @param {KeyboardEvent} event - Keydown event\n */\n onTabKeydown(event) {\n switch (event.key) {\n // 'Left' and 'Right' required for Edge 16 support.\n case 'ArrowLeft':\n case 'Left':\n this.activatePreviousTab()\n event.preventDefault()\n break\n case 'ArrowRight':\n case 'Right':\n this.activateNextTab()\n event.preventDefault()\n break\n }\n }\n\n /**\n * Activate next tab\n *\n * @private\n */\n activateNextTab() {\n const $currentTab = this.getCurrentTab()\n if (!$currentTab?.parentElement) {\n return\n }\n\n const $nextTabListItem = $currentTab.parentElement.nextElementSibling\n if (!$nextTabListItem) {\n return\n }\n\n const $nextTab = $nextTabListItem.querySelector('a.govuk-tabs__tab')\n if (!$nextTab) {\n return\n }\n\n this.hideTab($currentTab)\n this.showTab($nextTab)\n $nextTab.focus()\n this.createHistoryEntry($nextTab)\n }\n\n /**\n * Activate previous tab\n *\n * @private\n */\n activatePreviousTab() {\n const $currentTab = this.getCurrentTab()\n if (!$currentTab?.parentElement) {\n return\n }\n\n const $previousTabListItem =\n $currentTab.parentElement.previousElementSibling\n if (!$previousTabListItem) {\n return\n }\n\n const $previousTab = $previousTabListItem.querySelector('a.govuk-tabs__tab')\n if (!$previousTab) {\n return\n }\n\n this.hideTab($currentTab)\n this.showTab($previousTab)\n $previousTab.focus()\n this.createHistoryEntry($previousTab)\n }\n\n /**\n * Get tab panel for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n * @returns {Element | null} Tab panel\n */\n getPanel($tab) {\n const panelId = getFragmentFromUrl($tab.href)\n if (!panelId) {\n return null\n }\n\n return this.$root.querySelector(`#${panelId}`)\n }\n\n /**\n * Show tab panel for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n showPanel($tab) {\n const $panel = this.getPanel($tab)\n if (!$panel) {\n return\n }\n\n $panel.classList.remove(this.jsHiddenClass)\n }\n\n /**\n * Hide tab panel for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n hidePanel($tab) {\n const $panel = this.getPanel($tab)\n if (!$panel) {\n return\n }\n\n $panel.classList.add(this.jsHiddenClass)\n }\n\n /**\n * Unset 'selected' state for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n unhighlightTab($tab) {\n if (!$tab.parentElement) {\n return\n }\n\n $tab.setAttribute('aria-selected', 'false')\n $tab.parentElement.classList.remove('govuk-tabs__list-item--selected')\n $tab.setAttribute('tabindex', '-1')\n }\n\n /**\n * Set 'selected' state for tab link\n *\n * @private\n * @param {HTMLAnchorElement} $tab - Tab link\n */\n highlightTab($tab) {\n if (!$tab.parentElement) {\n return\n }\n\n $tab.setAttribute('aria-selected', 'true')\n $tab.parentElement.classList.add('govuk-tabs__list-item--selected')\n $tab.setAttribute('tabindex', '0')\n }\n\n /**\n * Get current tab link\n *\n * @private\n * @returns {HTMLAnchorElement | null} Tab link\n */\n getCurrentTab() {\n return this.$root.querySelector(\n '.govuk-tabs__list-item--selected a.govuk-tabs__tab'\n )\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-tabs'\n}\n"],"names":["getFragmentFromUrl","url","includes","undefined","split","pop","getBreakpoint","name","property","value","window","getComputedStyle","document","documentElement","getPropertyValue","isInitialised","$root","moduleName","HTMLElement","hasAttribute","isSupported","$scope","body","classList","contains","formatErrorMessage","Component","message","GOVUKFrontendError","Error","constructor","args","SupportError","supportMessage","HTMLScriptElement","prototype","ElementError","messageOrOptions","component","identifier","element","expectedType","InitError","componentOrMessage","GOVUKFrontendComponent","_$root","childConstructor","elementType","checkSupport","checkInitialised","setAttribute","Tabs","$tabs","$tabList","$tabListItems","jsHiddenClass","changingHash","boundTabClick","boundTabKeydown","boundOnHashChange","mql","querySelectorAll","length","onTabClick","bind","onTabKeydown","onHashChange","querySelector","setupResponsiveChecks","breakpoint","matchMedia","addEventListener","checkMode","addListener","_this$mql","matches","setup","teardown","_this$getTab","forEach","$item","$tab","setAttributes","hideTab","$activeTab","getTab","location","hash","showTab","removeAttribute","removeEventListener","unsetAttributes","$tabWithHash","$previousTab","getCurrentTab","focus","unhighlightTab","hidePanel","highlightTab","showPanel","panelId","href","$panel","getPanel","id","add","remove","event","$currentTab","$nextTab","currentTarget","HTMLAnchorElement","preventDefault","createHistoryEntry","key","activatePreviousTab","activateNextTab","parentElement","$nextTabListItem","nextElementSibling","$previousTabListItem","previousElementSibling"],"mappings":"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"}
@@ -12,12 +12,28 @@ function getBreakpoint(name) {
12
12
  value: value || undefined
13
13
  };
14
14
  }
15
+ function isInitialised($root, moduleName) {
16
+ return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);
17
+ }
18
+
19
+ /**
20
+ * Checks if GOV.UK Frontend is supported on this page
21
+ *
22
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
23
+ * won't be supported.
24
+ *
25
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
26
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
27
+ */
15
28
  function isSupported($scope = document.body) {
16
29
  if (!$scope) {
17
30
  return false;
18
31
  }
19
32
  return $scope.classList.contains('govuk-frontend-supported');
20
33
  }
34
+ function formatErrorMessage(Component, message) {
35
+ return `${Component.moduleName}: ${message}`;
36
+ }
21
37
 
22
38
  /**
23
39
  * Schema for component config
@@ -41,6 +57,10 @@ function isSupported($scope = document.body) {
41
57
  * @property {string[]} required - List of required config fields
42
58
  * @property {string} errorMessage - Error message when required config fields not provided
43
59
  */
60
+ /**
61
+ * @typedef ComponentWithModuleName
62
+ * @property {string} moduleName - Name of the component
63
+ */
44
64
 
45
65
  class GOVUKFrontendError extends Error {
46
66
  constructor(...args) {
@@ -65,30 +85,85 @@ class ElementError extends GOVUKFrontendError {
65
85
  let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
66
86
  if (typeof messageOrOptions === 'object') {
67
87
  const {
68
- componentName,
88
+ component,
69
89
  identifier,
70
90
  element,
71
91
  expectedType
72
92
  } = messageOrOptions;
73
- message = `${componentName}: ${identifier}`;
93
+ message = identifier;
74
94
  message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
95
+ message = formatErrorMessage(component, message);
75
96
  }
76
97
  super(message);
77
98
  this.name = 'ElementError';
78
99
  }
79
100
  }
101
+ class InitError extends GOVUKFrontendError {
102
+ constructor(componentOrMessage) {
103
+ const message = typeof componentOrMessage === 'string' ? componentOrMessage : formatErrorMessage(componentOrMessage, `Root element (\`$root\`) already initialised`);
104
+ super(message);
105
+ this.name = 'InitError';
106
+ }
107
+ }
108
+ /**
109
+ * @typedef {import('../common/index.mjs').ComponentWithModuleName} ComponentWithModuleName
110
+ */
80
111
 
81
112
  class GOVUKFrontendComponent {
82
- constructor() {
83
- this.checkSupport();
113
+ /**
114
+ * Returns the root element of the component
115
+ *
116
+ * @protected
117
+ * @returns {RootElementType} - the root element of component
118
+ */
119
+ get $root() {
120
+ return this._$root;
84
121
  }
85
- checkSupport() {
122
+ constructor($root) {
123
+ this._$root = void 0;
124
+ const childConstructor = this.constructor;
125
+ if (typeof childConstructor.moduleName !== 'string') {
126
+ throw new InitError(`\`moduleName\` not defined in component`);
127
+ }
128
+ if (!($root instanceof childConstructor.elementType)) {
129
+ throw new ElementError({
130
+ element: $root,
131
+ component: childConstructor,
132
+ identifier: 'Root element (`$root`)',
133
+ expectedType: childConstructor.elementType.name
134
+ });
135
+ } else {
136
+ this._$root = $root;
137
+ }
138
+ childConstructor.checkSupport();
139
+ this.checkInitialised();
140
+ const moduleName = childConstructor.moduleName;
141
+ this.$root.setAttribute(`data-${moduleName}-init`, '');
142
+ }
143
+ checkInitialised() {
144
+ const constructor = this.constructor;
145
+ const moduleName = constructor.moduleName;
146
+ if (moduleName && isInitialised(this.$root, moduleName)) {
147
+ throw new InitError(constructor);
148
+ }
149
+ }
150
+ static checkSupport() {
86
151
  if (!isSupported()) {
87
152
  throw new SupportError();
88
153
  }
89
154
  }
90
155
  }
91
156
 
157
+ /**
158
+ * @typedef ChildClass
159
+ * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
160
+ */
161
+
162
+ /**
163
+ * @typedef {typeof GOVUKFrontendComponent & ChildClass} ChildClassConstructor
164
+ */
165
+ GOVUKFrontendComponent.elementType = HTMLElement;
166
+
92
167
  /**
93
168
  * Tabs component
94
169
  *
@@ -96,11 +171,10 @@ class GOVUKFrontendComponent {
96
171
  */
97
172
  class Tabs extends GOVUKFrontendComponent {
98
173
  /**
99
- * @param {Element | null} $module - HTML element to use for tabs
174
+ * @param {Element | null} $root - HTML element to use for tabs
100
175
  */
101
- constructor($module) {
102
- super();
103
- this.$module = void 0;
176
+ constructor($root) {
177
+ super($root);
104
178
  this.$tabs = void 0;
105
179
  this.$tabList = void 0;
106
180
  this.$tabListItems = void 0;
@@ -110,36 +184,28 @@ class Tabs extends GOVUKFrontendComponent {
110
184
  this.boundTabKeydown = void 0;
111
185
  this.boundOnHashChange = void 0;
112
186
  this.mql = null;
113
- if (!$module) {
114
- throw new ElementError({
115
- componentName: 'Tabs',
116
- element: $module,
117
- identifier: 'Root element (`$module`)'
118
- });
119
- }
120
- const $tabs = $module.querySelectorAll('a.govuk-tabs__tab');
187
+ const $tabs = this.$root.querySelectorAll('a.govuk-tabs__tab');
121
188
  if (!$tabs.length) {
122
189
  throw new ElementError({
123
- componentName: 'Tabs',
190
+ component: Tabs,
124
191
  identifier: 'Links (`<a class="govuk-tabs__tab">`)'
125
192
  });
126
193
  }
127
- this.$module = $module;
128
194
  this.$tabs = $tabs;
129
195
  this.boundTabClick = this.onTabClick.bind(this);
130
196
  this.boundTabKeydown = this.onTabKeydown.bind(this);
131
197
  this.boundOnHashChange = this.onHashChange.bind(this);
132
- const $tabList = this.$module.querySelector('.govuk-tabs__list');
133
- const $tabListItems = this.$module.querySelectorAll('li.govuk-tabs__list-item');
198
+ const $tabList = this.$root.querySelector('.govuk-tabs__list');
199
+ const $tabListItems = this.$root.querySelectorAll('li.govuk-tabs__list-item');
134
200
  if (!$tabList) {
135
201
  throw new ElementError({
136
- componentName: 'Tabs',
202
+ component: Tabs,
137
203
  identifier: 'List (`<ul class="govuk-tabs__list">`)'
138
204
  });
139
205
  }
140
206
  if (!$tabListItems.length) {
141
207
  throw new ElementError({
142
- componentName: 'Tabs',
208
+ component: Tabs,
143
209
  identifier: 'List items (`<li class="govuk-tabs__list-item">`)'
144
210
  });
145
211
  }
@@ -151,7 +217,7 @@ class Tabs extends GOVUKFrontendComponent {
151
217
  const breakpoint = getBreakpoint('tablet');
152
218
  if (!breakpoint.value) {
153
219
  throw new ElementError({
154
- componentName: 'Tabs',
220
+ component: Tabs,
155
221
  identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
156
222
  });
157
223
  }
@@ -226,7 +292,7 @@ class Tabs extends GOVUKFrontendComponent {
226
292
  this.showPanel($tab);
227
293
  }
228
294
  getTab(hash) {
229
- return this.$module.querySelector(`a.govuk-tabs__tab[href="${hash}"]`);
295
+ return this.$root.querySelector(`a.govuk-tabs__tab[href="${hash}"]`);
230
296
  }
231
297
  setAttributes($tab) {
232
298
  const panelId = getFragmentFromUrl($tab.href);
@@ -337,7 +403,7 @@ class Tabs extends GOVUKFrontendComponent {
337
403
  if (!panelId) {
338
404
  return null;
339
405
  }
340
- return this.$module.querySelector(`#${panelId}`);
406
+ return this.$root.querySelector(`#${panelId}`);
341
407
  }
342
408
  showPanel($tab) {
343
409
  const $panel = this.getPanel($tab);
@@ -370,7 +436,7 @@ class Tabs extends GOVUKFrontendComponent {
370
436
  $tab.setAttribute('tabindex', '0');
371
437
  }
372
438
  getCurrentTab() {
373
- return this.$module.querySelector('.govuk-tabs__list-item--selected a.govuk-tabs__tab');
439
+ return this.$root.querySelector('.govuk-tabs__list-item--selected a.govuk-tabs__tab');
374
440
  }
375
441
  }
376
442
  Tabs.moduleName = 'govuk-tabs';