govuk_publishing_components 51.1.0 → 51.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/component_guide/application.scss +1 -1
- data/app/assets/stylesheets/govuk_publishing_components/_all_components.scss +1 -0
- data/app/assets/stylesheets/govuk_publishing_components/components/_metadata.scss +3 -19
- data/app/assets/stylesheets/govuk_publishing_components/components/helpers/_markdown-typography.scss +1 -0
- data/app/models/govuk_publishing_components/audit_comparer.rb +3 -3
- data/app/views/govuk_publishing_components/components/_title.html.erb +2 -3
- data/app/views/govuk_publishing_components/components/docs/add_another.yml +1 -1
- data/app/views/govuk_publishing_components/components/docs/big_number.yml +1 -0
- data/lib/govuk_publishing_components/presenters/checkboxes_helper.rb +1 -1
- data/lib/govuk_publishing_components/presenters/shared_helper.rb +0 -11
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +217 -184
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +216 -184
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.mjs +1 -0
- data/node_modules/govuk-frontend/dist/govuk/all.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.scss +6 -0
- data/node_modules/govuk-frontend/dist/govuk/all.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs +164 -0
- data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/common/govuk-frontend-version.mjs +1 -1
- data/node_modules/govuk-frontend/dist/govuk/common/index.mjs +1 -87
- data/node_modules/govuk-frontend/dist/govuk/common/index.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +149 -112
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs +148 -111
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs +5 -8
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +149 -112
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs +148 -111
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs +5 -8
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +174 -140
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs +173 -139
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs +17 -16
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/macro-options.json +4 -4
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +1 -24
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs +0 -23
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/date-input/macro-options.json +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +149 -112
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs +148 -111
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs +6 -8
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +149 -112
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs +148 -111
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs +5 -8
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js +1 -24
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs +0 -23
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/input/macro-options.json +4 -4
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +149 -112
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs +148 -111
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs +6 -8
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/macro-options.json +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +149 -112
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs +148 -111
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs +5 -8
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +1 -24
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs +0 -23
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +1 -24
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +0 -23
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +1 -24
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs +0 -23
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +1 -24
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs +0 -23
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/textarea/macro-options.json +1 -1
- data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss +1 -1
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css +1 -1
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js +1 -1
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/init.mjs +17 -13
- data/node_modules/govuk-frontend/dist/govuk/init.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/settings/_typography-responsive.scss +5 -10
- data/node_modules/govuk-frontend/dist/govuk/settings/_typography-responsive.scss.map +1 -1
- data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +1 -1
- data/node_modules/govuk-frontend/package.json +9 -9
- metadata +4 -6
- data/node_modules/govuk-frontend/dist/govuk/common/normalise-dataset.mjs +0 -18
- data/node_modules/govuk-frontend/dist/govuk/common/normalise-dataset.mjs.map +0 -1
- data/node_modules/govuk-frontend/dist/govuk/common/normalise-string.mjs +0 -31
- data/node_modules/govuk-frontend/dist/govuk/common/normalise-string.mjs.map +0 -1
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"accordion.mjs","sources":["../../../../src/govuk/components/accordion/accordion.mjs"],"sourcesContent":["import { mergeConfigs } from '../../common/index.mjs'\nimport { normaliseDataset } from '../../common/normalise-dataset.mjs'\nimport { ElementError } from '../../errors/index.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\nimport { I18n } from '../../i18n.mjs'\n\n/**\n * Accordion component\n *\n * This allows a collection of sections to be collapsed by default, showing only\n * their headers. Sections can be expanded or collapsed individually by clicking\n * their headers. A \"Show all sections\" button is also added to the top of the\n * accordion, which switches to \"Hide all sections\" when all the sections are\n * expanded.\n *\n * The state of each section is saved to the DOM via the `aria-expanded`\n * attribute, which also provides accessibility.\n *\n * @preserve\n */\nexport class Accordion extends GOVUKFrontendComponent {\n /**\n * @private\n * @type {AccordionConfig}\n */\n config\n\n /** @private */\n i18n\n\n /** @private */\n controlsClass = 'govuk-accordion__controls'\n\n /** @private */\n showAllClass = 'govuk-accordion__show-all'\n\n /** @private */\n showAllTextClass = 'govuk-accordion__show-all-text'\n\n /** @private */\n sectionClass = 'govuk-accordion__section'\n\n /** @private */\n sectionExpandedClass = 'govuk-accordion__section--expanded'\n\n /** @private */\n sectionButtonClass = 'govuk-accordion__section-button'\n\n /** @private */\n sectionHeaderClass = 'govuk-accordion__section-header'\n\n /** @private */\n sectionHeadingClass = 'govuk-accordion__section-heading'\n\n /** @private */\n sectionHeadingDividerClass = 'govuk-accordion__section-heading-divider'\n\n /** @private */\n sectionHeadingTextClass = 'govuk-accordion__section-heading-text'\n\n /** @private */\n sectionHeadingTextFocusClass = 'govuk-accordion__section-heading-text-focus'\n\n /** @private */\n sectionShowHideToggleClass = 'govuk-accordion__section-toggle'\n\n /** @private */\n sectionShowHideToggleFocusClass = 'govuk-accordion__section-toggle-focus'\n\n /** @private */\n sectionShowHideTextClass = 'govuk-accordion__section-toggle-text'\n\n /** @private */\n upChevronIconClass = 'govuk-accordion-nav__chevron'\n\n /** @private */\n downChevronIconClass = 'govuk-accordion-nav__chevron--down'\n\n /** @private */\n sectionSummaryClass = 'govuk-accordion__section-summary'\n\n /** @private */\n sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus'\n\n /** @private */\n sectionContentClass = 'govuk-accordion__section-content'\n\n /** @private */\n $sections\n\n /**\n * @private\n * @type {HTMLButtonElement | null}\n */\n $showAllButton = null\n\n /**\n * @private\n * @type {HTMLElement | null}\n */\n $showAllIcon = null\n\n /**\n * @private\n * @type {HTMLElement | null}\n */\n $showAllText = null\n\n /**\n * @param {Element | null} $root - HTML element to use for accordion\n * @param {AccordionConfig} [config] - Accordion config\n */\n constructor($root, config = {}) {\n super($root)\n\n this.config = mergeConfigs(\n Accordion.defaults,\n config,\n normaliseDataset(Accordion, this.$root.dataset)\n )\n\n this.i18n = new I18n(this.config.i18n)\n\n const $sections = this.$root.querySelectorAll(`.${this.sectionClass}`)\n if (!$sections.length) {\n throw new ElementError({\n component: Accordion,\n identifier: `Sections (\\`<div class=\"${this.sectionClass}\">\\`)`\n })\n }\n\n this.$sections = $sections\n\n this.initControls()\n this.initSectionHeaders()\n\n this.updateShowAllButton(this.areAllSectionsOpen())\n }\n\n /**\n * Initialise controls and set attributes\n *\n * @private\n */\n initControls() {\n // Create \"Show all\" button and set attributes\n this.$showAllButton = document.createElement('button')\n this.$showAllButton.setAttribute('type', 'button')\n this.$showAllButton.setAttribute('class', this.showAllClass)\n this.$showAllButton.setAttribute('aria-expanded', 'false')\n\n // Create icon, add to element\n this.$showAllIcon = document.createElement('span')\n this.$showAllIcon.classList.add(this.upChevronIconClass)\n this.$showAllButton.appendChild(this.$showAllIcon)\n\n // Create control wrapper and add controls to it\n const $accordionControls = document.createElement('div')\n $accordionControls.setAttribute('class', this.controlsClass)\n $accordionControls.appendChild(this.$showAllButton)\n this.$root.insertBefore($accordionControls, this.$root.firstChild)\n\n // Build additional wrapper for Show all toggle text and place after icon\n this.$showAllText = document.createElement('span')\n this.$showAllText.classList.add(this.showAllTextClass)\n this.$showAllButton.appendChild(this.$showAllText)\n\n // Handle click events on the show/hide all button\n this.$showAllButton.addEventListener('click', () =>\n this.onShowOrHideAllToggle()\n )\n\n // Handle 'beforematch' events, if the user agent supports them\n if ('onbeforematch' in document) {\n document.addEventListener('beforematch', (event) =>\n this.onBeforeMatch(event)\n )\n }\n }\n\n /**\n * Initialise section headers\n *\n * @private\n */\n initSectionHeaders() {\n this.$sections.forEach(($section, i) => {\n const $header = $section.querySelector(`.${this.sectionHeaderClass}`)\n if (!$header) {\n throw new ElementError({\n component: Accordion,\n identifier: `Section headers (\\`<div class=\"${this.sectionHeaderClass}\">\\`)`\n })\n }\n\n // Set header attributes\n this.constructHeaderMarkup($header, i)\n this.setExpanded(this.isExpanded($section), $section)\n\n // Handle events\n $header.addEventListener('click', () => this.onSectionToggle($section))\n\n // See if there is any state stored in sessionStorage and set the sections\n // to open or closed.\n this.setInitialState($section)\n })\n }\n\n /**\n * Construct section header\n *\n * @private\n * @param {Element} $header - Section header\n * @param {number} index - Section index\n */\n constructHeaderMarkup($header, index) {\n const $span = $header.querySelector(`.${this.sectionButtonClass}`)\n const $heading = $header.querySelector(`.${this.sectionHeadingClass}`)\n const $summary = $header.querySelector(`.${this.sectionSummaryClass}`)\n\n if (!$heading) {\n throw new ElementError({\n component: Accordion,\n identifier: `Section heading (\\`.${this.sectionHeadingClass}\\`)`\n })\n }\n\n if (!$span) {\n throw new ElementError({\n component: Accordion,\n identifier: `Section button placeholder (\\`<span class=\"${this.sectionButtonClass}\">\\`)`\n })\n }\n\n // Create a button element that will replace the\n // '.govuk-accordion__section-button' span\n const $button = document.createElement('button')\n $button.setAttribute('type', 'button')\n $button.setAttribute(\n 'aria-controls',\n `${this.$root.id}-content-${index + 1}`\n )\n\n // Copy all attributes from $span to $button (except `id`, which gets added\n // to the `$headingText` element)\n for (const attr of Array.from($span.attributes)) {\n if (attr.name !== 'id') {\n $button.setAttribute(attr.name, attr.value)\n }\n }\n\n // Create container for heading text so it can be styled\n const $headingText = document.createElement('span')\n $headingText.classList.add(this.sectionHeadingTextClass)\n // Copy the span ID to the heading text to allow it to be referenced by\n // `aria-labelledby` on the hidden content area without \"Show this section\"\n $headingText.id = $span.id\n\n // Create an inner heading text container to limit the width of the focus\n // state\n const $headingTextFocus = document.createElement('span')\n $headingTextFocus.classList.add(this.sectionHeadingTextFocusClass)\n $headingText.appendChild($headingTextFocus)\n // span could contain HTML elements\n // (see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content)\n Array.from($span.childNodes).forEach(($child) =>\n $headingTextFocus.appendChild($child)\n )\n\n // Create container for show / hide icons and text.\n const $showHideToggle = document.createElement('span')\n $showHideToggle.classList.add(this.sectionShowHideToggleClass)\n // Tell Google not to index the 'show' text as part of the heading. Must be\n // set on the element before it's added to the DOM.\n // See https://developers.google.com/search/docs/advanced/robots/robots_meta_tag#data-nosnippet-attr\n $showHideToggle.setAttribute('data-nosnippet', '')\n // Create an inner container to limit the width of the focus state\n const $showHideToggleFocus = document.createElement('span')\n $showHideToggleFocus.classList.add(this.sectionShowHideToggleFocusClass)\n $showHideToggle.appendChild($showHideToggleFocus)\n // Create wrapper for the show / hide text. Append text after the show/hide icon\n const $showHideText = document.createElement('span')\n const $showHideIcon = document.createElement('span')\n $showHideIcon.classList.add(this.upChevronIconClass)\n $showHideToggleFocus.appendChild($showHideIcon)\n $showHideText.classList.add(this.sectionShowHideTextClass)\n $showHideToggleFocus.appendChild($showHideText)\n\n // Append elements to the button:\n // 1. Heading text\n // 2. Punctuation\n // 3. (Optional: Summary line followed by punctuation)\n // 4. Show / hide toggle\n $button.appendChild($headingText)\n $button.appendChild(this.getButtonPunctuationEl())\n\n // If summary content exists add to DOM in correct order\n if ($summary) {\n // Create a new `span` element and copy the summary line content from the\n // original `div` to the new `span`. This is because the summary line text\n // is now inside a button element, which can only contain phrasing\n // content.\n const $summarySpan = document.createElement('span')\n // Create an inner summary container to limit the width of the summary\n // focus state\n const $summarySpanFocus = document.createElement('span')\n $summarySpanFocus.classList.add(this.sectionSummaryFocusClass)\n $summarySpan.appendChild($summarySpanFocus)\n\n // Get original attributes, and pass them to the replacement\n for (const attr of Array.from($summary.attributes)) {\n $summarySpan.setAttribute(attr.name, attr.value)\n }\n\n // Copy original contents of summary to the new summary span\n Array.from($summary.childNodes).forEach(($child) =>\n $summarySpanFocus.appendChild($child)\n )\n\n // Replace the original summary `div` with the new summary `span`\n $summary.remove()\n\n $button.appendChild($summarySpan)\n $button.appendChild(this.getButtonPunctuationEl())\n }\n\n $button.appendChild($showHideToggle)\n\n $heading.removeChild($span)\n $heading.appendChild($button)\n }\n\n /**\n * When a section is opened by the user agent via the 'beforematch' event\n *\n * @private\n * @param {Event} event - Generic event\n */\n onBeforeMatch(event) {\n const $fragment = event.target\n\n // Handle elements with `.closest()` support only\n if (!($fragment instanceof Element)) {\n return\n }\n\n // Handle when fragment is inside section\n const $section = $fragment.closest(`.${this.sectionClass}`)\n if ($section) {\n this.setExpanded(true, $section)\n }\n }\n\n /**\n * When section toggled, set and store state\n *\n * @private\n * @param {Element} $section - Section element\n */\n onSectionToggle($section) {\n const nowExpanded = !this.isExpanded($section)\n this.setExpanded(nowExpanded, $section)\n\n // Store the state in sessionStorage when a change is triggered\n this.storeState($section, nowExpanded)\n }\n\n /**\n * When Open/Close All toggled, set and store state\n *\n * @private\n */\n onShowOrHideAllToggle() {\n const nowExpanded = !this.areAllSectionsOpen()\n\n this.$sections.forEach(($section) => {\n this.setExpanded(nowExpanded, $section)\n this.storeState($section, nowExpanded)\n })\n\n this.updateShowAllButton(nowExpanded)\n }\n\n /**\n * Set section attributes when opened/closed\n *\n * @private\n * @param {boolean} expanded - Section expanded\n * @param {Element} $section - Section element\n */\n setExpanded(expanded, $section) {\n const $showHideIcon = $section.querySelector(`.${this.upChevronIconClass}`)\n const $showHideText = $section.querySelector(\n `.${this.sectionShowHideTextClass}`\n )\n const $button = $section.querySelector(`.${this.sectionButtonClass}`)\n const $content = $section.querySelector(`.${this.sectionContentClass}`)\n\n if (!$content) {\n throw new ElementError({\n component: Accordion,\n identifier: `Section content (\\`<div class=\"${this.sectionContentClass}\">\\`)`\n })\n }\n\n if (!$showHideIcon || !$showHideText || !$button) {\n // Return early for elements we create\n return\n }\n\n const newButtonText = expanded\n ? this.i18n.t('hideSection')\n : this.i18n.t('showSection')\n\n $showHideText.textContent = newButtonText\n $button.setAttribute('aria-expanded', `${expanded}`)\n\n // Update aria-label combining\n const ariaLabelParts = []\n\n const $headingText = $section.querySelector(\n `.${this.sectionHeadingTextClass}`\n )\n if ($headingText) {\n ariaLabelParts.push(`${$headingText.textContent}`.trim())\n }\n\n const $summary = $section.querySelector(`.${this.sectionSummaryClass}`)\n if ($summary) {\n ariaLabelParts.push(`${$summary.textContent}`.trim())\n }\n\n const ariaLabelMessage = expanded\n ? this.i18n.t('hideSectionAriaLabel')\n : this.i18n.t('showSectionAriaLabel')\n ariaLabelParts.push(ariaLabelMessage)\n\n /*\n * Join with a comma to add pause for assistive technology.\n * Example: [heading]Section A ,[pause] Show this section.\n * https://accessibility.blog.gov.uk/2017/12/18/what-working-on-gov-uk-navigation-taught-us-about-accessibility/\n */\n $button.setAttribute('aria-label', ariaLabelParts.join(' , '))\n\n // Swap icon, change class\n if (expanded) {\n $content.removeAttribute('hidden')\n $section.classList.add(this.sectionExpandedClass)\n $showHideIcon.classList.remove(this.downChevronIconClass)\n } else {\n $content.setAttribute('hidden', 'until-found')\n $section.classList.remove(this.sectionExpandedClass)\n $showHideIcon.classList.add(this.downChevronIconClass)\n }\n\n // See if \"Show all sections\" button text should be updated\n this.updateShowAllButton(this.areAllSectionsOpen())\n }\n\n /**\n * Get state of section\n *\n * @private\n * @param {Element} $section - Section element\n * @returns {boolean} True if expanded\n */\n isExpanded($section) {\n return $section.classList.contains(this.sectionExpandedClass)\n }\n\n /**\n * Check if all sections are open\n *\n * @private\n * @returns {boolean} True if all sections are open\n */\n areAllSectionsOpen() {\n return Array.from(this.$sections).every(($section) =>\n this.isExpanded($section)\n )\n }\n\n /**\n * Update \"Show all sections\" button\n *\n * @private\n * @param {boolean} expanded - Section expanded\n */\n updateShowAllButton(expanded) {\n if (!this.$showAllButton || !this.$showAllText || !this.$showAllIcon) {\n return\n }\n\n this.$showAllButton.setAttribute('aria-expanded', expanded.toString())\n this.$showAllText.textContent = expanded\n ? this.i18n.t('hideAllSections')\n : this.i18n.t('showAllSections')\n this.$showAllIcon.classList.toggle(this.downChevronIconClass, !expanded)\n }\n\n /**\n * Get the identifier for a section\n *\n * We need a unique way of identifying each content in the Accordion.\n * Since an `#id` should be unique and an `id` is required for `aria-`\n * attributes `id` can be safely used.\n *\n * @param {Element} $section - Section element\n * @returns {string | undefined | null} Identifier for section\n */\n getIdentifier($section) {\n const $button = $section.querySelector(`.${this.sectionButtonClass}`)\n\n return $button?.getAttribute('aria-controls')\n }\n\n /**\n * Set the state of the accordions in sessionStorage\n *\n * @private\n * @param {Element} $section - Section element\n * @param {boolean} isExpanded - Whether the section is expanded\n */\n storeState($section, isExpanded) {\n if (!this.config.rememberExpanded) {\n return\n }\n\n const id = this.getIdentifier($section)\n\n if (id) {\n try {\n window.sessionStorage.setItem(id, isExpanded.toString())\n } catch (exception) {}\n }\n }\n\n /**\n * Read the state of the accordions from sessionStorage\n *\n * @private\n * @param {Element} $section - Section element\n */\n setInitialState($section) {\n if (!this.config.rememberExpanded) {\n return\n }\n\n const id = this.getIdentifier($section)\n\n if (id) {\n try {\n const state = window.sessionStorage.getItem(id)\n\n if (state !== null) {\n this.setExpanded(state === 'true', $section)\n }\n } catch (exception) {}\n }\n }\n\n /**\n * Create an element to improve semantics of the section button with\n * punctuation\n *\n * Adding punctuation to the button can also improve its general semantics by\n * dividing its contents into thematic chunks. See\n * https://github.com/alphagov/govuk-frontend/issues/2327#issuecomment-922957442\n *\n * @private\n * @returns {Element} DOM element\n */\n getButtonPunctuationEl() {\n const $punctuationEl = document.createElement('span')\n $punctuationEl.classList.add(\n 'govuk-visually-hidden',\n this.sectionHeadingDividerClass\n )\n $punctuationEl.textContent = ', '\n return $punctuationEl\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-accordion'\n\n /**\n * Accordion default config\n *\n * @see {@link AccordionConfig}\n * @constant\n * @type {AccordionConfig}\n */\n static defaults = Object.freeze({\n i18n: {\n hideAllSections: 'Hide all sections',\n hideSection: 'Hide',\n hideSectionAriaLabel: 'Hide this section',\n showAllSections: 'Show all sections',\n showSection: 'Show',\n showSectionAriaLabel: 'Show this section'\n },\n rememberExpanded: true\n })\n\n /**\n * Accordion config schema\n *\n * @constant\n * @satisfies {Schema}\n */\n static schema = Object.freeze({\n properties: {\n i18n: { type: 'object' },\n rememberExpanded: { type: 'boolean' }\n }\n })\n}\n\n/**\n * Accordion config\n *\n * @see {@link Accordion.defaults}\n * @typedef {object} AccordionConfig\n * @property {AccordionTranslations} [i18n=Accordion.defaults.i18n] - Accordion translations\n * @property {boolean} [rememberExpanded] - Whether the expanded and collapsed\n * state of each section is remembered and restored when navigating.\n */\n\n/**\n * Accordion translations\n *\n * @see {@link Accordion.defaults.i18n}\n * @typedef {object} AccordionTranslations\n *\n * Messages used by the component for the labels of its buttons. This includes\n * the visible text shown on screen, and text to help assistive technology users\n * for the buttons toggling each section.\n * @property {string} [hideAllSections] - The text content for the 'Hide all\n * sections' button, used when at least one section is expanded.\n * @property {string} [hideSection] - The text content for the 'Hide'\n * button, used when a section is expanded.\n * @property {string} [hideSectionAriaLabel] - The text content appended to the\n * 'Hide' button's accessible name when a section is expanded.\n * @property {string} [showAllSections] - The text content for the 'Show all\n * sections' button, used when all sections are collapsed.\n * @property {string} [showSection] - The text content for the 'Show'\n * button, used when a section is collapsed.\n * @property {string} [showSectionAriaLabel] - The text content appended to the\n * 'Show' button's accessible name when a section is expanded.\n */\n\n/**\n * @typedef {import('../../common/index.mjs').Schema} Schema\n */\n"],"names":["Accordion","GOVUKFrontendComponent","constructor","$root","config","i18n","controlsClass","showAllClass","showAllTextClass","sectionClass","sectionExpandedClass","sectionButtonClass","sectionHeaderClass","sectionHeadingClass","sectionHeadingDividerClass","sectionHeadingTextClass","sectionHeadingTextFocusClass","sectionShowHideToggleClass","sectionShowHideToggleFocusClass","sectionShowHideTextClass","upChevronIconClass","downChevronIconClass","sectionSummaryClass","sectionSummaryFocusClass","sectionContentClass","$sections","$showAllButton","$showAllIcon","$showAllText","mergeConfigs","defaults","normaliseDataset","dataset","I18n","querySelectorAll","length","ElementError","component","identifier","initControls","initSectionHeaders","updateShowAllButton","areAllSectionsOpen","document","createElement","setAttribute","classList","add","appendChild","$accordionControls","insertBefore","firstChild","addEventListener","onShowOrHideAllToggle","event","onBeforeMatch","forEach","$section","i","$header","querySelector","constructHeaderMarkup","setExpanded","isExpanded","onSectionToggle","setInitialState","index","$span","$heading","$summary","$button","id","attr","Array","from","attributes","name","value","$headingText","$headingTextFocus","childNodes","$child","$showHideToggle","$showHideToggleFocus","$showHideText","$showHideIcon","getButtonPunctuationEl","$summarySpan","$summarySpanFocus","remove","removeChild","$fragment","target","Element","closest","nowExpanded","storeState","expanded","$content","newButtonText","t","textContent","ariaLabelParts","push","trim","ariaLabelMessage","join","removeAttribute","contains","every","toString","toggle","getIdentifier","getAttribute","rememberExpanded","window","sessionStorage","setItem","exception","state","getItem","$punctuationEl","moduleName","Object","freeze","hideAllSections","hideSection","hideSectionAriaLabel","showAllSections","showSection","showSectionAriaLabel","schema","properties","type"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"accordion.mjs","sources":["../../../../src/govuk/components/accordion/accordion.mjs"],"sourcesContent":["import { ConfigurableComponent } from '../../common/configuration.mjs'\nimport { ElementError } from '../../errors/index.mjs'\nimport { I18n } from '../../i18n.mjs'\n\n/**\n * Accordion component\n *\n * This allows a collection of sections to be collapsed by default, showing only\n * their headers. Sections can be expanded or collapsed individually by clicking\n * their headers. A \"Show all sections\" button is also added to the top of the\n * accordion, which switches to \"Hide all sections\" when all the sections are\n * expanded.\n *\n * The state of each section is saved to the DOM via the `aria-expanded`\n * attribute, which also provides accessibility.\n *\n * @preserve\n * @augments ConfigurableComponent<AccordionConfig>\n */\nexport class Accordion extends ConfigurableComponent {\n /** @private */\n i18n\n\n /** @private */\n controlsClass = 'govuk-accordion__controls'\n\n /** @private */\n showAllClass = 'govuk-accordion__show-all'\n\n /** @private */\n showAllTextClass = 'govuk-accordion__show-all-text'\n\n /** @private */\n sectionClass = 'govuk-accordion__section'\n\n /** @private */\n sectionExpandedClass = 'govuk-accordion__section--expanded'\n\n /** @private */\n sectionButtonClass = 'govuk-accordion__section-button'\n\n /** @private */\n sectionHeaderClass = 'govuk-accordion__section-header'\n\n /** @private */\n sectionHeadingClass = 'govuk-accordion__section-heading'\n\n /** @private */\n sectionHeadingDividerClass = 'govuk-accordion__section-heading-divider'\n\n /** @private */\n sectionHeadingTextClass = 'govuk-accordion__section-heading-text'\n\n /** @private */\n sectionHeadingTextFocusClass = 'govuk-accordion__section-heading-text-focus'\n\n /** @private */\n sectionShowHideToggleClass = 'govuk-accordion__section-toggle'\n\n /** @private */\n sectionShowHideToggleFocusClass = 'govuk-accordion__section-toggle-focus'\n\n /** @private */\n sectionShowHideTextClass = 'govuk-accordion__section-toggle-text'\n\n /** @private */\n upChevronIconClass = 'govuk-accordion-nav__chevron'\n\n /** @private */\n downChevronIconClass = 'govuk-accordion-nav__chevron--down'\n\n /** @private */\n sectionSummaryClass = 'govuk-accordion__section-summary'\n\n /** @private */\n sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus'\n\n /** @private */\n sectionContentClass = 'govuk-accordion__section-content'\n\n /** @private */\n $sections\n\n /**\n * @private\n * @type {HTMLButtonElement | null}\n */\n $showAllButton = null\n\n /**\n * @private\n * @type {HTMLElement | null}\n */\n $showAllIcon = null\n\n /**\n * @private\n * @type {HTMLElement | null}\n */\n $showAllText = null\n\n /**\n * @param {Element | null} $root - HTML element to use for accordion\n * @param {AccordionConfig} [config] - Accordion config\n */\n constructor($root, config = {}) {\n super($root, config)\n\n this.i18n = new I18n(this.config.i18n)\n\n const $sections = this.$root.querySelectorAll(`.${this.sectionClass}`)\n if (!$sections.length) {\n throw new ElementError({\n component: Accordion,\n identifier: `Sections (\\`<div class=\"${this.sectionClass}\">\\`)`\n })\n }\n\n this.$sections = $sections\n\n this.initControls()\n this.initSectionHeaders()\n\n this.updateShowAllButton(this.areAllSectionsOpen())\n }\n\n /**\n * Initialise controls and set attributes\n *\n * @private\n */\n initControls() {\n // Create \"Show all\" button and set attributes\n this.$showAllButton = document.createElement('button')\n this.$showAllButton.setAttribute('type', 'button')\n this.$showAllButton.setAttribute('class', this.showAllClass)\n this.$showAllButton.setAttribute('aria-expanded', 'false')\n\n // Create icon, add to element\n this.$showAllIcon = document.createElement('span')\n this.$showAllIcon.classList.add(this.upChevronIconClass)\n this.$showAllButton.appendChild(this.$showAllIcon)\n\n // Create control wrapper and add controls to it\n const $accordionControls = document.createElement('div')\n $accordionControls.setAttribute('class', this.controlsClass)\n $accordionControls.appendChild(this.$showAllButton)\n this.$root.insertBefore($accordionControls, this.$root.firstChild)\n\n // Build additional wrapper for Show all toggle text and place after icon\n this.$showAllText = document.createElement('span')\n this.$showAllText.classList.add(this.showAllTextClass)\n this.$showAllButton.appendChild(this.$showAllText)\n\n // Handle click events on the show/hide all button\n this.$showAllButton.addEventListener('click', () =>\n this.onShowOrHideAllToggle()\n )\n\n // Handle 'beforematch' events, if the user agent supports them\n if ('onbeforematch' in document) {\n document.addEventListener('beforematch', (event) =>\n this.onBeforeMatch(event)\n )\n }\n }\n\n /**\n * Initialise section headers\n *\n * @private\n */\n initSectionHeaders() {\n this.$sections.forEach(($section, i) => {\n const $header = $section.querySelector(`.${this.sectionHeaderClass}`)\n if (!$header) {\n throw new ElementError({\n component: Accordion,\n identifier: `Section headers (\\`<div class=\"${this.sectionHeaderClass}\">\\`)`\n })\n }\n\n // Set header attributes\n this.constructHeaderMarkup($header, i)\n this.setExpanded(this.isExpanded($section), $section)\n\n // Handle events\n $header.addEventListener('click', () => this.onSectionToggle($section))\n\n // See if there is any state stored in sessionStorage and set the sections\n // to open or closed.\n this.setInitialState($section)\n })\n }\n\n /**\n * Construct section header\n *\n * @private\n * @param {Element} $header - Section header\n * @param {number} index - Section index\n */\n constructHeaderMarkup($header, index) {\n const $span = $header.querySelector(`.${this.sectionButtonClass}`)\n const $heading = $header.querySelector(`.${this.sectionHeadingClass}`)\n const $summary = $header.querySelector(`.${this.sectionSummaryClass}`)\n\n if (!$heading) {\n throw new ElementError({\n component: Accordion,\n identifier: `Section heading (\\`.${this.sectionHeadingClass}\\`)`\n })\n }\n\n if (!$span) {\n throw new ElementError({\n component: Accordion,\n identifier: `Section button placeholder (\\`<span class=\"${this.sectionButtonClass}\">\\`)`\n })\n }\n\n // Create a button element that will replace the\n // '.govuk-accordion__section-button' span\n const $button = document.createElement('button')\n $button.setAttribute('type', 'button')\n $button.setAttribute(\n 'aria-controls',\n `${this.$root.id}-content-${index + 1}`\n )\n\n // Copy all attributes from $span to $button (except `id`, which gets added\n // to the `$headingText` element)\n for (const attr of Array.from($span.attributes)) {\n if (attr.name !== 'id') {\n $button.setAttribute(attr.name, attr.value)\n }\n }\n\n // Create container for heading text so it can be styled\n const $headingText = document.createElement('span')\n $headingText.classList.add(this.sectionHeadingTextClass)\n // Copy the span ID to the heading text to allow it to be referenced by\n // `aria-labelledby` on the hidden content area without \"Show this section\"\n $headingText.id = $span.id\n\n // Create an inner heading text container to limit the width of the focus\n // state\n const $headingTextFocus = document.createElement('span')\n $headingTextFocus.classList.add(this.sectionHeadingTextFocusClass)\n $headingText.appendChild($headingTextFocus)\n // span could contain HTML elements\n // (see https://www.w3.org/TR/2011/WD-html5-20110525/content-models.html#phrasing-content)\n Array.from($span.childNodes).forEach(($child) =>\n $headingTextFocus.appendChild($child)\n )\n\n // Create container for show / hide icons and text.\n const $showHideToggle = document.createElement('span')\n $showHideToggle.classList.add(this.sectionShowHideToggleClass)\n // Tell Google not to index the 'show' text as part of the heading. Must be\n // set on the element before it's added to the DOM.\n // See https://developers.google.com/search/docs/advanced/robots/robots_meta_tag#data-nosnippet-attr\n $showHideToggle.setAttribute('data-nosnippet', '')\n // Create an inner container to limit the width of the focus state\n const $showHideToggleFocus = document.createElement('span')\n $showHideToggleFocus.classList.add(this.sectionShowHideToggleFocusClass)\n $showHideToggle.appendChild($showHideToggleFocus)\n // Create wrapper for the show / hide text. Append text after the show/hide icon\n const $showHideText = document.createElement('span')\n const $showHideIcon = document.createElement('span')\n $showHideIcon.classList.add(this.upChevronIconClass)\n $showHideToggleFocus.appendChild($showHideIcon)\n $showHideText.classList.add(this.sectionShowHideTextClass)\n $showHideToggleFocus.appendChild($showHideText)\n\n // Append elements to the button:\n // 1. Heading text\n // 2. Punctuation\n // 3. (Optional: Summary line followed by punctuation)\n // 4. Show / hide toggle\n $button.appendChild($headingText)\n $button.appendChild(this.getButtonPunctuationEl())\n\n // If summary content exists add to DOM in correct order\n if ($summary) {\n // Create a new `span` element and copy the summary line content from the\n // original `div` to the new `span`. This is because the summary line text\n // is now inside a button element, which can only contain phrasing\n // content.\n const $summarySpan = document.createElement('span')\n // Create an inner summary container to limit the width of the summary\n // focus state\n const $summarySpanFocus = document.createElement('span')\n $summarySpanFocus.classList.add(this.sectionSummaryFocusClass)\n $summarySpan.appendChild($summarySpanFocus)\n\n // Get original attributes, and pass them to the replacement\n for (const attr of Array.from($summary.attributes)) {\n $summarySpan.setAttribute(attr.name, attr.value)\n }\n\n // Copy original contents of summary to the new summary span\n Array.from($summary.childNodes).forEach(($child) =>\n $summarySpanFocus.appendChild($child)\n )\n\n // Replace the original summary `div` with the new summary `span`\n $summary.remove()\n\n $button.appendChild($summarySpan)\n $button.appendChild(this.getButtonPunctuationEl())\n }\n\n $button.appendChild($showHideToggle)\n\n $heading.removeChild($span)\n $heading.appendChild($button)\n }\n\n /**\n * When a section is opened by the user agent via the 'beforematch' event\n *\n * @private\n * @param {Event} event - Generic event\n */\n onBeforeMatch(event) {\n const $fragment = event.target\n\n // Handle elements with `.closest()` support only\n if (!($fragment instanceof Element)) {\n return\n }\n\n // Handle when fragment is inside section\n const $section = $fragment.closest(`.${this.sectionClass}`)\n if ($section) {\n this.setExpanded(true, $section)\n }\n }\n\n /**\n * When section toggled, set and store state\n *\n * @private\n * @param {Element} $section - Section element\n */\n onSectionToggle($section) {\n const nowExpanded = !this.isExpanded($section)\n this.setExpanded(nowExpanded, $section)\n\n // Store the state in sessionStorage when a change is triggered\n this.storeState($section, nowExpanded)\n }\n\n /**\n * When Open/Close All toggled, set and store state\n *\n * @private\n */\n onShowOrHideAllToggle() {\n const nowExpanded = !this.areAllSectionsOpen()\n\n this.$sections.forEach(($section) => {\n this.setExpanded(nowExpanded, $section)\n this.storeState($section, nowExpanded)\n })\n\n this.updateShowAllButton(nowExpanded)\n }\n\n /**\n * Set section attributes when opened/closed\n *\n * @private\n * @param {boolean} expanded - Section expanded\n * @param {Element} $section - Section element\n */\n setExpanded(expanded, $section) {\n const $showHideIcon = $section.querySelector(`.${this.upChevronIconClass}`)\n const $showHideText = $section.querySelector(\n `.${this.sectionShowHideTextClass}`\n )\n const $button = $section.querySelector(`.${this.sectionButtonClass}`)\n const $content = $section.querySelector(`.${this.sectionContentClass}`)\n\n if (!$content) {\n throw new ElementError({\n component: Accordion,\n identifier: `Section content (\\`<div class=\"${this.sectionContentClass}\">\\`)`\n })\n }\n\n if (!$showHideIcon || !$showHideText || !$button) {\n // Return early for elements we create\n return\n }\n\n const newButtonText = expanded\n ? this.i18n.t('hideSection')\n : this.i18n.t('showSection')\n\n $showHideText.textContent = newButtonText\n $button.setAttribute('aria-expanded', `${expanded}`)\n\n // Update aria-label combining\n const ariaLabelParts = []\n\n const $headingText = $section.querySelector(\n `.${this.sectionHeadingTextClass}`\n )\n if ($headingText) {\n ariaLabelParts.push(`${$headingText.textContent}`.trim())\n }\n\n const $summary = $section.querySelector(`.${this.sectionSummaryClass}`)\n if ($summary) {\n ariaLabelParts.push(`${$summary.textContent}`.trim())\n }\n\n const ariaLabelMessage = expanded\n ? this.i18n.t('hideSectionAriaLabel')\n : this.i18n.t('showSectionAriaLabel')\n ariaLabelParts.push(ariaLabelMessage)\n\n /*\n * Join with a comma to add pause for assistive technology.\n * Example: [heading]Section A ,[pause] Show this section.\n * https://accessibility.blog.gov.uk/2017/12/18/what-working-on-gov-uk-navigation-taught-us-about-accessibility/\n */\n $button.setAttribute('aria-label', ariaLabelParts.join(' , '))\n\n // Swap icon, change class\n if (expanded) {\n $content.removeAttribute('hidden')\n $section.classList.add(this.sectionExpandedClass)\n $showHideIcon.classList.remove(this.downChevronIconClass)\n } else {\n $content.setAttribute('hidden', 'until-found')\n $section.classList.remove(this.sectionExpandedClass)\n $showHideIcon.classList.add(this.downChevronIconClass)\n }\n\n // See if \"Show all sections\" button text should be updated\n this.updateShowAllButton(this.areAllSectionsOpen())\n }\n\n /**\n * Get state of section\n *\n * @private\n * @param {Element} $section - Section element\n * @returns {boolean} True if expanded\n */\n isExpanded($section) {\n return $section.classList.contains(this.sectionExpandedClass)\n }\n\n /**\n * Check if all sections are open\n *\n * @private\n * @returns {boolean} True if all sections are open\n */\n areAllSectionsOpen() {\n return Array.from(this.$sections).every(($section) =>\n this.isExpanded($section)\n )\n }\n\n /**\n * Update \"Show all sections\" button\n *\n * @private\n * @param {boolean} expanded - Section expanded\n */\n updateShowAllButton(expanded) {\n if (!this.$showAllButton || !this.$showAllText || !this.$showAllIcon) {\n return\n }\n\n this.$showAllButton.setAttribute('aria-expanded', expanded.toString())\n this.$showAllText.textContent = expanded\n ? this.i18n.t('hideAllSections')\n : this.i18n.t('showAllSections')\n this.$showAllIcon.classList.toggle(this.downChevronIconClass, !expanded)\n }\n\n /**\n * Get the identifier for a section\n *\n * We need a unique way of identifying each content in the Accordion.\n * Since an `#id` should be unique and an `id` is required for `aria-`\n * attributes `id` can be safely used.\n *\n * @param {Element} $section - Section element\n * @returns {string | undefined | null} Identifier for section\n */\n getIdentifier($section) {\n const $button = $section.querySelector(`.${this.sectionButtonClass}`)\n\n return $button?.getAttribute('aria-controls')\n }\n\n /**\n * Set the state of the accordions in sessionStorage\n *\n * @private\n * @param {Element} $section - Section element\n * @param {boolean} isExpanded - Whether the section is expanded\n */\n storeState($section, isExpanded) {\n if (!this.config.rememberExpanded) {\n return\n }\n\n const id = this.getIdentifier($section)\n\n if (id) {\n try {\n window.sessionStorage.setItem(id, isExpanded.toString())\n } catch (exception) {}\n }\n }\n\n /**\n * Read the state of the accordions from sessionStorage\n *\n * @private\n * @param {Element} $section - Section element\n */\n setInitialState($section) {\n if (!this.config.rememberExpanded) {\n return\n }\n\n const id = this.getIdentifier($section)\n\n if (id) {\n try {\n const state = window.sessionStorage.getItem(id)\n\n if (state !== null) {\n this.setExpanded(state === 'true', $section)\n }\n } catch (exception) {}\n }\n }\n\n /**\n * Create an element to improve semantics of the section button with\n * punctuation\n *\n * Adding punctuation to the button can also improve its general semantics by\n * dividing its contents into thematic chunks. See\n * https://github.com/alphagov/govuk-frontend/issues/2327#issuecomment-922957442\n *\n * @private\n * @returns {Element} DOM element\n */\n getButtonPunctuationEl() {\n const $punctuationEl = document.createElement('span')\n $punctuationEl.classList.add(\n 'govuk-visually-hidden',\n this.sectionHeadingDividerClass\n )\n $punctuationEl.textContent = ', '\n return $punctuationEl\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-accordion'\n\n /**\n * Accordion default config\n *\n * @see {@link AccordionConfig}\n * @constant\n * @type {AccordionConfig}\n */\n static defaults = Object.freeze({\n i18n: {\n hideAllSections: 'Hide all sections',\n hideSection: 'Hide',\n hideSectionAriaLabel: 'Hide this section',\n showAllSections: 'Show all sections',\n showSection: 'Show',\n showSectionAriaLabel: 'Show this section'\n },\n rememberExpanded: true\n })\n\n /**\n * Accordion config schema\n *\n * @constant\n * @satisfies {Schema}\n */\n static schema = Object.freeze({\n properties: {\n i18n: { type: 'object' },\n rememberExpanded: { type: 'boolean' }\n }\n })\n}\n\n/**\n * Accordion config\n *\n * @see {@link Accordion.defaults}\n * @typedef {object} AccordionConfig\n * @property {AccordionTranslations} [i18n=Accordion.defaults.i18n] - Accordion translations\n * @property {boolean} [rememberExpanded] - Whether the expanded and collapsed\n * state of each section is remembered and restored when navigating.\n */\n\n/**\n * Accordion translations\n *\n * @see {@link Accordion.defaults.i18n}\n * @typedef {object} AccordionTranslations\n *\n * Messages used by the component for the labels of its buttons. This includes\n * the visible text shown on screen, and text to help assistive technology users\n * for the buttons toggling each section.\n * @property {string} [hideAllSections] - The text content for the 'Hide all\n * sections' button, used when at least one section is expanded.\n * @property {string} [hideSection] - The text content for the 'Hide'\n * button, used when a section is expanded.\n * @property {string} [hideSectionAriaLabel] - The text content appended to the\n * 'Hide' button's accessible name when a section is expanded.\n * @property {string} [showAllSections] - The text content for the 'Show all\n * sections' button, used when all sections are collapsed.\n * @property {string} [showSection] - The text content for the 'Show'\n * button, used when a section is collapsed.\n * @property {string} [showSectionAriaLabel] - The text content appended to the\n * 'Show' button's accessible name when a section is expanded.\n */\n\n/**\n * @typedef {import('../../common/configuration.mjs').Schema} Schema\n */\n"],"names":["Accordion","ConfigurableComponent","constructor","$root","config","i18n","controlsClass","showAllClass","showAllTextClass","sectionClass","sectionExpandedClass","sectionButtonClass","sectionHeaderClass","sectionHeadingClass","sectionHeadingDividerClass","sectionHeadingTextClass","sectionHeadingTextFocusClass","sectionShowHideToggleClass","sectionShowHideToggleFocusClass","sectionShowHideTextClass","upChevronIconClass","downChevronIconClass","sectionSummaryClass","sectionSummaryFocusClass","sectionContentClass","$sections","$showAllButton","$showAllIcon","$showAllText","I18n","querySelectorAll","length","ElementError","component","identifier","initControls","initSectionHeaders","updateShowAllButton","areAllSectionsOpen","document","createElement","setAttribute","classList","add","appendChild","$accordionControls","insertBefore","firstChild","addEventListener","onShowOrHideAllToggle","event","onBeforeMatch","forEach","$section","i","$header","querySelector","constructHeaderMarkup","setExpanded","isExpanded","onSectionToggle","setInitialState","index","$span","$heading","$summary","$button","id","attr","Array","from","attributes","name","value","$headingText","$headingTextFocus","childNodes","$child","$showHideToggle","$showHideToggleFocus","$showHideText","$showHideIcon","getButtonPunctuationEl","$summarySpan","$summarySpanFocus","remove","removeChild","$fragment","target","Element","closest","nowExpanded","storeState","expanded","$content","newButtonText","t","textContent","ariaLabelParts","push","trim","ariaLabelMessage","join","removeAttribute","contains","every","toString","toggle","getIdentifier","getAttribute","rememberExpanded","window","sessionStorage","setItem","exception","state","getItem","$punctuationEl","moduleName","defaults","Object","freeze","hideAllSections","hideSection","hideSectionAriaLabel","showAllSections","showSection","showSectionAriaLabel","schema","properties","type"],"mappings":"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"}
|
@@ -1,79 +1,9 @@
|
|
1
1
|
(function (global, factory) {
|
2
2
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
3
3
|
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.GOVUKFrontend = {}));
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.GOVUKFrontend = global.GOVUKFrontend || {}));
|
5
5
|
})(this, (function (exports) { 'use strict';
|
6
6
|
|
7
|
-
function normaliseString(value, property) {
|
8
|
-
const trimmedValue = value ? value.trim() : '';
|
9
|
-
let output;
|
10
|
-
let outputType = property == null ? void 0 : property.type;
|
11
|
-
if (!outputType) {
|
12
|
-
if (['true', 'false'].includes(trimmedValue)) {
|
13
|
-
outputType = 'boolean';
|
14
|
-
}
|
15
|
-
if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
|
16
|
-
outputType = 'number';
|
17
|
-
}
|
18
|
-
}
|
19
|
-
switch (outputType) {
|
20
|
-
case 'boolean':
|
21
|
-
output = trimmedValue === 'true';
|
22
|
-
break;
|
23
|
-
case 'number':
|
24
|
-
output = Number(trimmedValue);
|
25
|
-
break;
|
26
|
-
default:
|
27
|
-
output = value;
|
28
|
-
}
|
29
|
-
return output;
|
30
|
-
}
|
31
|
-
|
32
|
-
/**
|
33
|
-
* @typedef {import('./index.mjs').SchemaProperty} SchemaProperty
|
34
|
-
*/
|
35
|
-
|
36
|
-
function mergeConfigs(...configObjects) {
|
37
|
-
const formattedConfigObject = {};
|
38
|
-
for (const configObject of configObjects) {
|
39
|
-
for (const key of Object.keys(configObject)) {
|
40
|
-
const option = formattedConfigObject[key];
|
41
|
-
const override = configObject[key];
|
42
|
-
if (isObject(option) && isObject(override)) {
|
43
|
-
formattedConfigObject[key] = mergeConfigs(option, override);
|
44
|
-
} else {
|
45
|
-
formattedConfigObject[key] = override;
|
46
|
-
}
|
47
|
-
}
|
48
|
-
}
|
49
|
-
return formattedConfigObject;
|
50
|
-
}
|
51
|
-
function extractConfigByNamespace(Component, dataset, namespace) {
|
52
|
-
const property = Component.schema.properties[namespace];
|
53
|
-
if ((property == null ? void 0 : property.type) !== 'object') {
|
54
|
-
return;
|
55
|
-
}
|
56
|
-
const newObject = {
|
57
|
-
[namespace]: ({})
|
58
|
-
};
|
59
|
-
for (const [key, value] of Object.entries(dataset)) {
|
60
|
-
let current = newObject;
|
61
|
-
const keyParts = key.split('.');
|
62
|
-
for (const [index, name] of keyParts.entries()) {
|
63
|
-
if (typeof current === 'object') {
|
64
|
-
if (index < keyParts.length - 1) {
|
65
|
-
if (!isObject(current[name])) {
|
66
|
-
current[name] = {};
|
67
|
-
}
|
68
|
-
current = current[name];
|
69
|
-
} else if (key !== namespace) {
|
70
|
-
current[name] = normaliseString(value);
|
71
|
-
}
|
72
|
-
}
|
73
|
-
}
|
74
|
-
}
|
75
|
-
return newObject[namespace];
|
76
|
-
}
|
77
7
|
function isInitialised($root, moduleName) {
|
78
8
|
return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);
|
79
9
|
}
|
@@ -102,47 +32,11 @@
|
|
102
32
|
function formatErrorMessage(Component, message) {
|
103
33
|
return `${Component.moduleName}: ${message}`;
|
104
34
|
}
|
105
|
-
|
106
|
-
/**
|
107
|
-
* Schema for component config
|
108
|
-
*
|
109
|
-
* @typedef {object} Schema
|
110
|
-
* @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
|
111
|
-
* @property {SchemaCondition[]} [anyOf] - List of schema conditions
|
112
|
-
*/
|
113
|
-
|
114
|
-
/**
|
115
|
-
* Schema property for component config
|
116
|
-
*
|
117
|
-
* @typedef {object} SchemaProperty
|
118
|
-
* @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
|
119
|
-
*/
|
120
|
-
|
121
|
-
/**
|
122
|
-
* Schema condition for component config
|
123
|
-
*
|
124
|
-
* @typedef {object} SchemaCondition
|
125
|
-
* @property {string[]} required - List of required config fields
|
126
|
-
* @property {string} errorMessage - Error message when required config fields not provided
|
127
|
-
*/
|
128
35
|
/**
|
129
36
|
* @typedef ComponentWithModuleName
|
130
37
|
* @property {string} moduleName - Name of the component
|
131
38
|
*/
|
132
39
|
|
133
|
-
function normaliseDataset(Component, dataset) {
|
134
|
-
const out = {};
|
135
|
-
for (const [field, property] of Object.entries(Component.schema.properties)) {
|
136
|
-
if (field in dataset) {
|
137
|
-
out[field] = normaliseString(dataset[field], property);
|
138
|
-
}
|
139
|
-
if ((property == null ? void 0 : property.type) === 'object') {
|
140
|
-
out[field] = extractConfigByNamespace(Component, dataset, field);
|
141
|
-
}
|
142
|
-
}
|
143
|
-
return out;
|
144
|
-
}
|
145
|
-
|
146
40
|
class GOVUKFrontendError extends Error {
|
147
41
|
constructor(...args) {
|
148
42
|
super(...args);
|
@@ -161,6 +55,12 @@
|
|
161
55
|
this.name = 'SupportError';
|
162
56
|
}
|
163
57
|
}
|
58
|
+
class ConfigError extends GOVUKFrontendError {
|
59
|
+
constructor(...args) {
|
60
|
+
super(...args);
|
61
|
+
this.name = 'ConfigError';
|
62
|
+
}
|
63
|
+
}
|
164
64
|
class ElementError extends GOVUKFrontendError {
|
165
65
|
constructor(messageOrOptions) {
|
166
66
|
let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
|
@@ -245,23 +145,160 @@
|
|
245
145
|
*/
|
246
146
|
GOVUKFrontendComponent.elementType = HTMLElement;
|
247
147
|
|
148
|
+
const configOverride = Symbol.for('configOverride');
|
149
|
+
class ConfigurableComponent extends GOVUKFrontendComponent {
|
150
|
+
[configOverride](param) {
|
151
|
+
return {};
|
152
|
+
}
|
153
|
+
|
154
|
+
/**
|
155
|
+
* Returns the root element of the component
|
156
|
+
*
|
157
|
+
* @protected
|
158
|
+
* @returns {ConfigurationType} - the root element of component
|
159
|
+
*/
|
160
|
+
get config() {
|
161
|
+
return this._config;
|
162
|
+
}
|
163
|
+
constructor($root, config) {
|
164
|
+
super($root);
|
165
|
+
this._config = void 0;
|
166
|
+
const childConstructor = this.constructor;
|
167
|
+
if (typeof childConstructor.defaults === 'undefined') {
|
168
|
+
throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
|
169
|
+
}
|
170
|
+
const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
|
171
|
+
this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);
|
172
|
+
}
|
173
|
+
}
|
174
|
+
function normaliseString(value, property) {
|
175
|
+
const trimmedValue = value ? value.trim() : '';
|
176
|
+
let output;
|
177
|
+
let outputType = property == null ? void 0 : property.type;
|
178
|
+
if (!outputType) {
|
179
|
+
if (['true', 'false'].includes(trimmedValue)) {
|
180
|
+
outputType = 'boolean';
|
181
|
+
}
|
182
|
+
if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
|
183
|
+
outputType = 'number';
|
184
|
+
}
|
185
|
+
}
|
186
|
+
switch (outputType) {
|
187
|
+
case 'boolean':
|
188
|
+
output = trimmedValue === 'true';
|
189
|
+
break;
|
190
|
+
case 'number':
|
191
|
+
output = Number(trimmedValue);
|
192
|
+
break;
|
193
|
+
default:
|
194
|
+
output = value;
|
195
|
+
}
|
196
|
+
return output;
|
197
|
+
}
|
198
|
+
function normaliseDataset(Component, dataset) {
|
199
|
+
if (typeof Component.schema === 'undefined') {
|
200
|
+
throw new ConfigError(formatErrorMessage(Component, 'Config passed as parameter into constructor but no schema defined'));
|
201
|
+
}
|
202
|
+
const out = {};
|
203
|
+
for (const [field, property] of Object.entries(Component.schema.properties)) {
|
204
|
+
if (field in dataset) {
|
205
|
+
out[field] = normaliseString(dataset[field], property);
|
206
|
+
}
|
207
|
+
if ((property == null ? void 0 : property.type) === 'object') {
|
208
|
+
out[field] = extractConfigByNamespace(Component.schema, dataset, field);
|
209
|
+
}
|
210
|
+
}
|
211
|
+
return out;
|
212
|
+
}
|
213
|
+
function mergeConfigs(...configObjects) {
|
214
|
+
const formattedConfigObject = {};
|
215
|
+
for (const configObject of configObjects) {
|
216
|
+
for (const key of Object.keys(configObject)) {
|
217
|
+
const option = formattedConfigObject[key];
|
218
|
+
const override = configObject[key];
|
219
|
+
if (isObject(option) && isObject(override)) {
|
220
|
+
formattedConfigObject[key] = mergeConfigs(option, override);
|
221
|
+
} else {
|
222
|
+
formattedConfigObject[key] = override;
|
223
|
+
}
|
224
|
+
}
|
225
|
+
}
|
226
|
+
return formattedConfigObject;
|
227
|
+
}
|
228
|
+
function extractConfigByNamespace(schema, dataset, namespace) {
|
229
|
+
const property = schema.properties[namespace];
|
230
|
+
if ((property == null ? void 0 : property.type) !== 'object') {
|
231
|
+
return;
|
232
|
+
}
|
233
|
+
const newObject = {
|
234
|
+
[namespace]: ({})
|
235
|
+
};
|
236
|
+
for (const [key, value] of Object.entries(dataset)) {
|
237
|
+
let current = newObject;
|
238
|
+
const keyParts = key.split('.');
|
239
|
+
for (const [index, name] of keyParts.entries()) {
|
240
|
+
if (typeof current === 'object') {
|
241
|
+
if (index < keyParts.length - 1) {
|
242
|
+
if (!isObject(current[name])) {
|
243
|
+
current[name] = {};
|
244
|
+
}
|
245
|
+
current = current[name];
|
246
|
+
} else if (key !== namespace) {
|
247
|
+
current[name] = normaliseString(value);
|
248
|
+
}
|
249
|
+
}
|
250
|
+
}
|
251
|
+
}
|
252
|
+
return newObject[namespace];
|
253
|
+
}
|
254
|
+
/**
|
255
|
+
* Schema for component config
|
256
|
+
*
|
257
|
+
* @typedef {object} Schema
|
258
|
+
* @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
|
259
|
+
* @property {SchemaCondition[]} [anyOf] - List of schema conditions
|
260
|
+
*/
|
261
|
+
/**
|
262
|
+
* Schema property for component config
|
263
|
+
*
|
264
|
+
* @typedef {object} SchemaProperty
|
265
|
+
* @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
|
266
|
+
*/
|
267
|
+
/**
|
268
|
+
* Schema condition for component config
|
269
|
+
*
|
270
|
+
* @typedef {object} SchemaCondition
|
271
|
+
* @property {string[]} required - List of required config fields
|
272
|
+
* @property {string} errorMessage - Error message when required config fields not provided
|
273
|
+
*/
|
274
|
+
/**
|
275
|
+
* @template {ObjectNested} [ConfigurationType={}]
|
276
|
+
* @typedef ChildClass
|
277
|
+
* @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
|
278
|
+
* @property {Schema} [schema] - The schema of the component configuration
|
279
|
+
* @property {ConfigurationType} [defaults] - The default values of the configuration of the component
|
280
|
+
*/
|
281
|
+
/**
|
282
|
+
* @template {ObjectNested} [ConfigurationType={}]
|
283
|
+
* @typedef {typeof GOVUKFrontendComponent & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>
|
284
|
+
*/
|
285
|
+
|
248
286
|
const DEBOUNCE_TIMEOUT_IN_SECONDS = 1;
|
249
287
|
|
250
288
|
/**
|
251
289
|
* JavaScript enhancements for the Button component
|
252
290
|
*
|
253
291
|
* @preserve
|
292
|
+
* @augments ConfigurableComponent<ButtonConfig>
|
254
293
|
*/
|
255
|
-
class Button extends
|
294
|
+
class Button extends ConfigurableComponent {
|
256
295
|
/**
|
257
296
|
* @param {Element | null} $root - HTML element to use for button
|
258
297
|
* @param {ButtonConfig} [config] - Button config
|
259
298
|
*/
|
260
299
|
constructor($root, config = {}) {
|
261
|
-
super($root);
|
262
|
-
this.config = void 0;
|
300
|
+
super($root, config);
|
263
301
|
this.debounceFormSubmitTimer = null;
|
264
|
-
this.config = mergeConfigs(Button.defaults, config, normaliseDataset(Button, this.$root.dataset));
|
265
302
|
this.$root.addEventListener('keydown', event => this.handleKeyDown(event));
|
266
303
|
this.$root.addEventListener('click', event => this.debounce(event));
|
267
304
|
}
|
@@ -298,7 +335,7 @@
|
|
298
335
|
*/
|
299
336
|
|
300
337
|
/**
|
301
|
-
* @typedef {import('../../common/
|
338
|
+
* @typedef {import('../../common/configuration.mjs').Schema} Schema
|
302
339
|
*/
|
303
340
|
Button.moduleName = 'govuk-button';
|
304
341
|
Button.defaults = Object.freeze({
|