govuk_publishing_components 44.1.0 → 44.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/lib/govuk_publishing_components/version.rb +1 -1
  3. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +336 -225
  4. data/node_modules/govuk-frontend/dist/govuk/all.bundle.js.map +1 -1
  5. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +334 -226
  6. data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs.map +1 -1
  7. data/node_modules/govuk-frontend/dist/govuk/all.mjs +3 -0
  8. data/node_modules/govuk-frontend/dist/govuk/all.mjs.map +1 -1
  9. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest.svg +1 -0
  10. data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs +1 -1
  11. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs +21 -1
  12. data/node_modules/govuk-frontend/dist/govuk/common/index.mjs.map +1 -1
  13. data/node_modules/govuk-frontend/dist/govuk/components/_index.scss +1 -0
  14. data/node_modules/govuk-frontend/dist/govuk/components/_index.scss.map +1 -1
  15. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +92 -26
  16. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js.map +1 -1
  17. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +92 -26
  18. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs.map +1 -1
  19. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +12 -21
  20. data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs.map +1 -1
  21. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +86 -20
  22. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js.map +1 -1
  23. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +86 -20
  24. data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs.map +1 -1
  25. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs +6 -16
  26. data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs.map +1 -1
  27. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +89 -23
  28. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js.map +1 -1
  29. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +89 -23
  30. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs.map +1 -1
  31. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +10 -19
  32. data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs.map +1 -1
  33. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +113 -47
  34. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js.map +1 -1
  35. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +113 -47
  36. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs.map +1 -1
  37. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs +7 -16
  38. data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs.map +1 -1
  39. data/node_modules/govuk-frontend/dist/govuk/components/details/_index.scss +7 -2
  40. data/node_modules/govuk-frontend/dist/govuk/components/details/_index.scss.map +1 -1
  41. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +86 -20
  42. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js.map +1 -1
  43. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +86 -20
  44. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs.map +1 -1
  45. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs +6 -16
  46. data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs.map +1 -1
  47. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +87 -21
  48. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js.map +1 -1
  49. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +87 -21
  50. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs.map +1 -1
  51. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs +7 -16
  52. data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs.map +1 -1
  53. data/node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss +8 -10
  54. data/node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss.map +1 -1
  55. data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss +8 -0
  56. data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss.map +1 -1
  57. data/node_modules/govuk-frontend/dist/govuk/components/header/fixtures.json +12 -0
  58. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js +87 -21
  59. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js.map +1 -1
  60. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs +87 -21
  61. data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs.map +1 -1
  62. data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs +7 -16
  63. data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs.map +1 -1
  64. data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-full-width-border.html +24 -0
  65. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +86 -20
  66. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js.map +1 -1
  67. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +86 -20
  68. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs.map +1 -1
  69. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs +6 -16
  70. data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs.map +1 -1
  71. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +89 -23
  72. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js.map +1 -1
  73. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +89 -23
  74. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs.map +1 -1
  75. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs +9 -18
  76. data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs.map +1 -1
  77. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +113 -47
  78. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js.map +1 -1
  79. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +113 -47
  80. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs.map +1 -1
  81. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs +7 -16
  82. data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs.map +1 -1
  83. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/README.md +15 -0
  84. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_index.scss +168 -0
  85. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_index.scss.map +1 -0
  86. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_service-navigation.scss +4 -0
  87. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_service-navigation.scss.map +1 -0
  88. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/fixtures.json +464 -0
  89. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/macro-options.json +138 -0
  90. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/macro.njk +3 -0
  91. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +249 -0
  92. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js.map +1 -0
  93. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +241 -0
  94. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs.map +1 -0
  95. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs +85 -0
  96. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs.map +1 -0
  97. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-default.html +57 -0
  98. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-html-navigation-items.html +49 -0
  99. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-large-navigation.html +153 -0
  100. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-long-service-name.html +20 -0
  101. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-navigation-with-a-current-item.html +58 -0
  102. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-navigation-with-an-active-item.html +58 -0
  103. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-non-link-navigation-items.html +49 -0
  104. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-link.html +20 -0
  105. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-name-and-navigation.html +63 -0
  106. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-name.html +18 -0
  107. data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template.njk +102 -0
  108. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +93 -26
  109. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js.map +1 -1
  110. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +93 -26
  111. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs.map +1 -1
  112. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs +13 -21
  113. data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs.map +1 -1
  114. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +93 -27
  115. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js.map +1 -1
  116. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +93 -27
  117. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs.map +1 -1
  118. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs +13 -22
  119. data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs.map +1 -1
  120. data/node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss +4 -3
  121. data/node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss.map +1 -1
  122. data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss +1 -1
  123. data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs +16 -3
  124. data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs.map +1 -1
  125. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend-component.mjs +49 -5
  126. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend-component.mjs.map +1 -1
  127. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css +2 -2
  128. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css.map +1 -1
  129. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
  130. data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js.map +1 -1
  131. data/node_modules/govuk-frontend/dist/govuk/init.mjs +72 -10
  132. data/node_modules/govuk-frontend/dist/govuk/init.mjs.map +1 -1
  133. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss +3 -0
  134. data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss.map +1 -1
  135. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +5 -1
  136. data/node_modules/govuk-frontend/package.json +8 -8
  137. metadata +29 -4
  138. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest-2x.png +0 -0
  139. data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest.png +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"notification-banner.bundle.js","sources":["../../../../src/govuk/common/normalise-string.mjs","../../../../src/govuk/common/index.mjs","../../../../src/govuk/common/normalise-dataset.mjs","../../../../src/govuk/errors/index.mjs","../../../../src/govuk/govuk-frontend-component.mjs","../../../../src/govuk/components/notification-banner/notification-banner.mjs"],"sourcesContent":["/**\n * Normalise string\n *\n * 'If it looks like a duck, and it quacks like a duck…' 🦆\n *\n * If the passed value looks like a boolean or a number, convert it to a boolean\n * or number.\n *\n * Designed to be used to convert config passed via data attributes (which are\n * always strings) into something sensible.\n *\n * @internal\n * @param {DOMStringMap[string]} value - The value to normalise\n * @param {SchemaProperty} [property] - Component schema property\n * @returns {string | boolean | number | undefined} Normalised data\n */\nexport function normaliseString(value, property) {\n const trimmedValue = value ? value.trim() : ''\n\n let output\n let outputType = property?.type\n\n // No schema type set? Determine automatically\n if (!outputType) {\n if (['true', 'false'].includes(trimmedValue)) {\n outputType = 'boolean'\n }\n\n // Empty / whitespace-only strings are considered finite so we need to check\n // the length of the trimmed string as well\n if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {\n outputType = 'number'\n }\n }\n\n switch (outputType) {\n case 'boolean':\n output = trimmedValue === 'true'\n break\n\n case 'number':\n output = Number(trimmedValue)\n break\n\n default:\n output = value\n }\n\n return output\n}\n\n/**\n * @typedef {import('./index.mjs').SchemaProperty} SchemaProperty\n */\n","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","import { extractConfigByNamespace } from './index.mjs'\nimport { normaliseString } from './normalise-string.mjs'\n\n/**\n * Normalise dataset\n *\n * Loop over an object and normalise each value using {@link normaliseString},\n * optionally expanding nested `i18n.field`\n *\n * @internal\n * @param {{ schema: Schema }} Component - Component class\n * @param {DOMStringMap} dataset - HTML element dataset\n * @returns {ObjectNested} Normalised dataset\n */\nexport function normaliseDataset(Component, dataset) {\n const out = /** @type {ReturnType<typeof normaliseDataset>} */ ({})\n\n // Normalise top-level dataset ('data-*') values using schema types\n for (const [field, property] of Object.entries(Component.schema.properties)) {\n if (field in dataset) {\n out[field] = normaliseString(dataset[field], property)\n }\n\n /**\n * Extract and normalise nested object values automatically using\n * {@link normaliseString} but only schema object types are allowed\n */\n if (property?.type === 'object') {\n out[field] = extractConfigByNamespace(Component, dataset, field)\n }\n }\n\n return out\n}\n\n/**\n * @internal\n * @typedef {import('./index.mjs').ObjectNested} ObjectNested\n * @typedef {import('./index.mjs').Schema} Schema\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 { mergeConfigs, setFocus } from '../../common/index.mjs'\nimport { normaliseDataset } from '../../common/normalise-dataset.mjs'\nimport { ElementError } from '../../errors/index.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\n\n/**\n * Notification Banner component\n *\n * @preserve\n */\nexport class NotificationBanner extends GOVUKFrontendComponent {\n /** @private */\n $module\n\n /**\n * @private\n * @type {NotificationBannerConfig}\n */\n config\n\n /**\n * @param {Element | null} $module - HTML element to use for notification banner\n * @param {NotificationBannerConfig} [config] - Notification banner config\n */\n constructor($module, config = {}) {\n super()\n\n if (!($module instanceof HTMLElement)) {\n throw new ElementError({\n componentName: 'Notification banner',\n element: $module,\n identifier: 'Root element (`$module`)'\n })\n }\n\n this.$module = $module\n\n this.config = mergeConfigs(\n NotificationBanner.defaults,\n config,\n normaliseDataset(NotificationBanner, $module.dataset)\n )\n\n /**\n * Focus the notification banner\n *\n * If `role=\"alert\"` is set, focus the element to help some assistive\n * technologies prioritise announcing it.\n *\n * You can turn off the auto-focus functionality by setting\n * `data-disable-auto-focus=\"true\"` in the component HTML. You might wish to\n * do this based on user research findings, or to avoid a clash with another\n * element which should be focused when the page loads.\n */\n if (\n this.$module.getAttribute('role') === 'alert' &&\n !this.config.disableAutoFocus\n ) {\n setFocus(this.$module)\n }\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-notification-banner'\n\n /**\n * Notification banner default config\n *\n * @see {@link NotificationBannerConfig}\n * @constant\n * @type {NotificationBannerConfig}\n */\n static defaults = Object.freeze({\n disableAutoFocus: false\n })\n\n /**\n * Notification banner config schema\n *\n * @constant\n * @satisfies {Schema}\n */\n static schema = Object.freeze({\n properties: {\n disableAutoFocus: { type: 'boolean' }\n }\n })\n}\n\n/**\n * Notification banner config\n *\n * @typedef {object} NotificationBannerConfig\n * @property {boolean} [disableAutoFocus=false] - If set to `true` the\n * notification banner will not be focussed when the page loads. This only\n * applies if the component has a `role` of `alert` – in other cases the\n * component will not be focused on page load, regardless of this option.\n */\n\n/**\n * @typedef {import('../../common/index.mjs').Schema} Schema\n */\n"],"names":["normaliseString","value","property","trimmedValue","trim","output","outputType","type","includes","length","isFinite","Number","mergeConfigs","configObjects","formattedConfigObject","configObject","key","Object","keys","option","override","isObject","extractConfigByNamespace","Component","dataset","namespace","schema","properties","newObject","entries","current","keyParts","split","index","name","setFocus","$element","options","_options$onBeforeFocu","isFocusable","getAttribute","setAttribute","onFocus","addEventListener","onBlur","once","_options$onBlur","call","removeAttribute","onBeforeFocus","focus","isSupported","$scope","document","body","classList","contains","isArray","Array","normaliseDataset","out","field","GOVUKFrontendError","Error","constructor","args","SupportError","supportMessage","HTMLScriptElement","prototype","ElementError","messageOrOptions","message","componentName","identifier","element","expectedType","GOVUKFrontendComponent","checkSupport","NotificationBanner","$module","config","HTMLElement","defaults","disableAutoFocus","moduleName","freeze"],"mappings":"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"}
1
+ {"version":3,"file":"notification-banner.bundle.js","sources":["../../../../src/govuk/common/normalise-string.mjs","../../../../src/govuk/common/index.mjs","../../../../src/govuk/common/normalise-dataset.mjs","../../../../src/govuk/errors/index.mjs","../../../../src/govuk/govuk-frontend-component.mjs","../../../../src/govuk/components/notification-banner/notification-banner.mjs"],"sourcesContent":["/**\n * Normalise string\n *\n * 'If it looks like a duck, and it quacks like a duck…' 🦆\n *\n * If the passed value looks like a boolean or a number, convert it to a boolean\n * or number.\n *\n * Designed to be used to convert config passed via data attributes (which are\n * always strings) into something sensible.\n *\n * @internal\n * @param {DOMStringMap[string]} value - The value to normalise\n * @param {SchemaProperty} [property] - Component schema property\n * @returns {string | boolean | number | undefined} Normalised data\n */\nexport function normaliseString(value, property) {\n const trimmedValue = value ? value.trim() : ''\n\n let output\n let outputType = property?.type\n\n // No schema type set? Determine automatically\n if (!outputType) {\n if (['true', 'false'].includes(trimmedValue)) {\n outputType = 'boolean'\n }\n\n // Empty / whitespace-only strings are considered finite so we need to check\n // the length of the trimmed string as well\n if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {\n outputType = 'number'\n }\n }\n\n switch (outputType) {\n case 'boolean':\n output = trimmedValue === 'true'\n break\n\n case 'number':\n output = Number(trimmedValue)\n break\n\n default:\n output = value\n }\n\n return output\n}\n\n/**\n * @typedef {import('./index.mjs').SchemaProperty} SchemaProperty\n */\n","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 { extractConfigByNamespace } from './index.mjs'\nimport { normaliseString } from './normalise-string.mjs'\n\n/**\n * Normalise dataset\n *\n * Loop over an object and normalise each value using {@link normaliseString},\n * optionally expanding nested `i18n.field`\n *\n * @internal\n * @param {{ schema: Schema }} Component - Component class\n * @param {DOMStringMap} dataset - HTML element dataset\n * @returns {ObjectNested} Normalised dataset\n */\nexport function normaliseDataset(Component, dataset) {\n const out = /** @type {ReturnType<typeof normaliseDataset>} */ ({})\n\n // Normalise top-level dataset ('data-*') values using schema types\n for (const [field, property] of Object.entries(Component.schema.properties)) {\n if (field in dataset) {\n out[field] = normaliseString(dataset[field], property)\n }\n\n /**\n * Extract and normalise nested object values automatically using\n * {@link normaliseString} but only schema object types are allowed\n */\n if (property?.type === 'object') {\n out[field] = extractConfigByNamespace(Component, dataset, field)\n }\n }\n\n return out\n}\n\n/**\n * @internal\n * @typedef {import('./index.mjs').ObjectNested} ObjectNested\n * @typedef {import('./index.mjs').Schema} Schema\n */\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 { mergeConfigs, setFocus } from '../../common/index.mjs'\nimport { normaliseDataset } from '../../common/normalise-dataset.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\n\n/**\n * Notification Banner component\n *\n * @preserve\n */\nexport class NotificationBanner extends GOVUKFrontendComponent {\n /**\n * @private\n * @type {NotificationBannerConfig}\n */\n config\n\n /**\n * @param {Element | null} $root - HTML element to use for notification banner\n * @param {NotificationBannerConfig} [config] - Notification banner config\n */\n constructor($root, config = {}) {\n super($root)\n\n this.config = mergeConfigs(\n NotificationBanner.defaults,\n config,\n normaliseDataset(NotificationBanner, this.$root.dataset)\n )\n\n /**\n * Focus the notification banner\n *\n * If `role=\"alert\"` is set, focus the element to help some assistive\n * technologies prioritise announcing it.\n *\n * You can turn off the auto-focus functionality by setting\n * `data-disable-auto-focus=\"true\"` in the component HTML. You might wish to\n * do this based on user research findings, or to avoid a clash with another\n * element which should be focused when the page loads.\n */\n if (\n this.$root.getAttribute('role') === 'alert' &&\n !this.config.disableAutoFocus\n ) {\n setFocus(this.$root)\n }\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-notification-banner'\n\n /**\n * Notification banner default config\n *\n * @see {@link NotificationBannerConfig}\n * @constant\n * @type {NotificationBannerConfig}\n */\n static defaults = Object.freeze({\n disableAutoFocus: false\n })\n\n /**\n * Notification banner config schema\n *\n * @constant\n * @satisfies {Schema}\n */\n static schema = Object.freeze({\n properties: {\n disableAutoFocus: { type: 'boolean' }\n }\n })\n}\n\n/**\n * Notification banner config\n *\n * @typedef {object} NotificationBannerConfig\n * @property {boolean} [disableAutoFocus=false] - If set to `true` the\n * notification banner will not be focussed when the page loads. This only\n * applies if the component has a `role` of `alert` – in other cases the\n * component will not be focused on page load, regardless of this option.\n */\n\n/**\n * @typedef {import('../../common/index.mjs').Schema} Schema\n */\n"],"names":["normaliseString","value","property","trimmedValue","trim","output","outputType","type","includes","length","isFinite","Number","mergeConfigs","configObjects","formattedConfigObject","configObject","key","Object","keys","option","override","isObject","extractConfigByNamespace","Component","dataset","namespace","schema","properties","newObject","entries","current","keyParts","split","index","name","setFocus","$element","options","_options$onBeforeFocu","isFocusable","getAttribute","setAttribute","onFocus","addEventListener","onBlur","once","_options$onBlur","call","removeAttribute","onBeforeFocus","focus","isInitialised","$root","moduleName","HTMLElement","hasAttribute","isSupported","$scope","document","body","classList","contains","isArray","Array","formatErrorMessage","message","normaliseDataset","out","field","GOVUKFrontendError","Error","constructor","args","SupportError","supportMessage","HTMLScriptElement","prototype","ElementError","messageOrOptions","component","identifier","element","expectedType","InitError","componentOrMessage","GOVUKFrontendComponent","_$root","childConstructor","elementType","checkSupport","checkInitialised","NotificationBanner","config","defaults","disableAutoFocus","freeze"],"mappings":"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"}
@@ -92,6 +92,19 @@ function setFocus($element, options = {}) {
92
92
  (_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
93
93
  $element.focus();
94
94
  }
95
+ function isInitialised($root, moduleName) {
96
+ return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);
97
+ }
98
+
99
+ /**
100
+ * Checks if GOV.UK Frontend is supported on this page
101
+ *
102
+ * Some browsers will load and run our JavaScript but GOV.UK Frontend
103
+ * won't be supported.
104
+ *
105
+ * @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
106
+ * @returns {boolean} Whether GOV.UK Frontend is supported on this page
107
+ */
95
108
  function isSupported($scope = document.body) {
96
109
  if (!$scope) {
97
110
  return false;
@@ -104,6 +117,9 @@ function isArray(option) {
104
117
  function isObject(option) {
105
118
  return !!option && typeof option === 'object' && !isArray(option);
106
119
  }
120
+ function formatErrorMessage(Component, message) {
121
+ return `${Component.moduleName}: ${message}`;
122
+ }
107
123
 
108
124
  /**
109
125
  * Schema for component config
@@ -127,6 +143,10 @@ function isObject(option) {
127
143
  * @property {string[]} required - List of required config fields
128
144
  * @property {string} errorMessage - Error message when required config fields not provided
129
145
  */
146
+ /**
147
+ * @typedef ComponentWithModuleName
148
+ * @property {string} moduleName - Name of the component
149
+ */
130
150
 
131
151
  function normaliseDataset(Component, dataset) {
132
152
  const out = {};
@@ -164,30 +184,85 @@ class ElementError extends GOVUKFrontendError {
164
184
  let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
165
185
  if (typeof messageOrOptions === 'object') {
166
186
  const {
167
- componentName,
187
+ component,
168
188
  identifier,
169
189
  element,
170
190
  expectedType
171
191
  } = messageOrOptions;
172
- message = `${componentName}: ${identifier}`;
192
+ message = identifier;
173
193
  message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
194
+ message = formatErrorMessage(component, message);
174
195
  }
175
196
  super(message);
176
197
  this.name = 'ElementError';
177
198
  }
178
199
  }
200
+ class InitError extends GOVUKFrontendError {
201
+ constructor(componentOrMessage) {
202
+ const message = typeof componentOrMessage === 'string' ? componentOrMessage : formatErrorMessage(componentOrMessage, `Root element (\`$root\`) already initialised`);
203
+ super(message);
204
+ this.name = 'InitError';
205
+ }
206
+ }
207
+ /**
208
+ * @typedef {import('../common/index.mjs').ComponentWithModuleName} ComponentWithModuleName
209
+ */
179
210
 
180
211
  class GOVUKFrontendComponent {
181
- constructor() {
182
- this.checkSupport();
212
+ /**
213
+ * Returns the root element of the component
214
+ *
215
+ * @protected
216
+ * @returns {RootElementType} - the root element of component
217
+ */
218
+ get $root() {
219
+ return this._$root;
183
220
  }
184
- checkSupport() {
221
+ constructor($root) {
222
+ this._$root = void 0;
223
+ const childConstructor = this.constructor;
224
+ if (typeof childConstructor.moduleName !== 'string') {
225
+ throw new InitError(`\`moduleName\` not defined in component`);
226
+ }
227
+ if (!($root instanceof childConstructor.elementType)) {
228
+ throw new ElementError({
229
+ element: $root,
230
+ component: childConstructor,
231
+ identifier: 'Root element (`$root`)',
232
+ expectedType: childConstructor.elementType.name
233
+ });
234
+ } else {
235
+ this._$root = $root;
236
+ }
237
+ childConstructor.checkSupport();
238
+ this.checkInitialised();
239
+ const moduleName = childConstructor.moduleName;
240
+ this.$root.setAttribute(`data-${moduleName}-init`, '');
241
+ }
242
+ checkInitialised() {
243
+ const constructor = this.constructor;
244
+ const moduleName = constructor.moduleName;
245
+ if (moduleName && isInitialised(this.$root, moduleName)) {
246
+ throw new InitError(constructor);
247
+ }
248
+ }
249
+ static checkSupport() {
185
250
  if (!isSupported()) {
186
251
  throw new SupportError();
187
252
  }
188
253
  }
189
254
  }
190
255
 
256
+ /**
257
+ * @typedef ChildClass
258
+ * @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
259
+ */
260
+
261
+ /**
262
+ * @typedef {typeof GOVUKFrontendComponent & ChildClass} ChildClassConstructor
263
+ */
264
+ GOVUKFrontendComponent.elementType = HTMLElement;
265
+
191
266
  /**
192
267
  * Notification Banner component
193
268
  *
@@ -195,24 +270,15 @@ class GOVUKFrontendComponent {
195
270
  */
196
271
  class NotificationBanner extends GOVUKFrontendComponent {
197
272
  /**
198
- * @param {Element | null} $module - HTML element to use for notification banner
273
+ * @param {Element | null} $root - HTML element to use for notification banner
199
274
  * @param {NotificationBannerConfig} [config] - Notification banner config
200
275
  */
201
- constructor($module, config = {}) {
202
- super();
203
- this.$module = void 0;
276
+ constructor($root, config = {}) {
277
+ super($root);
204
278
  this.config = void 0;
205
- if (!($module instanceof HTMLElement)) {
206
- throw new ElementError({
207
- componentName: 'Notification banner',
208
- element: $module,
209
- identifier: 'Root element (`$module`)'
210
- });
211
- }
212
- this.$module = $module;
213
- this.config = mergeConfigs(NotificationBanner.defaults, config, normaliseDataset(NotificationBanner, $module.dataset));
214
- if (this.$module.getAttribute('role') === 'alert' && !this.config.disableAutoFocus) {
215
- setFocus(this.$module);
279
+ this.config = mergeConfigs(NotificationBanner.defaults, config, normaliseDataset(NotificationBanner, this.$root.dataset));
280
+ if (this.$root.getAttribute('role') === 'alert' && !this.config.disableAutoFocus) {
281
+ setFocus(this.$root);
216
282
  }
217
283
  }
218
284
  }
@@ -1 +1 @@
1
- {"version":3,"file":"notification-banner.bundle.mjs","sources":["../../../../src/govuk/common/normalise-string.mjs","../../../../src/govuk/common/index.mjs","../../../../src/govuk/common/normalise-dataset.mjs","../../../../src/govuk/errors/index.mjs","../../../../src/govuk/govuk-frontend-component.mjs","../../../../src/govuk/components/notification-banner/notification-banner.mjs"],"sourcesContent":["/**\n * Normalise string\n *\n * 'If it looks like a duck, and it quacks like a duck…' 🦆\n *\n * If the passed value looks like a boolean or a number, convert it to a boolean\n * or number.\n *\n * Designed to be used to convert config passed via data attributes (which are\n * always strings) into something sensible.\n *\n * @internal\n * @param {DOMStringMap[string]} value - The value to normalise\n * @param {SchemaProperty} [property] - Component schema property\n * @returns {string | boolean | number | undefined} Normalised data\n */\nexport function normaliseString(value, property) {\n const trimmedValue = value ? value.trim() : ''\n\n let output\n let outputType = property?.type\n\n // No schema type set? Determine automatically\n if (!outputType) {\n if (['true', 'false'].includes(trimmedValue)) {\n outputType = 'boolean'\n }\n\n // Empty / whitespace-only strings are considered finite so we need to check\n // the length of the trimmed string as well\n if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {\n outputType = 'number'\n }\n }\n\n switch (outputType) {\n case 'boolean':\n output = trimmedValue === 'true'\n break\n\n case 'number':\n output = Number(trimmedValue)\n break\n\n default:\n output = value\n }\n\n return output\n}\n\n/**\n * @typedef {import('./index.mjs').SchemaProperty} SchemaProperty\n */\n","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","import { extractConfigByNamespace } from './index.mjs'\nimport { normaliseString } from './normalise-string.mjs'\n\n/**\n * Normalise dataset\n *\n * Loop over an object and normalise each value using {@link normaliseString},\n * optionally expanding nested `i18n.field`\n *\n * @internal\n * @param {{ schema: Schema }} Component - Component class\n * @param {DOMStringMap} dataset - HTML element dataset\n * @returns {ObjectNested} Normalised dataset\n */\nexport function normaliseDataset(Component, dataset) {\n const out = /** @type {ReturnType<typeof normaliseDataset>} */ ({})\n\n // Normalise top-level dataset ('data-*') values using schema types\n for (const [field, property] of Object.entries(Component.schema.properties)) {\n if (field in dataset) {\n out[field] = normaliseString(dataset[field], property)\n }\n\n /**\n * Extract and normalise nested object values automatically using\n * {@link normaliseString} but only schema object types are allowed\n */\n if (property?.type === 'object') {\n out[field] = extractConfigByNamespace(Component, dataset, field)\n }\n }\n\n return out\n}\n\n/**\n * @internal\n * @typedef {import('./index.mjs').ObjectNested} ObjectNested\n * @typedef {import('./index.mjs').Schema} Schema\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 { mergeConfigs, setFocus } from '../../common/index.mjs'\nimport { normaliseDataset } from '../../common/normalise-dataset.mjs'\nimport { ElementError } from '../../errors/index.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\n\n/**\n * Notification Banner component\n *\n * @preserve\n */\nexport class NotificationBanner extends GOVUKFrontendComponent {\n /** @private */\n $module\n\n /**\n * @private\n * @type {NotificationBannerConfig}\n */\n config\n\n /**\n * @param {Element | null} $module - HTML element to use for notification banner\n * @param {NotificationBannerConfig} [config] - Notification banner config\n */\n constructor($module, config = {}) {\n super()\n\n if (!($module instanceof HTMLElement)) {\n throw new ElementError({\n componentName: 'Notification banner',\n element: $module,\n identifier: 'Root element (`$module`)'\n })\n }\n\n this.$module = $module\n\n this.config = mergeConfigs(\n NotificationBanner.defaults,\n config,\n normaliseDataset(NotificationBanner, $module.dataset)\n )\n\n /**\n * Focus the notification banner\n *\n * If `role=\"alert\"` is set, focus the element to help some assistive\n * technologies prioritise announcing it.\n *\n * You can turn off the auto-focus functionality by setting\n * `data-disable-auto-focus=\"true\"` in the component HTML. You might wish to\n * do this based on user research findings, or to avoid a clash with another\n * element which should be focused when the page loads.\n */\n if (\n this.$module.getAttribute('role') === 'alert' &&\n !this.config.disableAutoFocus\n ) {\n setFocus(this.$module)\n }\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-notification-banner'\n\n /**\n * Notification banner default config\n *\n * @see {@link NotificationBannerConfig}\n * @constant\n * @type {NotificationBannerConfig}\n */\n static defaults = Object.freeze({\n disableAutoFocus: false\n })\n\n /**\n * Notification banner config schema\n *\n * @constant\n * @satisfies {Schema}\n */\n static schema = Object.freeze({\n properties: {\n disableAutoFocus: { type: 'boolean' }\n }\n })\n}\n\n/**\n * Notification banner config\n *\n * @typedef {object} NotificationBannerConfig\n * @property {boolean} [disableAutoFocus=false] - If set to `true` the\n * notification banner will not be focussed when the page loads. This only\n * applies if the component has a `role` of `alert` – in other cases the\n * component will not be focused on page load, regardless of this option.\n */\n\n/**\n * @typedef {import('../../common/index.mjs').Schema} Schema\n */\n"],"names":["normaliseString","value","property","trimmedValue","trim","output","outputType","type","includes","length","isFinite","Number","mergeConfigs","configObjects","formattedConfigObject","configObject","key","Object","keys","option","override","isObject","extractConfigByNamespace","Component","dataset","namespace","schema","properties","newObject","entries","current","keyParts","split","index","name","setFocus","$element","options","_options$onBeforeFocu","isFocusable","getAttribute","setAttribute","onFocus","addEventListener","onBlur","once","_options$onBlur","call","removeAttribute","onBeforeFocus","focus","isSupported","$scope","document","body","classList","contains","isArray","Array","normaliseDataset","out","field","GOVUKFrontendError","Error","constructor","args","SupportError","supportMessage","HTMLScriptElement","prototype","ElementError","messageOrOptions","message","componentName","identifier","element","expectedType","GOVUKFrontendComponent","checkSupport","NotificationBanner","$module","config","HTMLElement","defaults","disableAutoFocus","moduleName","freeze"],"mappings":"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"}
1
+ {"version":3,"file":"notification-banner.bundle.mjs","sources":["../../../../src/govuk/common/normalise-string.mjs","../../../../src/govuk/common/index.mjs","../../../../src/govuk/common/normalise-dataset.mjs","../../../../src/govuk/errors/index.mjs","../../../../src/govuk/govuk-frontend-component.mjs","../../../../src/govuk/components/notification-banner/notification-banner.mjs"],"sourcesContent":["/**\n * Normalise string\n *\n * 'If it looks like a duck, and it quacks like a duck…' 🦆\n *\n * If the passed value looks like a boolean or a number, convert it to a boolean\n * or number.\n *\n * Designed to be used to convert config passed via data attributes (which are\n * always strings) into something sensible.\n *\n * @internal\n * @param {DOMStringMap[string]} value - The value to normalise\n * @param {SchemaProperty} [property] - Component schema property\n * @returns {string | boolean | number | undefined} Normalised data\n */\nexport function normaliseString(value, property) {\n const trimmedValue = value ? value.trim() : ''\n\n let output\n let outputType = property?.type\n\n // No schema type set? Determine automatically\n if (!outputType) {\n if (['true', 'false'].includes(trimmedValue)) {\n outputType = 'boolean'\n }\n\n // Empty / whitespace-only strings are considered finite so we need to check\n // the length of the trimmed string as well\n if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {\n outputType = 'number'\n }\n }\n\n switch (outputType) {\n case 'boolean':\n output = trimmedValue === 'true'\n break\n\n case 'number':\n output = Number(trimmedValue)\n break\n\n default:\n output = value\n }\n\n return output\n}\n\n/**\n * @typedef {import('./index.mjs').SchemaProperty} SchemaProperty\n */\n","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 { extractConfigByNamespace } from './index.mjs'\nimport { normaliseString } from './normalise-string.mjs'\n\n/**\n * Normalise dataset\n *\n * Loop over an object and normalise each value using {@link normaliseString},\n * optionally expanding nested `i18n.field`\n *\n * @internal\n * @param {{ schema: Schema }} Component - Component class\n * @param {DOMStringMap} dataset - HTML element dataset\n * @returns {ObjectNested} Normalised dataset\n */\nexport function normaliseDataset(Component, dataset) {\n const out = /** @type {ReturnType<typeof normaliseDataset>} */ ({})\n\n // Normalise top-level dataset ('data-*') values using schema types\n for (const [field, property] of Object.entries(Component.schema.properties)) {\n if (field in dataset) {\n out[field] = normaliseString(dataset[field], property)\n }\n\n /**\n * Extract and normalise nested object values automatically using\n * {@link normaliseString} but only schema object types are allowed\n */\n if (property?.type === 'object') {\n out[field] = extractConfigByNamespace(Component, dataset, field)\n }\n }\n\n return out\n}\n\n/**\n * @internal\n * @typedef {import('./index.mjs').ObjectNested} ObjectNested\n * @typedef {import('./index.mjs').Schema} Schema\n */\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 { mergeConfigs, setFocus } from '../../common/index.mjs'\nimport { normaliseDataset } from '../../common/normalise-dataset.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\n\n/**\n * Notification Banner component\n *\n * @preserve\n */\nexport class NotificationBanner extends GOVUKFrontendComponent {\n /**\n * @private\n * @type {NotificationBannerConfig}\n */\n config\n\n /**\n * @param {Element | null} $root - HTML element to use for notification banner\n * @param {NotificationBannerConfig} [config] - Notification banner config\n */\n constructor($root, config = {}) {\n super($root)\n\n this.config = mergeConfigs(\n NotificationBanner.defaults,\n config,\n normaliseDataset(NotificationBanner, this.$root.dataset)\n )\n\n /**\n * Focus the notification banner\n *\n * If `role=\"alert\"` is set, focus the element to help some assistive\n * technologies prioritise announcing it.\n *\n * You can turn off the auto-focus functionality by setting\n * `data-disable-auto-focus=\"true\"` in the component HTML. You might wish to\n * do this based on user research findings, or to avoid a clash with another\n * element which should be focused when the page loads.\n */\n if (\n this.$root.getAttribute('role') === 'alert' &&\n !this.config.disableAutoFocus\n ) {\n setFocus(this.$root)\n }\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-notification-banner'\n\n /**\n * Notification banner default config\n *\n * @see {@link NotificationBannerConfig}\n * @constant\n * @type {NotificationBannerConfig}\n */\n static defaults = Object.freeze({\n disableAutoFocus: false\n })\n\n /**\n * Notification banner config schema\n *\n * @constant\n * @satisfies {Schema}\n */\n static schema = Object.freeze({\n properties: {\n disableAutoFocus: { type: 'boolean' }\n }\n })\n}\n\n/**\n * Notification banner config\n *\n * @typedef {object} NotificationBannerConfig\n * @property {boolean} [disableAutoFocus=false] - If set to `true` the\n * notification banner will not be focussed when the page loads. This only\n * applies if the component has a `role` of `alert` – in other cases the\n * component will not be focused on page load, regardless of this option.\n */\n\n/**\n * @typedef {import('../../common/index.mjs').Schema} Schema\n */\n"],"names":["normaliseString","value","property","trimmedValue","trim","output","outputType","type","includes","length","isFinite","Number","mergeConfigs","configObjects","formattedConfigObject","configObject","key","Object","keys","option","override","isObject","extractConfigByNamespace","Component","dataset","namespace","schema","properties","newObject","entries","current","keyParts","split","index","name","setFocus","$element","options","_options$onBeforeFocu","isFocusable","getAttribute","setAttribute","onFocus","addEventListener","onBlur","once","_options$onBlur","call","removeAttribute","onBeforeFocus","focus","isInitialised","$root","moduleName","HTMLElement","hasAttribute","isSupported","$scope","document","body","classList","contains","isArray","Array","formatErrorMessage","message","normaliseDataset","out","field","GOVUKFrontendError","Error","constructor","args","SupportError","supportMessage","HTMLScriptElement","prototype","ElementError","messageOrOptions","component","identifier","element","expectedType","InitError","componentOrMessage","GOVUKFrontendComponent","_$root","childConstructor","elementType","checkSupport","checkInitialised","NotificationBanner","config","defaults","disableAutoFocus","freeze"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { mergeConfigs, setFocus } from '../../common/index.mjs';
2
2
  import { normaliseDataset } from '../../common/normalise-dataset.mjs';
3
- import { ElementError } from '../../errors/index.mjs';
4
3
  import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs';
5
4
 
6
5
  /**
@@ -10,24 +9,15 @@ import { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs';
10
9
  */
11
10
  class NotificationBanner extends GOVUKFrontendComponent {
12
11
  /**
13
- * @param {Element | null} $module - HTML element to use for notification banner
12
+ * @param {Element | null} $root - HTML element to use for notification banner
14
13
  * @param {NotificationBannerConfig} [config] - Notification banner config
15
14
  */
16
- constructor($module, config = {}) {
17
- super();
18
- this.$module = void 0;
15
+ constructor($root, config = {}) {
16
+ super($root);
19
17
  this.config = void 0;
20
- if (!($module instanceof HTMLElement)) {
21
- throw new ElementError({
22
- componentName: 'Notification banner',
23
- element: $module,
24
- identifier: 'Root element (`$module`)'
25
- });
26
- }
27
- this.$module = $module;
28
- this.config = mergeConfigs(NotificationBanner.defaults, config, normaliseDataset(NotificationBanner, $module.dataset));
29
- if (this.$module.getAttribute('role') === 'alert' && !this.config.disableAutoFocus) {
30
- setFocus(this.$module);
18
+ this.config = mergeConfigs(NotificationBanner.defaults, config, normaliseDataset(NotificationBanner, this.$root.dataset));
19
+ if (this.$root.getAttribute('role') === 'alert' && !this.config.disableAutoFocus) {
20
+ setFocus(this.$root);
31
21
  }
32
22
  }
33
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"notification-banner.mjs","sources":["../../../../src/govuk/components/notification-banner/notification-banner.mjs"],"sourcesContent":["import { mergeConfigs, setFocus } from '../../common/index.mjs'\nimport { normaliseDataset } from '../../common/normalise-dataset.mjs'\nimport { ElementError } from '../../errors/index.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\n\n/**\n * Notification Banner component\n *\n * @preserve\n */\nexport class NotificationBanner extends GOVUKFrontendComponent {\n /** @private */\n $module\n\n /**\n * @private\n * @type {NotificationBannerConfig}\n */\n config\n\n /**\n * @param {Element | null} $module - HTML element to use for notification banner\n * @param {NotificationBannerConfig} [config] - Notification banner config\n */\n constructor($module, config = {}) {\n super()\n\n if (!($module instanceof HTMLElement)) {\n throw new ElementError({\n componentName: 'Notification banner',\n element: $module,\n identifier: 'Root element (`$module`)'\n })\n }\n\n this.$module = $module\n\n this.config = mergeConfigs(\n NotificationBanner.defaults,\n config,\n normaliseDataset(NotificationBanner, $module.dataset)\n )\n\n /**\n * Focus the notification banner\n *\n * If `role=\"alert\"` is set, focus the element to help some assistive\n * technologies prioritise announcing it.\n *\n * You can turn off the auto-focus functionality by setting\n * `data-disable-auto-focus=\"true\"` in the component HTML. You might wish to\n * do this based on user research findings, or to avoid a clash with another\n * element which should be focused when the page loads.\n */\n if (\n this.$module.getAttribute('role') === 'alert' &&\n !this.config.disableAutoFocus\n ) {\n setFocus(this.$module)\n }\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-notification-banner'\n\n /**\n * Notification banner default config\n *\n * @see {@link NotificationBannerConfig}\n * @constant\n * @type {NotificationBannerConfig}\n */\n static defaults = Object.freeze({\n disableAutoFocus: false\n })\n\n /**\n * Notification banner config schema\n *\n * @constant\n * @satisfies {Schema}\n */\n static schema = Object.freeze({\n properties: {\n disableAutoFocus: { type: 'boolean' }\n }\n })\n}\n\n/**\n * Notification banner config\n *\n * @typedef {object} NotificationBannerConfig\n * @property {boolean} [disableAutoFocus=false] - If set to `true` the\n * notification banner will not be focussed when the page loads. This only\n * applies if the component has a `role` of `alert` – in other cases the\n * component will not be focused on page load, regardless of this option.\n */\n\n/**\n * @typedef {import('../../common/index.mjs').Schema} Schema\n */\n"],"names":["NotificationBanner","GOVUKFrontendComponent","constructor","$module","config","HTMLElement","ElementError","componentName","element","identifier","mergeConfigs","defaults","normaliseDataset","dataset","getAttribute","disableAutoFocus","setFocus","moduleName","Object","freeze","schema","properties","type"],"mappings":";;;;;AAKA;AACA;AACA;AACA;AACA;AACO,MAAMA,kBAAkB,SAASC,sBAAsB,CAAC;AAU7D;AACF;AACA;AACA;AACEC,EAAAA,WAAWA,CAACC,OAAO,EAAEC,MAAM,GAAG,EAAE,EAAE;AAChC,IAAA,KAAK,EAAE,CAAA;AAAA,IAAA,IAAA,CAbTD,OAAO,GAAA,KAAA,CAAA,CAAA;AAAA,IAAA,IAAA,CAMPC,MAAM,GAAA,KAAA,CAAA,CAAA;AASJ,IAAA,IAAI,EAAED,OAAO,YAAYE,WAAW,CAAC,EAAE;MACrC,MAAM,IAAIC,YAAY,CAAC;AACrBC,QAAAA,aAAa,EAAE,qBAAqB;AACpCC,QAAAA,OAAO,EAAEL,OAAO;AAChBM,QAAAA,UAAU,EAAE,0BAAA;AACd,OAAC,CAAC,CAAA;AACJ,KAAA;IAEA,IAAI,CAACN,OAAO,GAAGA,OAAO,CAAA;AAEtB,IAAA,IAAI,CAACC,MAAM,GAAGM,YAAY,CACxBV,kBAAkB,CAACW,QAAQ,EAC3BP,MAAM,EACNQ,gBAAgB,CAACZ,kBAAkB,EAAEG,OAAO,CAACU,OAAO,CACtD,CAAC,CAAA;AAaD,IAAA,IACE,IAAI,CAACV,OAAO,CAACW,YAAY,CAAC,MAAM,CAAC,KAAK,OAAO,IAC7C,CAAC,IAAI,CAACV,MAAM,CAACW,gBAAgB,EAC7B;AACAC,MAAAA,QAAQ,CAAC,IAAI,CAACb,OAAO,CAAC,CAAA;AACxB,KAAA;AACF,GAAA;AA6BF,CAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AA7FaH,kBAAkB,CAuDtBiB,UAAU,GAAG,2BAA2B,CAAA;AAvDpCjB,kBAAkB,CAgEtBW,QAAQ,GAAGO,MAAM,CAACC,MAAM,CAAC;AAC9BJ,EAAAA,gBAAgB,EAAE,KAAA;AACpB,CAAC,CAAC,CAAA;AAlESf,kBAAkB,CA0EtBoB,MAAM,GAAGF,MAAM,CAACC,MAAM,CAAC;AAC5BE,EAAAA,UAAU,EAAE;AACVN,IAAAA,gBAAgB,EAAE;AAAEO,MAAAA,IAAI,EAAE,SAAA;AAAU,KAAA;AACtC,GAAA;AACF,CAAC,CAAC;;;;"}
1
+ {"version":3,"file":"notification-banner.mjs","sources":["../../../../src/govuk/components/notification-banner/notification-banner.mjs"],"sourcesContent":["import { mergeConfigs, setFocus } from '../../common/index.mjs'\nimport { normaliseDataset } from '../../common/normalise-dataset.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\n\n/**\n * Notification Banner component\n *\n * @preserve\n */\nexport class NotificationBanner extends GOVUKFrontendComponent {\n /**\n * @private\n * @type {NotificationBannerConfig}\n */\n config\n\n /**\n * @param {Element | null} $root - HTML element to use for notification banner\n * @param {NotificationBannerConfig} [config] - Notification banner config\n */\n constructor($root, config = {}) {\n super($root)\n\n this.config = mergeConfigs(\n NotificationBanner.defaults,\n config,\n normaliseDataset(NotificationBanner, this.$root.dataset)\n )\n\n /**\n * Focus the notification banner\n *\n * If `role=\"alert\"` is set, focus the element to help some assistive\n * technologies prioritise announcing it.\n *\n * You can turn off the auto-focus functionality by setting\n * `data-disable-auto-focus=\"true\"` in the component HTML. You might wish to\n * do this based on user research findings, or to avoid a clash with another\n * element which should be focused when the page loads.\n */\n if (\n this.$root.getAttribute('role') === 'alert' &&\n !this.config.disableAutoFocus\n ) {\n setFocus(this.$root)\n }\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-notification-banner'\n\n /**\n * Notification banner default config\n *\n * @see {@link NotificationBannerConfig}\n * @constant\n * @type {NotificationBannerConfig}\n */\n static defaults = Object.freeze({\n disableAutoFocus: false\n })\n\n /**\n * Notification banner config schema\n *\n * @constant\n * @satisfies {Schema}\n */\n static schema = Object.freeze({\n properties: {\n disableAutoFocus: { type: 'boolean' }\n }\n })\n}\n\n/**\n * Notification banner config\n *\n * @typedef {object} NotificationBannerConfig\n * @property {boolean} [disableAutoFocus=false] - If set to `true` the\n * notification banner will not be focussed when the page loads. This only\n * applies if the component has a `role` of `alert` – in other cases the\n * component will not be focused on page load, regardless of this option.\n */\n\n/**\n * @typedef {import('../../common/index.mjs').Schema} Schema\n */\n"],"names":["NotificationBanner","GOVUKFrontendComponent","constructor","$root","config","mergeConfigs","defaults","normaliseDataset","dataset","getAttribute","disableAutoFocus","setFocus","moduleName","Object","freeze","schema","properties","type"],"mappings":";;;;AAIA;AACA;AACA;AACA;AACA;AACO,MAAMA,kBAAkB,SAASC,sBAAsB,CAAC;AAO7D;AACF;AACA;AACA;AACEC,EAAAA,WAAWA,CAACC,KAAK,EAAEC,MAAM,GAAG,EAAE,EAAE;IAC9B,KAAK,CAACD,KAAK,CAAC,CAAA;AAAA,IAAA,IAAA,CAPdC,MAAM,GAAA,KAAA,CAAA,CAAA;IASJ,IAAI,CAACA,MAAM,GAAGC,YAAY,CACxBL,kBAAkB,CAACM,QAAQ,EAC3BF,MAAM,EACNG,gBAAgB,CAACP,kBAAkB,EAAE,IAAI,CAACG,KAAK,CAACK,OAAO,CACzD,CAAC,CAAA;AAaD,IAAA,IACE,IAAI,CAACL,KAAK,CAACM,YAAY,CAAC,MAAM,CAAC,KAAK,OAAO,IAC3C,CAAC,IAAI,CAACL,MAAM,CAACM,gBAAgB,EAC7B;AACAC,MAAAA,QAAQ,CAAC,IAAI,CAACR,KAAK,CAAC,CAAA;AACtB,KAAA;AACF,GAAA;AA6BF,CAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AAhFaH,kBAAkB,CA0CtBY,UAAU,GAAG,2BAA2B,CAAA;AA1CpCZ,kBAAkB,CAmDtBM,QAAQ,GAAGO,MAAM,CAACC,MAAM,CAAC;AAC9BJ,EAAAA,gBAAgB,EAAE,KAAA;AACpB,CAAC,CAAC,CAAA;AArDSV,kBAAkB,CA6DtBe,MAAM,GAAGF,MAAM,CAACC,MAAM,CAAC;AAC5BE,EAAAA,UAAU,EAAE;AACVN,IAAAA,gBAAgB,EAAE;AAAEO,MAAAA,IAAI,EAAE,SAAA;AAAU,KAAA;AACtC,GAAA;AACF,CAAC,CAAC;;;;"}