defra_ruby_template 5.4.1 → 5.11.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/views/layouts/defra_ruby_template.html.erb +39 -18
- data/lib/defra_ruby_template/version.rb +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.js +882 -492
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.js.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs +877 -492
- data/node_modules/govuk-frontend/dist/govuk/all.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/all.mjs +5 -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/assets/images/govuk-crest.svg +1 -0
- data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/favicon.ico +0 -0
- data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/favicon.svg +1 -0
- data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-crest.svg +1 -0
- data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-icon-180.png +0 -0
- data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-icon-192.png +0 -0
- data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-icon-512.png +0 -0
- data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-icon-mask.svg +1 -0
- data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/images/govuk-opengraph-image.png +0 -0
- data/node_modules/govuk-frontend/dist/govuk/assets/rebrand/manifest.json +39 -0
- data/node_modules/govuk-frontend/dist/govuk/common/closest-attribute-value.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/common/configuration.mjs +169 -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 +20 -83
- data/node_modules/govuk-frontend/dist/govuk/common/index.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/component.mjs +60 -0
- data/node_modules/govuk-frontend/dist/govuk/component.mjs.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/_index.scss +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/_index.scss +35 -31
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js +296 -195
- 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 +295 -194
- 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 +88 -110
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/accordion/fixtures.json +16 -3
- data/node_modules/govuk-frontend/dist/govuk/components/back-link/fixtures.json +25 -15
- data/node_modules/govuk-frontend/dist/govuk/components/back-link/template-with-custom-link.html +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/back-link/template.njk +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/fixtures.json +53 -15
- data/node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/macro-options.json +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/template-default.html +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/template-inverse.html +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/template-with-collapse-on-mobile.html +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/template-with-last-breadcrumb-as-current-page.html +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/template-with-multiple-levels.html +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/template-with-one-level.html +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/template-without-the-home-section.html +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/template.njk +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js +217 -106
- 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 +216 -105
- 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 +9 -22
- data/node_modules/govuk-frontend/dist/govuk/components/button/button.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/button/fixtures.json +38 -0
- data/node_modules/govuk-frontend/dist/govuk/components/button/macro-options.json +2 -1
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/_index.scss +12 -4
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/character-count.bundle.js +256 -145
- 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 +255 -144
- 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 +29 -34
- 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/fixtures.json +80 -1
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/macro-options.json +6 -6
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-error.html +12 -0
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/template-with-hint-and-error.html +15 -0
- data/node_modules/govuk-frontend/dist/govuk/components/character-count/template.njk +5 -4
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/_index.scss +6 -1
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.js +96 -50
- 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 +95 -49
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs +9 -18
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/checkboxes.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/fixtures.json +88 -1
- data/node_modules/govuk-frontend/dist/govuk/components/checkboxes/template-small-with-divider-and-none.html +34 -0
- data/node_modules/govuk-frontend/dist/govuk/components/cookie-banner/_index.scss +23 -14
- data/node_modules/govuk-frontend/dist/govuk/components/cookie-banner/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/cookie-banner/fixtures.json +23 -0
- data/node_modules/govuk-frontend/dist/govuk/components/date-input/_index.scss +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/date-input/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/date-input/fixtures.json +27 -0
- data/node_modules/govuk-frontend/dist/govuk/components/date-input/macro-options.json +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/details/_index.scss +7 -2
- data/node_modules/govuk-frontend/dist/govuk/components/details/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/details/fixtures.json +10 -0
- data/node_modules/govuk-frontend/dist/govuk/components/error-message/fixtures.json +9 -0
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/_index.scss +4 -0
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.bundle.js +238 -127
- 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 +237 -126
- 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 +10 -22
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/error-summary.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/error-summary/fixtures.json +19 -0
- data/node_modules/govuk-frontend/dist/govuk/components/exit-this-page/exit-this-page.bundle.js +218 -107
- 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 +217 -106
- 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 +10 -22
- 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/exit-this-page/fixtures.json +4 -0
- data/node_modules/govuk-frontend/dist/govuk/components/fieldset/_index.scss +3 -5
- data/node_modules/govuk-frontend/dist/govuk/components/fieldset/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/fieldset/fixtures.json +18 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/_index.scss +175 -9
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js +744 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.js.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs +736 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.bundle.mjs.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs +257 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/file-upload.mjs.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/fixtures.json +220 -16
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/macro-options.json +52 -3
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/template-allows-direct-media-capture.html +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/template-allows-image-files-only.html +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/template-allows-multiple-files.html +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/template-disabled.html +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/template-enhanced-disabled.html +13 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/template-enhanced-with-error-message-and-hint.html +16 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/template-enhanced.html +10 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/template-translated.html +10 -0
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/template.njk +42 -5
- data/node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss +61 -19
- data/node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/footer/fixtures.json +34 -0
- data/node_modules/govuk-frontend/dist/govuk/components/footer/macro-options.json +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/footer/template.njk +10 -0
- data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss +223 -21
- data/node_modules/govuk-frontend/dist/govuk/components/header/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/header/fixtures.json +78 -32
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.js +90 -43
- 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 +89 -42
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs +10 -18
- data/node_modules/govuk-frontend/dist/govuk/components/header/header.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/header/macro-options.json +31 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-default.html +20 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-full-width-with-navigation.html +21 -15
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-full-width.html +21 -15
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-navigation-item-with-html.html +20 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-navigation-item-with-text-without-link.html +20 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-custom-menu-button-label.html +20 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-custom-menu-button-text.html +20 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-custom-navigation-label.html +20 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-full-width-border.html +30 -0
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-large-navigation.html +20 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-navigation.html +20 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-product-name.html +21 -15
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-service-name-and-navigation.html +20 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-service-name-but-no-service-url.html +20 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-service-name.html +20 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template-with-st-edwards-crown.html +10 -12
- data/node_modules/govuk-frontend/dist/govuk/components/header/template.njk +11 -41
- data/node_modules/govuk-frontend/dist/govuk/components/hint/fixtures.json +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/input/_index.scss +7 -4
- data/node_modules/govuk-frontend/dist/govuk/components/input/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/input/fixtures.json +97 -27
- data/node_modules/govuk-frontend/dist/govuk/components/input/macro-options.json +6 -6
- data/node_modules/govuk-frontend/dist/govuk/components/input/template-default.html +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/input/template-disabled.html +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/input/template-with-error-and-hint.html +12 -0
- data/node_modules/govuk-frontend/dist/govuk/components/input/template-with-error-message.html +2 -5
- data/node_modules/govuk-frontend/dist/govuk/components/input/template.njk +5 -4
- data/node_modules/govuk-frontend/dist/govuk/components/inset-text/fixtures.json +6 -0
- data/node_modules/govuk-frontend/dist/govuk/components/label/fixtures.json +17 -0
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/_index.scss +3 -2
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/fixtures.json +24 -0
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.bundle.js +238 -127
- 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 +237 -126
- 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 +10 -22
- data/node_modules/govuk-frontend/dist/govuk/components/notification-banner/notification-banner.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/pagination/_index.scss +24 -37
- data/node_modules/govuk-frontend/dist/govuk/components/pagination/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/pagination/fixtures.json +15 -0
- data/node_modules/govuk-frontend/dist/govuk/components/pagination/macro-options.json +4 -4
- data/node_modules/govuk-frontend/dist/govuk/components/panel/_index.scss +13 -9
- data/node_modules/govuk-frontend/dist/govuk/components/panel/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/panel/fixtures.json +9 -0
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/_index.scss +12 -9
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/fixtures.json +27 -2
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/macro-options.json +3 -3
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.bundle.js +220 -110
- 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 +219 -109
- 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 +12 -25
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/password-input.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/template-default.html +3 -3
- data/node_modules/govuk-frontend/dist/govuk/components/password-input/template.njk +4 -2
- data/node_modules/govuk-frontend/dist/govuk/components/phase-banner/_index.scss +0 -8
- data/node_modules/govuk-frontend/dist/govuk/components/phase-banner/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/phase-banner/fixtures.json +7 -0
- data/node_modules/govuk-frontend/dist/govuk/components/radios/_index.scss +7 -5
- data/node_modules/govuk-frontend/dist/govuk/components/radios/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/radios/fixtures.json +51 -5
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.js +96 -50
- 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 +95 -49
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs +9 -18
- data/node_modules/govuk-frontend/dist/govuk/components/radios/radios.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/radios/template-small-with-a-divider.html +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/radios/template-with-a-divider.html +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/select/_index.scss +5 -5
- data/node_modules/govuk-frontend/dist/govuk/components/select/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/select/fixtures.json +43 -9
- data/node_modules/govuk-frontend/dist/govuk/components/select/macro-options.json +2 -2
- data/node_modules/govuk-frontend/dist/govuk/components/select/template-id.html +7 -0
- data/node_modules/govuk-frontend/dist/govuk/components/select/template.njk +6 -4
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/README.md +15 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_index.scss +187 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_index.scss.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_service-navigation.scss +4 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/_service-navigation.scss.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/fixtures.json +515 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/macro-options.json +138 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/macro.njk +3 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js +229 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.js.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs +221 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.bundle.mjs.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs +85 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/service-navigation.mjs.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-default.html +57 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-html-navigation-items.html +49 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-large-navigation.html +153 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-long-service-name.html +20 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-navigation-with-a-current-item.html +58 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-navigation-with-an-active-item.html +58 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-non-link-navigation-items.html +49 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-link.html +20 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-name-and-navigation.html +63 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template-with-service-name.html +18 -0
- data/node_modules/govuk-frontend/dist/govuk/components/service-navigation/template.njk +103 -0
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/_index.scss +6 -4
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/fixtures.json +9 -0
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.bundle.js +95 -48
- 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 +94 -47
- 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/skip-link/skip-link.mjs +15 -23
- data/node_modules/govuk-frontend/dist/govuk/components/skip-link/skip-link.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/summary-list/_index.scss +14 -22
- data/node_modules/govuk-frontend/dist/govuk/components/summary-list/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/summary-list/fixtures.json +174 -1
- data/node_modules/govuk-frontend/dist/govuk/components/summary-list/template-as-a-summary-card-extreme.html +106 -0
- data/node_modules/govuk-frontend/dist/govuk/components/table/fixtures.json +22 -1
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/fixtures.json +15 -1
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.js +95 -53
- 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 +94 -52
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.bundle.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs +15 -28
- data/node_modules/govuk-frontend/dist/govuk/components/tabs/tabs.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/tag/_index.scss +11 -8
- data/node_modules/govuk-frontend/dist/govuk/components/tag/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/tag/fixtures.json +14 -0
- data/node_modules/govuk-frontend/dist/govuk/components/task-list/_index.scss +12 -10
- data/node_modules/govuk-frontend/dist/govuk/components/task-list/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/task-list/fixtures.json +44 -0
- data/node_modules/govuk-frontend/dist/govuk/components/task-list/template-with-empty-values.html +27 -0
- data/node_modules/govuk-frontend/dist/govuk/components/task-list/template.njk +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/textarea/_index.scss +3 -3
- data/node_modules/govuk-frontend/dist/govuk/components/textarea/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/textarea/fixtures.json +32 -1
- data/node_modules/govuk-frontend/dist/govuk/components/textarea/macro-options.json +3 -3
- data/node_modules/govuk-frontend/dist/govuk/components/textarea/template.njk +6 -4
- data/node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss +6 -5
- data/node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/components/warning-text/fixtures.json +8 -0
- data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss +1 -1
- data/node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs +16 -3
- data/node_modules/govuk-frontend/dist/govuk/errors/index.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend.min.css +2 -2
- 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/helpers/_colour.scss +55 -8
- data/node_modules/govuk-frontend/dist/govuk/helpers/_colour.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/helpers/_focused.scss +14 -4
- data/node_modules/govuk-frontend/dist/govuk/helpers/_focused.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/helpers/_grid.scss +1 -1
- data/node_modules/govuk-frontend/dist/govuk/helpers/_grid.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/helpers/_links.scss +2 -2
- data/node_modules/govuk-frontend/dist/govuk/helpers/_links.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/helpers/_shape-arrow.scss +1 -1
- data/node_modules/govuk-frontend/dist/govuk/helpers/_shape-arrow.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/helpers/_typography.scss +18 -1
- data/node_modules/govuk-frontend/dist/govuk/helpers/_typography.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/helpers/_visually-hidden.scss +30 -62
- data/node_modules/govuk-frontend/dist/govuk/helpers/_visually-hidden.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/i18n.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/init.mjs +90 -24
- data/node_modules/govuk-frontend/dist/govuk/init.mjs.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/macros/logo.njk +78 -0
- data/node_modules/govuk-frontend/dist/govuk/objects/_template.scss +5 -1
- data/node_modules/govuk-frontend/dist/govuk/objects/_template.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/overrides/_typography.scss +5 -1
- data/node_modules/govuk-frontend/dist/govuk/overrides/_typography.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/settings/_colours-applied.scss +39 -1
- data/node_modules/govuk-frontend/dist/govuk/settings/_colours-applied.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss +244 -10
- data/node_modules/govuk-frontend/dist/govuk/settings/_colours-organisations.scss.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/dist/govuk/template.njk +20 -9
- data/node_modules/govuk-frontend/dist/govuk/tools/_index.scss +1 -0
- data/node_modules/govuk-frontend/dist/govuk/tools/_index.scss.map +1 -1
- data/node_modules/govuk-frontend/dist/govuk/tools/_rebrand.scss +65 -0
- data/node_modules/govuk-frontend/dist/govuk/tools/_rebrand.scss.map +1 -0
- data/node_modules/govuk-frontend/dist/govuk-prototype-kit/functions.js +25 -0
- data/node_modules/govuk-frontend/dist/govuk-prototype-kit/init.scss +1 -1
- data/node_modules/govuk-frontend/dist/govuk-prototype-kit/init.scss.map +1 -1
- data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +8 -1
- data/node_modules/govuk-frontend/package.json +16 -16
- data/spec/spec_helper.rb +98 -0
- data/spec/tasks/assets_spec.rb +53 -0
- data/vendor/assets/assets/fonts/bold-affa96571d-v2.woff +0 -0
- data/vendor/assets/assets/fonts/bold-b542beb274-v2.woff2 +0 -0
- data/vendor/assets/assets/fonts/light-94a07e06a1-v2.woff2 +0 -0
- data/vendor/assets/assets/fonts/light-f591b13f7d-v2.woff +0 -0
- data/vendor/assets/assets/images/favicon.ico +0 -0
- data/vendor/assets/assets/images/favicon.svg +1 -0
- data/vendor/assets/assets/images/govuk-crest.svg +1 -0
- data/vendor/assets/assets/images/govuk-icon-180.png +0 -0
- data/vendor/assets/assets/images/govuk-icon-192.png +0 -0
- data/vendor/assets/assets/images/govuk-icon-512.png +0 -0
- data/vendor/assets/assets/images/govuk-icon-mask.svg +1 -0
- data/vendor/assets/assets/images/govuk-opengraph-image.png +0 -0
- data/vendor/assets/assets/manifest.json +39 -0
- data/vendor/assets/assets/rebrand/images/favicon.ico +0 -0
- data/vendor/assets/assets/rebrand/images/favicon.svg +1 -0
- data/vendor/assets/assets/rebrand/images/govuk-crest.svg +1 -0
- data/vendor/assets/assets/rebrand/images/govuk-icon-180.png +0 -0
- data/vendor/assets/assets/rebrand/images/govuk-icon-192.png +0 -0
- data/vendor/assets/assets/rebrand/images/govuk-icon-512.png +0 -0
- data/vendor/assets/assets/rebrand/images/govuk-icon-mask.svg +1 -0
- data/vendor/assets/assets/rebrand/images/govuk-opengraph-image.png +0 -0
- data/vendor/assets/assets/rebrand/manifest.json +39 -0
- data/vendor/assets/images/govuk-crest.svg +1 -0
- data/vendor/assets/javascripts/defra_ruby_template.js +882 -492
- data/vendor/assets/stylesheets/all.scss +6 -0
- data/vendor/assets/stylesheets/components/_index.scss +1 -0
- data/vendor/assets/stylesheets/components/accordion/_index.scss +35 -31
- data/vendor/assets/stylesheets/components/character-count/_index.scss +12 -4
- data/vendor/assets/stylesheets/components/checkboxes/_index.scss +6 -1
- data/vendor/assets/stylesheets/components/cookie-banner/_index.scss +23 -14
- data/vendor/assets/stylesheets/components/date-input/_index.scss +2 -2
- data/vendor/assets/stylesheets/components/details/_index.scss +7 -2
- data/vendor/assets/stylesheets/components/error-summary/_index.scss +4 -0
- data/vendor/assets/stylesheets/components/fieldset/_index.scss +3 -5
- data/vendor/assets/stylesheets/components/file-upload/_index.scss +175 -9
- data/vendor/assets/stylesheets/components/footer/_index.scss +61 -19
- data/vendor/assets/stylesheets/components/header/_index.scss +223 -21
- data/vendor/assets/stylesheets/components/input/_index.scss +7 -4
- data/vendor/assets/stylesheets/components/notification-banner/_index.scss +3 -2
- data/vendor/assets/stylesheets/components/pagination/_index.scss +24 -37
- data/vendor/assets/stylesheets/components/panel/_index.scss +13 -9
- data/vendor/assets/stylesheets/components/password-input/_index.scss +12 -9
- data/vendor/assets/stylesheets/components/phase-banner/_index.scss +0 -8
- data/vendor/assets/stylesheets/components/radios/_index.scss +7 -5
- data/vendor/assets/stylesheets/components/select/_index.scss +5 -5
- data/vendor/assets/stylesheets/components/service-navigation/_index.scss +187 -0
- data/vendor/assets/stylesheets/components/service-navigation/_service-navigation.scss +4 -0
- data/vendor/assets/stylesheets/components/skip-link/_index.scss +6 -4
- data/vendor/assets/stylesheets/components/summary-list/_index.scss +14 -22
- data/vendor/assets/stylesheets/components/tag/_index.scss +11 -8
- data/vendor/assets/stylesheets/components/task-list/_index.scss +12 -10
- data/vendor/assets/stylesheets/components/textarea/_index.scss +3 -3
- data/vendor/assets/stylesheets/components/warning-text/_index.scss +6 -5
- data/vendor/assets/stylesheets/core/_govuk-frontend-properties.scss +1 -1
- data/vendor/assets/stylesheets/defra_ruby_template.scss +6 -0
- data/vendor/assets/stylesheets/govuk-frontend.min.css +2 -2
- data/vendor/assets/stylesheets/helpers/_colour.scss +55 -8
- data/vendor/assets/stylesheets/helpers/_focused.scss +14 -4
- data/vendor/assets/stylesheets/helpers/_grid.scss +1 -1
- data/vendor/assets/stylesheets/helpers/_links.scss +2 -2
- data/vendor/assets/stylesheets/helpers/_shape-arrow.scss +1 -1
- data/vendor/assets/stylesheets/helpers/_typography.scss +18 -1
- data/vendor/assets/stylesheets/helpers/_visually-hidden.scss +30 -62
- data/vendor/assets/stylesheets/objects/_template.scss +5 -1
- data/vendor/assets/stylesheets/overrides/_typography.scss +5 -1
- data/vendor/assets/stylesheets/settings/_colours-applied.scss +39 -1
- data/vendor/assets/stylesheets/settings/_colours-organisations.scss +244 -10
- data/vendor/assets/stylesheets/settings/_typography-responsive.scss +5 -10
- data/vendor/assets/stylesheets/tools/_index.scss +1 -0
- data/vendor/assets/stylesheets/tools/_rebrand.scss +65 -0
- metadata +100 -24
- data/.github/dependabot.yml +0 -14
- data/.github/workflows/ci.yml +0 -31
- data/.gitignore +0 -8
- data/.rspec +0 -1
- data/.rubocop.yml +0 -3
- data/.ruby-version +0 -1
- data/Gemfile +0 -9
- data/Gemfile.lock +0 -58
- data/defra_ruby_template.gemspec +0 -35
- data/node_modules/.package-lock.json +0 -16
- data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest-2x.png +0 -0
- data/node_modules/govuk-frontend/dist/govuk/assets/images/govuk-crest.png +0 -0
- 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
- data/node_modules/govuk-frontend/dist/govuk/components/file-upload/template-with-value.html +0 -6
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend-component.mjs +0 -16
- data/node_modules/govuk-frontend/dist/govuk/govuk-frontend-component.mjs.map +0 -1
- data/package-lock.json +0 -24
- data/package.json +0 -29
@@ -1,75 +1,5 @@
|
|
1
|
-
const version = '5.
|
1
|
+
const version = '5.10.2';
|
2
2
|
|
3
|
-
function normaliseString(value, property) {
|
4
|
-
const trimmedValue = value ? value.trim() : '';
|
5
|
-
let output;
|
6
|
-
let outputType = property == null ? void 0 : property.type;
|
7
|
-
if (!outputType) {
|
8
|
-
if (['true', 'false'].includes(trimmedValue)) {
|
9
|
-
outputType = 'boolean';
|
10
|
-
}
|
11
|
-
if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
|
12
|
-
outputType = 'number';
|
13
|
-
}
|
14
|
-
}
|
15
|
-
switch (outputType) {
|
16
|
-
case 'boolean':
|
17
|
-
output = trimmedValue === 'true';
|
18
|
-
break;
|
19
|
-
case 'number':
|
20
|
-
output = Number(trimmedValue);
|
21
|
-
break;
|
22
|
-
default:
|
23
|
-
output = value;
|
24
|
-
}
|
25
|
-
return output;
|
26
|
-
}
|
27
|
-
|
28
|
-
/**
|
29
|
-
* @typedef {import('./index.mjs').SchemaProperty} SchemaProperty
|
30
|
-
*/
|
31
|
-
|
32
|
-
function mergeConfigs(...configObjects) {
|
33
|
-
const formattedConfigObject = {};
|
34
|
-
for (const configObject of configObjects) {
|
35
|
-
for (const key of Object.keys(configObject)) {
|
36
|
-
const option = formattedConfigObject[key];
|
37
|
-
const override = configObject[key];
|
38
|
-
if (isObject(option) && isObject(override)) {
|
39
|
-
formattedConfigObject[key] = mergeConfigs(option, override);
|
40
|
-
} else {
|
41
|
-
formattedConfigObject[key] = override;
|
42
|
-
}
|
43
|
-
}
|
44
|
-
}
|
45
|
-
return formattedConfigObject;
|
46
|
-
}
|
47
|
-
function extractConfigByNamespace(Component, dataset, namespace) {
|
48
|
-
const property = Component.schema.properties[namespace];
|
49
|
-
if ((property == null ? void 0 : property.type) !== 'object') {
|
50
|
-
return;
|
51
|
-
}
|
52
|
-
const newObject = {
|
53
|
-
[namespace]: ({})
|
54
|
-
};
|
55
|
-
for (const [key, value] of Object.entries(dataset)) {
|
56
|
-
let current = newObject;
|
57
|
-
const keyParts = key.split('.');
|
58
|
-
for (const [index, name] of keyParts.entries()) {
|
59
|
-
if (typeof current === 'object') {
|
60
|
-
if (index < keyParts.length - 1) {
|
61
|
-
if (!isObject(current[name])) {
|
62
|
-
current[name] = {};
|
63
|
-
}
|
64
|
-
current = current[name];
|
65
|
-
} else if (key !== namespace) {
|
66
|
-
current[name] = normaliseString(value);
|
67
|
-
}
|
68
|
-
}
|
69
|
-
}
|
70
|
-
}
|
71
|
-
return newObject[namespace];
|
72
|
-
}
|
73
3
|
function getFragmentFromUrl(url) {
|
74
4
|
if (!url.includes('#')) {
|
75
5
|
return undefined;
|
@@ -108,75 +38,42 @@ function setFocus($element, options = {}) {
|
|
108
38
|
(_options$onBeforeFocu = options.onBeforeFocus) == null || _options$onBeforeFocu.call($element);
|
109
39
|
$element.focus();
|
110
40
|
}
|
41
|
+
function isInitialised($root, moduleName) {
|
42
|
+
return $root instanceof HTMLElement && $root.hasAttribute(`data-${moduleName}-init`);
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
* Checks if GOV.UK Frontend is supported on this page
|
47
|
+
*
|
48
|
+
* Some browsers will load and run our JavaScript but GOV.UK Frontend
|
49
|
+
* won't be supported.
|
50
|
+
*
|
51
|
+
* @param {HTMLElement | null} [$scope] - (internal) `<body>` HTML element checked for browser support
|
52
|
+
* @returns {boolean} Whether GOV.UK Frontend is supported on this page
|
53
|
+
*/
|
111
54
|
function isSupported($scope = document.body) {
|
112
55
|
if (!$scope) {
|
113
56
|
return false;
|
114
57
|
}
|
115
58
|
return $scope.classList.contains('govuk-frontend-supported');
|
116
59
|
}
|
117
|
-
function validateConfig(schema, config) {
|
118
|
-
const validationErrors = [];
|
119
|
-
for (const [name, conditions] of Object.entries(schema)) {
|
120
|
-
const errors = [];
|
121
|
-
if (Array.isArray(conditions)) {
|
122
|
-
for (const {
|
123
|
-
required,
|
124
|
-
errorMessage
|
125
|
-
} of conditions) {
|
126
|
-
if (!required.every(key => !!config[key])) {
|
127
|
-
errors.push(errorMessage);
|
128
|
-
}
|
129
|
-
}
|
130
|
-
if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {
|
131
|
-
validationErrors.push(...errors);
|
132
|
-
}
|
133
|
-
}
|
134
|
-
}
|
135
|
-
return validationErrors;
|
136
|
-
}
|
137
60
|
function isArray(option) {
|
138
61
|
return Array.isArray(option);
|
139
62
|
}
|
140
63
|
function isObject(option) {
|
141
64
|
return !!option && typeof option === 'object' && !isArray(option);
|
142
65
|
}
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
*
|
147
|
-
* @typedef {object} Schema
|
148
|
-
* @property {{ [field: string]: SchemaProperty | undefined }} properties - Schema properties
|
149
|
-
* @property {SchemaCondition[]} [anyOf] - List of schema conditions
|
150
|
-
*/
|
151
|
-
|
66
|
+
function formatErrorMessage(Component, message) {
|
67
|
+
return `${Component.moduleName}: ${message}`;
|
68
|
+
}
|
152
69
|
/**
|
153
|
-
*
|
154
|
-
*
|
155
|
-
* @typedef {object} SchemaProperty
|
156
|
-
* @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
|
70
|
+
* @typedef ComponentWithModuleName
|
71
|
+
* @property {string} moduleName - Name of the component
|
157
72
|
*/
|
158
|
-
|
159
73
|
/**
|
160
|
-
*
|
161
|
-
*
|
162
|
-
* @typedef {object} SchemaCondition
|
163
|
-
* @property {string[]} required - List of required config fields
|
164
|
-
* @property {string} errorMessage - Error message when required config fields not provided
|
74
|
+
* @import { ObjectNested } from './configuration.mjs'
|
165
75
|
*/
|
166
76
|
|
167
|
-
function normaliseDataset(Component, dataset) {
|
168
|
-
const out = {};
|
169
|
-
for (const [field, property] of Object.entries(Component.schema.properties)) {
|
170
|
-
if (field in dataset) {
|
171
|
-
out[field] = normaliseString(dataset[field], property);
|
172
|
-
}
|
173
|
-
if ((property == null ? void 0 : property.type) === 'object') {
|
174
|
-
out[field] = extractConfigByNamespace(Component, dataset, field);
|
175
|
-
}
|
176
|
-
}
|
177
|
-
return out;
|
178
|
-
}
|
179
|
-
|
180
77
|
class GOVUKFrontendError extends Error {
|
181
78
|
constructor(...args) {
|
182
79
|
super(...args);
|
@@ -206,30 +103,248 @@ class ElementError extends GOVUKFrontendError {
|
|
206
103
|
let message = typeof messageOrOptions === 'string' ? messageOrOptions : '';
|
207
104
|
if (typeof messageOrOptions === 'object') {
|
208
105
|
const {
|
209
|
-
|
106
|
+
component,
|
210
107
|
identifier,
|
211
108
|
element,
|
212
109
|
expectedType
|
213
110
|
} = messageOrOptions;
|
214
|
-
message =
|
111
|
+
message = identifier;
|
215
112
|
message += element ? ` is not of type ${expectedType != null ? expectedType : 'HTMLElement'}` : ' not found';
|
113
|
+
message = formatErrorMessage(component, message);
|
216
114
|
}
|
217
115
|
super(message);
|
218
116
|
this.name = 'ElementError';
|
219
117
|
}
|
220
118
|
}
|
119
|
+
class InitError extends GOVUKFrontendError {
|
120
|
+
constructor(componentOrMessage) {
|
121
|
+
const message = typeof componentOrMessage === 'string' ? componentOrMessage : formatErrorMessage(componentOrMessage, `Root element (\`$root\`) already initialised`);
|
122
|
+
super(message);
|
123
|
+
this.name = 'InitError';
|
124
|
+
}
|
125
|
+
}
|
126
|
+
/**
|
127
|
+
* @import { ComponentWithModuleName } from '../common/index.mjs'
|
128
|
+
*/
|
221
129
|
|
222
|
-
class
|
223
|
-
|
224
|
-
|
130
|
+
class Component {
|
131
|
+
/**
|
132
|
+
* Returns the root element of the component
|
133
|
+
*
|
134
|
+
* @protected
|
135
|
+
* @returns {RootElementType} - the root element of component
|
136
|
+
*/
|
137
|
+
get $root() {
|
138
|
+
return this._$root;
|
139
|
+
}
|
140
|
+
constructor($root) {
|
141
|
+
this._$root = void 0;
|
142
|
+
const childConstructor = this.constructor;
|
143
|
+
if (typeof childConstructor.moduleName !== 'string') {
|
144
|
+
throw new InitError(`\`moduleName\` not defined in component`);
|
145
|
+
}
|
146
|
+
if (!($root instanceof childConstructor.elementType)) {
|
147
|
+
throw new ElementError({
|
148
|
+
element: $root,
|
149
|
+
component: childConstructor,
|
150
|
+
identifier: 'Root element (`$root`)',
|
151
|
+
expectedType: childConstructor.elementType.name
|
152
|
+
});
|
153
|
+
} else {
|
154
|
+
this._$root = $root;
|
155
|
+
}
|
156
|
+
childConstructor.checkSupport();
|
157
|
+
this.checkInitialised();
|
158
|
+
const moduleName = childConstructor.moduleName;
|
159
|
+
this.$root.setAttribute(`data-${moduleName}-init`, '');
|
160
|
+
}
|
161
|
+
checkInitialised() {
|
162
|
+
const constructor = this.constructor;
|
163
|
+
const moduleName = constructor.moduleName;
|
164
|
+
if (moduleName && isInitialised(this.$root, moduleName)) {
|
165
|
+
throw new InitError(constructor);
|
166
|
+
}
|
225
167
|
}
|
226
|
-
checkSupport() {
|
168
|
+
static checkSupport() {
|
227
169
|
if (!isSupported()) {
|
228
170
|
throw new SupportError();
|
229
171
|
}
|
230
172
|
}
|
231
173
|
}
|
232
174
|
|
175
|
+
/**
|
176
|
+
* @typedef ChildClass
|
177
|
+
* @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
|
178
|
+
*/
|
179
|
+
|
180
|
+
/**
|
181
|
+
* @typedef {typeof Component & ChildClass} ChildClassConstructor
|
182
|
+
*/
|
183
|
+
Component.elementType = HTMLElement;
|
184
|
+
|
185
|
+
const configOverride = Symbol.for('configOverride');
|
186
|
+
class ConfigurableComponent extends Component {
|
187
|
+
[configOverride](param) {
|
188
|
+
return {};
|
189
|
+
}
|
190
|
+
|
191
|
+
/**
|
192
|
+
* Returns the root element of the component
|
193
|
+
*
|
194
|
+
* @protected
|
195
|
+
* @returns {ConfigurationType} - the root element of component
|
196
|
+
*/
|
197
|
+
get config() {
|
198
|
+
return this._config;
|
199
|
+
}
|
200
|
+
constructor($root, config) {
|
201
|
+
super($root);
|
202
|
+
this._config = void 0;
|
203
|
+
const childConstructor = this.constructor;
|
204
|
+
if (!isObject(childConstructor.defaults)) {
|
205
|
+
throw new ConfigError(formatErrorMessage(childConstructor, 'Config passed as parameter into constructor but no defaults defined'));
|
206
|
+
}
|
207
|
+
const datasetConfig = normaliseDataset(childConstructor, this._$root.dataset);
|
208
|
+
this._config = mergeConfigs(childConstructor.defaults, config != null ? config : {}, this[configOverride](datasetConfig), datasetConfig);
|
209
|
+
}
|
210
|
+
}
|
211
|
+
function normaliseString(value, property) {
|
212
|
+
const trimmedValue = value ? value.trim() : '';
|
213
|
+
let output;
|
214
|
+
let outputType = property == null ? void 0 : property.type;
|
215
|
+
if (!outputType) {
|
216
|
+
if (['true', 'false'].includes(trimmedValue)) {
|
217
|
+
outputType = 'boolean';
|
218
|
+
}
|
219
|
+
if (trimmedValue.length > 0 && isFinite(Number(trimmedValue))) {
|
220
|
+
outputType = 'number';
|
221
|
+
}
|
222
|
+
}
|
223
|
+
switch (outputType) {
|
224
|
+
case 'boolean':
|
225
|
+
output = trimmedValue === 'true';
|
226
|
+
break;
|
227
|
+
case 'number':
|
228
|
+
output = Number(trimmedValue);
|
229
|
+
break;
|
230
|
+
default:
|
231
|
+
output = value;
|
232
|
+
}
|
233
|
+
return output;
|
234
|
+
}
|
235
|
+
function normaliseDataset(Component, dataset) {
|
236
|
+
if (!isObject(Component.schema)) {
|
237
|
+
throw new ConfigError(formatErrorMessage(Component, 'Config passed as parameter into constructor but no schema defined'));
|
238
|
+
}
|
239
|
+
const out = {};
|
240
|
+
const entries = Object.entries(Component.schema.properties);
|
241
|
+
for (const entry of entries) {
|
242
|
+
const [namespace, property] = entry;
|
243
|
+
const field = namespace.toString();
|
244
|
+
if (field in dataset) {
|
245
|
+
out[field] = normaliseString(dataset[field], property);
|
246
|
+
}
|
247
|
+
if ((property == null ? void 0 : property.type) === 'object') {
|
248
|
+
out[field] = extractConfigByNamespace(Component.schema, dataset, namespace);
|
249
|
+
}
|
250
|
+
}
|
251
|
+
return out;
|
252
|
+
}
|
253
|
+
function mergeConfigs(...configObjects) {
|
254
|
+
const formattedConfigObject = {};
|
255
|
+
for (const configObject of configObjects) {
|
256
|
+
for (const key of Object.keys(configObject)) {
|
257
|
+
const option = formattedConfigObject[key];
|
258
|
+
const override = configObject[key];
|
259
|
+
if (isObject(option) && isObject(override)) {
|
260
|
+
formattedConfigObject[key] = mergeConfigs(option, override);
|
261
|
+
} else {
|
262
|
+
formattedConfigObject[key] = override;
|
263
|
+
}
|
264
|
+
}
|
265
|
+
}
|
266
|
+
return formattedConfigObject;
|
267
|
+
}
|
268
|
+
function validateConfig(schema, config) {
|
269
|
+
const validationErrors = [];
|
270
|
+
for (const [name, conditions] of Object.entries(schema)) {
|
271
|
+
const errors = [];
|
272
|
+
if (Array.isArray(conditions)) {
|
273
|
+
for (const {
|
274
|
+
required,
|
275
|
+
errorMessage
|
276
|
+
} of conditions) {
|
277
|
+
if (!required.every(key => !!config[key])) {
|
278
|
+
errors.push(errorMessage);
|
279
|
+
}
|
280
|
+
}
|
281
|
+
if (name === 'anyOf' && !(conditions.length - errors.length >= 1)) {
|
282
|
+
validationErrors.push(...errors);
|
283
|
+
}
|
284
|
+
}
|
285
|
+
}
|
286
|
+
return validationErrors;
|
287
|
+
}
|
288
|
+
function extractConfigByNamespace(schema, dataset, namespace) {
|
289
|
+
const property = schema.properties[namespace];
|
290
|
+
if ((property == null ? void 0 : property.type) !== 'object') {
|
291
|
+
return;
|
292
|
+
}
|
293
|
+
const newObject = {
|
294
|
+
[namespace]: {}
|
295
|
+
};
|
296
|
+
for (const [key, value] of Object.entries(dataset)) {
|
297
|
+
let current = newObject;
|
298
|
+
const keyParts = key.split('.');
|
299
|
+
for (const [index, name] of keyParts.entries()) {
|
300
|
+
if (isObject(current)) {
|
301
|
+
if (index < keyParts.length - 1) {
|
302
|
+
if (!isObject(current[name])) {
|
303
|
+
current[name] = {};
|
304
|
+
}
|
305
|
+
current = current[name];
|
306
|
+
} else if (key !== namespace) {
|
307
|
+
current[name] = normaliseString(value);
|
308
|
+
}
|
309
|
+
}
|
310
|
+
}
|
311
|
+
}
|
312
|
+
return newObject[namespace];
|
313
|
+
}
|
314
|
+
/**
|
315
|
+
* Schema for component config
|
316
|
+
*
|
317
|
+
* @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType
|
318
|
+
* @typedef {object} Schema
|
319
|
+
* @property {Record<keyof ConfigurationType, SchemaProperty | undefined>} properties - Schema properties
|
320
|
+
* @property {SchemaCondition<ConfigurationType>[]} [anyOf] - List of schema conditions
|
321
|
+
*/
|
322
|
+
/**
|
323
|
+
* Schema property for component config
|
324
|
+
*
|
325
|
+
* @typedef {object} SchemaProperty
|
326
|
+
* @property {'string' | 'boolean' | 'number' | 'object'} type - Property type
|
327
|
+
*/
|
328
|
+
/**
|
329
|
+
* Schema condition for component config
|
330
|
+
*
|
331
|
+
* @template {Partial<Record<keyof ConfigurationType, unknown>>} ConfigurationType
|
332
|
+
* @typedef {object} SchemaCondition
|
333
|
+
* @property {(keyof ConfigurationType)[]} required - List of required config fields
|
334
|
+
* @property {string} errorMessage - Error message when required config fields not provided
|
335
|
+
*/
|
336
|
+
/**
|
337
|
+
* @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]
|
338
|
+
* @typedef ChildClass
|
339
|
+
* @property {string} moduleName - The module name that'll be looked for in the DOM when initialising the component
|
340
|
+
* @property {Schema<ConfigurationType>} [schema] - The schema of the component configuration
|
341
|
+
* @property {ConfigurationType} [defaults] - The default values of the configuration of the component
|
342
|
+
*/
|
343
|
+
/**
|
344
|
+
* @template {Partial<Record<keyof ConfigurationType, unknown>>} [ConfigurationType=ObjectNested]
|
345
|
+
* @typedef {typeof Component & ChildClass<ConfigurationType>} ChildClassConstructor<ConfigurationType>
|
346
|
+
*/
|
347
|
+
|
233
348
|
class I18n {
|
234
349
|
constructor(translations = {}, config = {}) {
|
235
350
|
var _config$locale;
|
@@ -436,16 +551,15 @@ I18n.pluralRules = {
|
|
436
551
|
* attribute, which also provides accessibility.
|
437
552
|
*
|
438
553
|
* @preserve
|
554
|
+
* @augments ConfigurableComponent<AccordionConfig>
|
439
555
|
*/
|
440
|
-
class Accordion extends
|
556
|
+
class Accordion extends ConfigurableComponent {
|
441
557
|
/**
|
442
|
-
* @param {Element | null} $
|
558
|
+
* @param {Element | null} $root - HTML element to use for accordion
|
443
559
|
* @param {AccordionConfig} [config] - Accordion config
|
444
560
|
*/
|
445
|
-
constructor($
|
446
|
-
super();
|
447
|
-
this.$module = void 0;
|
448
|
-
this.config = void 0;
|
561
|
+
constructor($root, config = {}) {
|
562
|
+
super($root, config);
|
449
563
|
this.i18n = void 0;
|
450
564
|
this.controlsClass = 'govuk-accordion__controls';
|
451
565
|
this.showAllClass = 'govuk-accordion__show-all';
|
@@ -467,33 +581,21 @@ class Accordion extends GOVUKFrontendComponent {
|
|
467
581
|
this.sectionSummaryFocusClass = 'govuk-accordion__section-summary-focus';
|
468
582
|
this.sectionContentClass = 'govuk-accordion__section-content';
|
469
583
|
this.$sections = void 0;
|
470
|
-
this.browserSupportsSessionStorage = false;
|
471
584
|
this.$showAllButton = null;
|
472
585
|
this.$showAllIcon = null;
|
473
586
|
this.$showAllText = null;
|
474
|
-
if (!($module instanceof HTMLElement)) {
|
475
|
-
throw new ElementError({
|
476
|
-
componentName: 'Accordion',
|
477
|
-
element: $module,
|
478
|
-
identifier: 'Root element (`$module`)'
|
479
|
-
});
|
480
|
-
}
|
481
|
-
this.$module = $module;
|
482
|
-
this.config = mergeConfigs(Accordion.defaults, config, normaliseDataset(Accordion, $module.dataset));
|
483
587
|
this.i18n = new I18n(this.config.i18n);
|
484
|
-
const $sections = this.$
|
588
|
+
const $sections = this.$root.querySelectorAll(`.${this.sectionClass}`);
|
485
589
|
if (!$sections.length) {
|
486
590
|
throw new ElementError({
|
487
|
-
|
591
|
+
component: Accordion,
|
488
592
|
identifier: `Sections (\`<div class="${this.sectionClass}">\`)`
|
489
593
|
});
|
490
594
|
}
|
491
595
|
this.$sections = $sections;
|
492
|
-
this.browserSupportsSessionStorage = helper.checkForSessionStorage();
|
493
596
|
this.initControls();
|
494
597
|
this.initSectionHeaders();
|
495
|
-
|
496
|
-
this.updateShowAllButton(areAllSectionsOpen);
|
598
|
+
this.updateShowAllButton(this.areAllSectionsOpen());
|
497
599
|
}
|
498
600
|
initControls() {
|
499
601
|
this.$showAllButton = document.createElement('button');
|
@@ -506,7 +608,7 @@ class Accordion extends GOVUKFrontendComponent {
|
|
506
608
|
const $accordionControls = document.createElement('div');
|
507
609
|
$accordionControls.setAttribute('class', this.controlsClass);
|
508
610
|
$accordionControls.appendChild(this.$showAllButton);
|
509
|
-
this.$
|
611
|
+
this.$root.insertBefore($accordionControls, this.$root.firstChild);
|
510
612
|
this.$showAllText = document.createElement('span');
|
511
613
|
this.$showAllText.classList.add(this.showAllTextClass);
|
512
614
|
this.$showAllButton.appendChild(this.$showAllText);
|
@@ -520,7 +622,7 @@ class Accordion extends GOVUKFrontendComponent {
|
|
520
622
|
const $header = $section.querySelector(`.${this.sectionHeaderClass}`);
|
521
623
|
if (!$header) {
|
522
624
|
throw new ElementError({
|
523
|
-
|
625
|
+
component: Accordion,
|
524
626
|
identifier: `Section headers (\`<div class="${this.sectionHeaderClass}">\`)`
|
525
627
|
});
|
526
628
|
}
|
@@ -536,22 +638,22 @@ class Accordion extends GOVUKFrontendComponent {
|
|
536
638
|
const $summary = $header.querySelector(`.${this.sectionSummaryClass}`);
|
537
639
|
if (!$heading) {
|
538
640
|
throw new ElementError({
|
539
|
-
|
641
|
+
component: Accordion,
|
540
642
|
identifier: `Section heading (\`.${this.sectionHeadingClass}\`)`
|
541
643
|
});
|
542
644
|
}
|
543
645
|
if (!$span) {
|
544
646
|
throw new ElementError({
|
545
|
-
|
647
|
+
component: Accordion,
|
546
648
|
identifier: `Section button placeholder (\`<span class="${this.sectionButtonClass}">\`)`
|
547
649
|
});
|
548
650
|
}
|
549
651
|
const $button = document.createElement('button');
|
550
652
|
$button.setAttribute('type', 'button');
|
551
|
-
$button.setAttribute('aria-controls', `${this.$
|
653
|
+
$button.setAttribute('aria-controls', `${this.$root.id}-content-${index + 1}`);
|
552
654
|
for (const attr of Array.from($span.attributes)) {
|
553
|
-
if (attr.
|
554
|
-
$button.setAttribute(attr.
|
655
|
+
if (attr.name !== 'id') {
|
656
|
+
$button.setAttribute(attr.name, attr.value);
|
555
657
|
}
|
556
658
|
}
|
557
659
|
const $headingText = document.createElement('span');
|
@@ -560,7 +662,7 @@ class Accordion extends GOVUKFrontendComponent {
|
|
560
662
|
const $headingTextFocus = document.createElement('span');
|
561
663
|
$headingTextFocus.classList.add(this.sectionHeadingTextFocusClass);
|
562
664
|
$headingText.appendChild($headingTextFocus);
|
563
|
-
$
|
665
|
+
Array.from($span.childNodes).forEach($child => $headingTextFocus.appendChild($child));
|
564
666
|
const $showHideToggle = document.createElement('span');
|
565
667
|
$showHideToggle.classList.add(this.sectionShowHideToggleClass);
|
566
668
|
$showHideToggle.setAttribute('data-nosnippet', '');
|
@@ -575,16 +677,16 @@ class Accordion extends GOVUKFrontendComponent {
|
|
575
677
|
$showHideToggleFocus.appendChild($showHideText);
|
576
678
|
$button.appendChild($headingText);
|
577
679
|
$button.appendChild(this.getButtonPunctuationEl());
|
578
|
-
if ($summary
|
680
|
+
if ($summary) {
|
579
681
|
const $summarySpan = document.createElement('span');
|
580
682
|
const $summarySpanFocus = document.createElement('span');
|
581
683
|
$summarySpanFocus.classList.add(this.sectionSummaryFocusClass);
|
582
684
|
$summarySpan.appendChild($summarySpanFocus);
|
583
685
|
for (const attr of Array.from($summary.attributes)) {
|
584
|
-
$summarySpan.setAttribute(attr.
|
686
|
+
$summarySpan.setAttribute(attr.name, attr.value);
|
585
687
|
}
|
586
|
-
$
|
587
|
-
$summary.
|
688
|
+
Array.from($summary.childNodes).forEach($child => $summarySpanFocus.appendChild($child));
|
689
|
+
$summary.remove();
|
588
690
|
$button.appendChild($summarySpan);
|
589
691
|
$button.appendChild(this.getButtonPunctuationEl());
|
590
692
|
}
|
@@ -603,15 +705,15 @@ class Accordion extends GOVUKFrontendComponent {
|
|
603
705
|
}
|
604
706
|
}
|
605
707
|
onSectionToggle($section) {
|
606
|
-
const
|
607
|
-
this.setExpanded(
|
608
|
-
this.storeState($section);
|
708
|
+
const nowExpanded = !this.isExpanded($section);
|
709
|
+
this.setExpanded(nowExpanded, $section);
|
710
|
+
this.storeState($section, nowExpanded);
|
609
711
|
}
|
610
712
|
onShowOrHideAllToggle() {
|
611
|
-
const nowExpanded = !this.
|
713
|
+
const nowExpanded = !this.areAllSectionsOpen();
|
612
714
|
this.$sections.forEach($section => {
|
613
715
|
this.setExpanded(nowExpanded, $section);
|
614
|
-
this.storeState($section);
|
716
|
+
this.storeState($section, nowExpanded);
|
615
717
|
});
|
616
718
|
this.updateShowAllButton(nowExpanded);
|
617
719
|
}
|
@@ -622,7 +724,7 @@ class Accordion extends GOVUKFrontendComponent {
|
|
622
724
|
const $content = $section.querySelector(`.${this.sectionContentClass}`);
|
623
725
|
if (!$content) {
|
624
726
|
throw new ElementError({
|
625
|
-
|
727
|
+
component: Accordion,
|
626
728
|
identifier: `Section content (\`<div class="${this.sectionContentClass}">\`)`
|
627
729
|
});
|
628
730
|
}
|
@@ -653,17 +755,13 @@ class Accordion extends GOVUKFrontendComponent {
|
|
653
755
|
$section.classList.remove(this.sectionExpandedClass);
|
654
756
|
$showHideIcon.classList.add(this.downChevronIconClass);
|
655
757
|
}
|
656
|
-
|
657
|
-
this.updateShowAllButton(areAllSectionsOpen);
|
758
|
+
this.updateShowAllButton(this.areAllSectionsOpen());
|
658
759
|
}
|
659
760
|
isExpanded($section) {
|
660
761
|
return $section.classList.contains(this.sectionExpandedClass);
|
661
762
|
}
|
662
|
-
|
663
|
-
|
664
|
-
const expandedSectionCount = this.$module.querySelectorAll(`.${this.sectionExpandedClass}`).length;
|
665
|
-
const areAllSectionsOpen = sectionsCount === expandedSectionCount;
|
666
|
-
return areAllSectionsOpen;
|
763
|
+
areAllSectionsOpen() {
|
764
|
+
return Array.from(this.$sections).every($section => this.isExpanded($section));
|
667
765
|
}
|
668
766
|
updateShowAllButton(expanded) {
|
669
767
|
if (!this.$showAllButton || !this.$showAllText || !this.$showAllIcon) {
|
@@ -673,78 +771,53 @@ class Accordion extends GOVUKFrontendComponent {
|
|
673
771
|
this.$showAllText.textContent = expanded ? this.i18n.t('hideAllSections') : this.i18n.t('showAllSections');
|
674
772
|
this.$showAllIcon.classList.toggle(this.downChevronIconClass, !expanded);
|
675
773
|
}
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
774
|
+
|
775
|
+
/**
|
776
|
+
* Get the identifier for a section
|
777
|
+
*
|
778
|
+
* We need a unique way of identifying each content in the Accordion.
|
779
|
+
* Since an `#id` should be unique and an `id` is required for `aria-`
|
780
|
+
* attributes `id` can be safely used.
|
781
|
+
*
|
782
|
+
* @param {Element} $section - Section element
|
783
|
+
* @returns {string | undefined | null} Identifier for section
|
784
|
+
*/
|
785
|
+
getIdentifier($section) {
|
786
|
+
const $button = $section.querySelector(`.${this.sectionButtonClass}`);
|
787
|
+
return $button == null ? void 0 : $button.getAttribute('aria-controls');
|
687
788
|
}
|
688
|
-
|
689
|
-
if (this.
|
690
|
-
|
691
|
-
if ($button) {
|
692
|
-
const contentId = $button.getAttribute('aria-controls');
|
693
|
-
const contentState = contentId ? window.sessionStorage.getItem(contentId) : null;
|
694
|
-
if (contentState !== null) {
|
695
|
-
this.setExpanded(contentState === 'true', $section);
|
696
|
-
}
|
697
|
-
}
|
789
|
+
storeState($section, isExpanded) {
|
790
|
+
if (!this.config.rememberExpanded) {
|
791
|
+
return;
|
698
792
|
}
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
return $punctuationEl;
|
705
|
-
}
|
706
|
-
}
|
707
|
-
Accordion.moduleName = 'govuk-accordion';
|
708
|
-
Accordion.defaults = Object.freeze({
|
709
|
-
i18n: {
|
710
|
-
hideAllSections: 'Hide all sections',
|
711
|
-
hideSection: 'Hide',
|
712
|
-
hideSectionAriaLabel: 'Hide this section',
|
713
|
-
showAllSections: 'Show all sections',
|
714
|
-
showSection: 'Show',
|
715
|
-
showSectionAriaLabel: 'Show this section'
|
716
|
-
},
|
717
|
-
rememberExpanded: true
|
718
|
-
});
|
719
|
-
Accordion.schema = Object.freeze({
|
720
|
-
properties: {
|
721
|
-
i18n: {
|
722
|
-
type: 'object'
|
723
|
-
},
|
724
|
-
rememberExpanded: {
|
725
|
-
type: 'boolean'
|
793
|
+
const id = this.getIdentifier($section);
|
794
|
+
if (id) {
|
795
|
+
try {
|
796
|
+
window.sessionStorage.setItem(id, isExpanded.toString());
|
797
|
+
} catch (exception) {}
|
726
798
|
}
|
727
799
|
}
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
result = window.sessionStorage.getItem(testString) === testString.toString();
|
741
|
-
window.sessionStorage.removeItem(testString);
|
742
|
-
return result;
|
743
|
-
} catch (exception) {
|
744
|
-
return false;
|
800
|
+
setInitialState($section) {
|
801
|
+
if (!this.config.rememberExpanded) {
|
802
|
+
return;
|
803
|
+
}
|
804
|
+
const id = this.getIdentifier($section);
|
805
|
+
if (id) {
|
806
|
+
try {
|
807
|
+
const state = window.sessionStorage.getItem(id);
|
808
|
+
if (state !== null) {
|
809
|
+
this.setExpanded(state === 'true', $section);
|
810
|
+
}
|
811
|
+
} catch (exception) {}
|
745
812
|
}
|
746
813
|
}
|
747
|
-
|
814
|
+
getButtonPunctuationEl() {
|
815
|
+
const $punctuationEl = document.createElement('span');
|
816
|
+
$punctuationEl.classList.add('govuk-visually-hidden', this.sectionHeadingDividerClass);
|
817
|
+
$punctuationEl.textContent = ', ';
|
818
|
+
return $punctuationEl;
|
819
|
+
}
|
820
|
+
}
|
748
821
|
|
749
822
|
/**
|
750
823
|
* Accordion config
|
@@ -780,8 +853,30 @@ const helper = {
|
|
780
853
|
*/
|
781
854
|
|
782
855
|
/**
|
783
|
-
* @
|
856
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
784
857
|
*/
|
858
|
+
Accordion.moduleName = 'govuk-accordion';
|
859
|
+
Accordion.defaults = Object.freeze({
|
860
|
+
i18n: {
|
861
|
+
hideAllSections: 'Hide all sections',
|
862
|
+
hideSection: 'Hide',
|
863
|
+
hideSectionAriaLabel: 'Hide this section',
|
864
|
+
showAllSections: 'Show all sections',
|
865
|
+
showSection: 'Show',
|
866
|
+
showSectionAriaLabel: 'Show this section'
|
867
|
+
},
|
868
|
+
rememberExpanded: true
|
869
|
+
});
|
870
|
+
Accordion.schema = Object.freeze({
|
871
|
+
properties: {
|
872
|
+
i18n: {
|
873
|
+
type: 'object'
|
874
|
+
},
|
875
|
+
rememberExpanded: {
|
876
|
+
type: 'boolean'
|
877
|
+
}
|
878
|
+
}
|
879
|
+
});
|
785
880
|
|
786
881
|
const DEBOUNCE_TIMEOUT_IN_SECONDS = 1;
|
787
882
|
|
@@ -789,28 +884,18 @@ const DEBOUNCE_TIMEOUT_IN_SECONDS = 1;
|
|
789
884
|
* JavaScript enhancements for the Button component
|
790
885
|
*
|
791
886
|
* @preserve
|
887
|
+
* @augments ConfigurableComponent<ButtonConfig>
|
792
888
|
*/
|
793
|
-
class Button extends
|
889
|
+
class Button extends ConfigurableComponent {
|
794
890
|
/**
|
795
|
-
* @param {Element | null} $
|
891
|
+
* @param {Element | null} $root - HTML element to use for button
|
796
892
|
* @param {ButtonConfig} [config] - Button config
|
797
893
|
*/
|
798
|
-
constructor($
|
799
|
-
super();
|
800
|
-
this.$module = void 0;
|
801
|
-
this.config = void 0;
|
894
|
+
constructor($root, config = {}) {
|
895
|
+
super($root, config);
|
802
896
|
this.debounceFormSubmitTimer = null;
|
803
|
-
|
804
|
-
|
805
|
-
componentName: 'Button',
|
806
|
-
element: $module,
|
807
|
-
identifier: 'Root element (`$module`)'
|
808
|
-
});
|
809
|
-
}
|
810
|
-
this.$module = $module;
|
811
|
-
this.config = mergeConfigs(Button.defaults, config, normaliseDataset(Button, $module.dataset));
|
812
|
-
this.$module.addEventListener('keydown', event => this.handleKeyDown(event));
|
813
|
-
this.$module.addEventListener('click', event => this.debounce(event));
|
897
|
+
this.$root.addEventListener('keydown', event => this.handleKeyDown(event));
|
898
|
+
this.$root.addEventListener('click', event => this.debounce(event));
|
814
899
|
}
|
815
900
|
handleKeyDown(event) {
|
816
901
|
const $target = event.target;
|
@@ -845,7 +930,7 @@ class Button extends GOVUKFrontendComponent {
|
|
845
930
|
*/
|
846
931
|
|
847
932
|
/**
|
848
|
-
* @
|
933
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
849
934
|
*/
|
850
935
|
Button.moduleName = 'govuk-button';
|
851
936
|
Button.defaults = Object.freeze({
|
@@ -875,69 +960,63 @@ function closestAttributeValue($element, attributeName) {
|
|
875
960
|
* of the available characters/words has been entered.
|
876
961
|
*
|
877
962
|
* @preserve
|
963
|
+
* @augments ConfigurableComponent<CharacterCountConfig>
|
878
964
|
*/
|
879
|
-
class CharacterCount extends
|
965
|
+
class CharacterCount extends ConfigurableComponent {
|
966
|
+
[configOverride](datasetConfig) {
|
967
|
+
let configOverrides = {};
|
968
|
+
if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
|
969
|
+
configOverrides = {
|
970
|
+
maxlength: undefined,
|
971
|
+
maxwords: undefined
|
972
|
+
};
|
973
|
+
}
|
974
|
+
return configOverrides;
|
975
|
+
}
|
976
|
+
|
880
977
|
/**
|
881
|
-
* @param {Element | null} $
|
978
|
+
* @param {Element | null} $root - HTML element to use for character count
|
882
979
|
* @param {CharacterCountConfig} [config] - Character count config
|
883
980
|
*/
|
884
|
-
constructor($
|
981
|
+
constructor($root, config = {}) {
|
885
982
|
var _ref, _this$config$maxwords;
|
886
|
-
super();
|
887
|
-
this.$module = void 0;
|
983
|
+
super($root, config);
|
888
984
|
this.$textarea = void 0;
|
889
985
|
this.$visibleCountMessage = void 0;
|
890
986
|
this.$screenReaderCountMessage = void 0;
|
891
987
|
this.lastInputTimestamp = null;
|
892
988
|
this.lastInputValue = '';
|
893
989
|
this.valueChecker = null;
|
894
|
-
this.config = void 0;
|
895
990
|
this.i18n = void 0;
|
896
991
|
this.maxLength = void 0;
|
897
|
-
|
898
|
-
throw new ElementError({
|
899
|
-
componentName: 'Character count',
|
900
|
-
element: $module,
|
901
|
-
identifier: 'Root element (`$module`)'
|
902
|
-
});
|
903
|
-
}
|
904
|
-
const $textarea = $module.querySelector('.govuk-js-character-count');
|
992
|
+
const $textarea = this.$root.querySelector('.govuk-js-character-count');
|
905
993
|
if (!($textarea instanceof HTMLTextAreaElement || $textarea instanceof HTMLInputElement)) {
|
906
994
|
throw new ElementError({
|
907
|
-
|
995
|
+
component: CharacterCount,
|
908
996
|
element: $textarea,
|
909
997
|
expectedType: 'HTMLTextareaElement or HTMLInputElement',
|
910
998
|
identifier: 'Form field (`.govuk-js-character-count`)'
|
911
999
|
});
|
912
1000
|
}
|
913
|
-
const datasetConfig = normaliseDataset(CharacterCount, $module.dataset);
|
914
|
-
let configOverrides = {};
|
915
|
-
if ('maxwords' in datasetConfig || 'maxlength' in datasetConfig) {
|
916
|
-
configOverrides = {
|
917
|
-
maxlength: undefined,
|
918
|
-
maxwords: undefined
|
919
|
-
};
|
920
|
-
}
|
921
|
-
this.config = mergeConfigs(CharacterCount.defaults, config, configOverrides, datasetConfig);
|
922
1001
|
const errors = validateConfig(CharacterCount.schema, this.config);
|
923
1002
|
if (errors[0]) {
|
924
|
-
throw new ConfigError(
|
1003
|
+
throw new ConfigError(formatErrorMessage(CharacterCount, errors[0]));
|
925
1004
|
}
|
926
1005
|
this.i18n = new I18n(this.config.i18n, {
|
927
|
-
locale: closestAttributeValue(
|
1006
|
+
locale: closestAttributeValue(this.$root, 'lang')
|
928
1007
|
});
|
929
1008
|
this.maxLength = (_ref = (_this$config$maxwords = this.config.maxwords) != null ? _this$config$maxwords : this.config.maxlength) != null ? _ref : Infinity;
|
930
|
-
this.$module = $module;
|
931
1009
|
this.$textarea = $textarea;
|
932
1010
|
const textareaDescriptionId = `${this.$textarea.id}-info`;
|
933
1011
|
const $textareaDescription = document.getElementById(textareaDescriptionId);
|
934
1012
|
if (!$textareaDescription) {
|
935
1013
|
throw new ElementError({
|
936
|
-
|
1014
|
+
component: CharacterCount,
|
937
1015
|
element: $textareaDescription,
|
938
1016
|
identifier: `Count message (\`id="${textareaDescriptionId}"\`)`
|
939
1017
|
});
|
940
1018
|
}
|
1019
|
+
this.$errorMessage = this.$root.querySelector('.govuk-error-message');
|
941
1020
|
if (`${$textareaDescription.textContent}`.match(/^\s*$/)) {
|
942
1021
|
$textareaDescription.textContent = this.i18n.t('textareaDescription', {
|
943
1022
|
count: this.maxLength
|
@@ -996,7 +1075,9 @@ class CharacterCount extends GOVUKFrontendComponent {
|
|
996
1075
|
const remainingNumber = this.maxLength - this.count(this.$textarea.value);
|
997
1076
|
const isError = remainingNumber < 0;
|
998
1077
|
this.$visibleCountMessage.classList.toggle('govuk-character-count__message--disabled', !this.isOverThreshold());
|
999
|
-
this.$
|
1078
|
+
if (!this.$errorMessage) {
|
1079
|
+
this.$textarea.classList.toggle('govuk-textarea--error', isError);
|
1080
|
+
}
|
1000
1081
|
this.$visibleCountMessage.classList.toggle('govuk-error-message', isError);
|
1001
1082
|
this.$visibleCountMessage.classList.toggle('govuk-hint', !isError);
|
1002
1083
|
this.$visibleCountMessage.textContent = this.getCountMessage();
|
@@ -1105,8 +1186,8 @@ class CharacterCount extends GOVUKFrontendComponent {
|
|
1105
1186
|
*/
|
1106
1187
|
|
1107
1188
|
/**
|
1108
|
-
* @
|
1109
|
-
* @
|
1189
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1190
|
+
* @import { TranslationPluralForms } from '../../i18n.mjs'
|
1110
1191
|
*/
|
1111
1192
|
CharacterCount.moduleName = 'govuk-character-count';
|
1112
1193
|
CharacterCount.defaults = Object.freeze({
|
@@ -1164,7 +1245,7 @@ CharacterCount.schema = Object.freeze({
|
|
1164
1245
|
*
|
1165
1246
|
* @preserve
|
1166
1247
|
*/
|
1167
|
-
class Checkboxes extends
|
1248
|
+
class Checkboxes extends Component {
|
1168
1249
|
/**
|
1169
1250
|
* Checkboxes can be associated with a 'conditionally revealed' content block
|
1170
1251
|
* – for example, a checkbox for 'Phone' could reveal an additional form field
|
@@ -1177,27 +1258,18 @@ class Checkboxes extends GOVUKFrontendComponent {
|
|
1177
1258
|
* (for example if the user has navigated back), and set up event handlers to
|
1178
1259
|
* keep the reveal in sync with the checkbox state.
|
1179
1260
|
*
|
1180
|
-
* @param {Element | null} $
|
1261
|
+
* @param {Element | null} $root - HTML element to use for checkboxes
|
1181
1262
|
*/
|
1182
|
-
constructor($
|
1183
|
-
super();
|
1184
|
-
this.$module = void 0;
|
1263
|
+
constructor($root) {
|
1264
|
+
super($root);
|
1185
1265
|
this.$inputs = void 0;
|
1186
|
-
|
1187
|
-
throw new ElementError({
|
1188
|
-
componentName: 'Checkboxes',
|
1189
|
-
element: $module,
|
1190
|
-
identifier: 'Root element (`$module`)'
|
1191
|
-
});
|
1192
|
-
}
|
1193
|
-
const $inputs = $module.querySelectorAll('input[type="checkbox"]');
|
1266
|
+
const $inputs = this.$root.querySelectorAll('input[type="checkbox"]');
|
1194
1267
|
if (!$inputs.length) {
|
1195
1268
|
throw new ElementError({
|
1196
|
-
|
1269
|
+
component: Checkboxes,
|
1197
1270
|
identifier: 'Form inputs (`<input type="checkbox">`)'
|
1198
1271
|
});
|
1199
1272
|
}
|
1200
|
-
this.$module = $module;
|
1201
1273
|
this.$inputs = $inputs;
|
1202
1274
|
this.$inputs.forEach($input => {
|
1203
1275
|
const targetId = $input.getAttribute('data-aria-controls');
|
@@ -1206,7 +1278,7 @@ class Checkboxes extends GOVUKFrontendComponent {
|
|
1206
1278
|
}
|
1207
1279
|
if (!document.getElementById(targetId)) {
|
1208
1280
|
throw new ElementError({
|
1209
|
-
|
1281
|
+
component: Checkboxes,
|
1210
1282
|
identifier: `Conditional reveal (\`id="${targetId}"\`)`
|
1211
1283
|
});
|
1212
1284
|
}
|
@@ -1215,7 +1287,7 @@ class Checkboxes extends GOVUKFrontendComponent {
|
|
1215
1287
|
});
|
1216
1288
|
window.addEventListener('pageshow', () => this.syncAllConditionalReveals());
|
1217
1289
|
this.syncAllConditionalReveals();
|
1218
|
-
this.$
|
1290
|
+
this.$root.addEventListener('click', event => this.handleClick(event));
|
1219
1291
|
}
|
1220
1292
|
syncAllConditionalReveals() {
|
1221
1293
|
this.$inputs.forEach($input => this.syncConditionalRevealWithInputState($input));
|
@@ -1281,29 +1353,19 @@ Checkboxes.moduleName = 'govuk-checkboxes';
|
|
1281
1353
|
* configuration.
|
1282
1354
|
*
|
1283
1355
|
* @preserve
|
1356
|
+
* @augments ConfigurableComponent<ErrorSummaryConfig>
|
1284
1357
|
*/
|
1285
|
-
class ErrorSummary extends
|
1358
|
+
class ErrorSummary extends ConfigurableComponent {
|
1286
1359
|
/**
|
1287
|
-
* @param {Element | null} $
|
1360
|
+
* @param {Element | null} $root - HTML element to use for error summary
|
1288
1361
|
* @param {ErrorSummaryConfig} [config] - Error summary config
|
1289
1362
|
*/
|
1290
|
-
constructor($
|
1291
|
-
super();
|
1292
|
-
this.$module = void 0;
|
1293
|
-
this.config = void 0;
|
1294
|
-
if (!($module instanceof HTMLElement)) {
|
1295
|
-
throw new ElementError({
|
1296
|
-
componentName: 'Error summary',
|
1297
|
-
element: $module,
|
1298
|
-
identifier: 'Root element (`$module`)'
|
1299
|
-
});
|
1300
|
-
}
|
1301
|
-
this.$module = $module;
|
1302
|
-
this.config = mergeConfigs(ErrorSummary.defaults, config, normaliseDataset(ErrorSummary, $module.dataset));
|
1363
|
+
constructor($root, config = {}) {
|
1364
|
+
super($root, config);
|
1303
1365
|
if (!this.config.disableAutoFocus) {
|
1304
|
-
setFocus(this.$
|
1366
|
+
setFocus(this.$root);
|
1305
1367
|
}
|
1306
|
-
this.$
|
1368
|
+
this.$root.addEventListener('click', event => this.handleClick(event));
|
1307
1369
|
}
|
1308
1370
|
handleClick(event) {
|
1309
1371
|
const $target = event.target;
|
@@ -1366,7 +1428,7 @@ class ErrorSummary extends GOVUKFrontendComponent {
|
|
1366
1428
|
*/
|
1367
1429
|
|
1368
1430
|
/**
|
1369
|
-
* @
|
1431
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1370
1432
|
*/
|
1371
1433
|
ErrorSummary.moduleName = 'govuk-error-summary';
|
1372
1434
|
ErrorSummary.defaults = Object.freeze({
|
@@ -1384,16 +1446,15 @@ ErrorSummary.schema = Object.freeze({
|
|
1384
1446
|
* Exit this page component
|
1385
1447
|
*
|
1386
1448
|
* @preserve
|
1449
|
+
* @augments ConfigurableComponent<ExitThisPageConfig>
|
1387
1450
|
*/
|
1388
|
-
class ExitThisPage extends
|
1451
|
+
class ExitThisPage extends ConfigurableComponent {
|
1389
1452
|
/**
|
1390
|
-
* @param {Element | null} $
|
1453
|
+
* @param {Element | null} $root - HTML element that wraps the Exit This Page button
|
1391
1454
|
* @param {ExitThisPageConfig} [config] - Exit This Page config
|
1392
1455
|
*/
|
1393
|
-
constructor($
|
1394
|
-
super();
|
1395
|
-
this.$module = void 0;
|
1396
|
-
this.config = void 0;
|
1456
|
+
constructor($root, config = {}) {
|
1457
|
+
super($root, config);
|
1397
1458
|
this.i18n = void 0;
|
1398
1459
|
this.$button = void 0;
|
1399
1460
|
this.$skiplinkButton = null;
|
@@ -1405,25 +1466,16 @@ class ExitThisPage extends GOVUKFrontendComponent {
|
|
1405
1466
|
this.timeoutTime = 5000;
|
1406
1467
|
this.keypressTimeoutId = null;
|
1407
1468
|
this.timeoutMessageId = null;
|
1408
|
-
|
1409
|
-
throw new ElementError({
|
1410
|
-
componentName: 'Exit this page',
|
1411
|
-
element: $module,
|
1412
|
-
identifier: 'Root element (`$module`)'
|
1413
|
-
});
|
1414
|
-
}
|
1415
|
-
const $button = $module.querySelector('.govuk-exit-this-page__button');
|
1469
|
+
const $button = this.$root.querySelector('.govuk-exit-this-page__button');
|
1416
1470
|
if (!($button instanceof HTMLAnchorElement)) {
|
1417
1471
|
throw new ElementError({
|
1418
|
-
|
1472
|
+
component: ExitThisPage,
|
1419
1473
|
element: $button,
|
1420
1474
|
expectedType: 'HTMLAnchorElement',
|
1421
1475
|
identifier: 'Button (`.govuk-exit-this-page__button`)'
|
1422
1476
|
});
|
1423
1477
|
}
|
1424
|
-
this.config = mergeConfigs(ExitThisPage.defaults, config, normaliseDataset(ExitThisPage, $module.dataset));
|
1425
1478
|
this.i18n = new I18n(this.config.i18n);
|
1426
|
-
this.$module = $module;
|
1427
1479
|
this.$button = $button;
|
1428
1480
|
const $skiplinkButton = document.querySelector('.govuk-js-exit-this-page-skiplink');
|
1429
1481
|
if ($skiplinkButton instanceof HTMLAnchorElement) {
|
@@ -1442,7 +1494,7 @@ class ExitThisPage extends GOVUKFrontendComponent {
|
|
1442
1494
|
this.$updateSpan = document.createElement('span');
|
1443
1495
|
this.$updateSpan.setAttribute('role', 'status');
|
1444
1496
|
this.$updateSpan.className = 'govuk-visually-hidden';
|
1445
|
-
this.$
|
1497
|
+
this.$root.appendChild(this.$updateSpan);
|
1446
1498
|
}
|
1447
1499
|
initButtonClickHandler() {
|
1448
1500
|
this.$button.addEventListener('click', this.handleClick.bind(this));
|
@@ -1588,7 +1640,7 @@ class ExitThisPage extends GOVUKFrontendComponent {
|
|
1588
1640
|
*/
|
1589
1641
|
|
1590
1642
|
/**
|
1591
|
-
* @
|
1643
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1592
1644
|
*/
|
1593
1645
|
ExitThisPage.moduleName = 'govuk-exit-this-page';
|
1594
1646
|
ExitThisPage.defaults = Object.freeze({
|
@@ -1607,48 +1659,289 @@ ExitThisPage.schema = Object.freeze({
|
|
1607
1659
|
}
|
1608
1660
|
});
|
1609
1661
|
|
1662
|
+
/**
|
1663
|
+
* File upload component
|
1664
|
+
*
|
1665
|
+
* @preserve
|
1666
|
+
* @augments ConfigurableComponent<FileUploadConfig>
|
1667
|
+
*/
|
1668
|
+
class FileUpload extends ConfigurableComponent {
|
1669
|
+
/**
|
1670
|
+
* @param {Element | null} $root - File input element
|
1671
|
+
* @param {FileUploadConfig} [config] - File Upload config
|
1672
|
+
*/
|
1673
|
+
constructor($root, config = {}) {
|
1674
|
+
super($root, config);
|
1675
|
+
this.$input = void 0;
|
1676
|
+
this.$button = void 0;
|
1677
|
+
this.$status = void 0;
|
1678
|
+
this.i18n = void 0;
|
1679
|
+
this.id = void 0;
|
1680
|
+
this.$announcements = void 0;
|
1681
|
+
this.enteredAnotherElement = void 0;
|
1682
|
+
const $input = this.$root.querySelector('input');
|
1683
|
+
if ($input === null) {
|
1684
|
+
throw new ElementError({
|
1685
|
+
component: FileUpload,
|
1686
|
+
identifier: 'File inputs (`<input type="file">`)'
|
1687
|
+
});
|
1688
|
+
}
|
1689
|
+
if ($input.type !== 'file') {
|
1690
|
+
throw new ElementError(formatErrorMessage(FileUpload, 'File input (`<input type="file">`) attribute (`type`) is not `file`'));
|
1691
|
+
}
|
1692
|
+
this.$input = $input;
|
1693
|
+
this.$input.setAttribute('hidden', 'true');
|
1694
|
+
if (!this.$input.id) {
|
1695
|
+
throw new ElementError({
|
1696
|
+
component: FileUpload,
|
1697
|
+
identifier: 'File input (`<input type="file">`) attribute (`id`)'
|
1698
|
+
});
|
1699
|
+
}
|
1700
|
+
this.id = this.$input.id;
|
1701
|
+
this.i18n = new I18n(this.config.i18n, {
|
1702
|
+
locale: closestAttributeValue(this.$root, 'lang')
|
1703
|
+
});
|
1704
|
+
const $label = this.findLabel();
|
1705
|
+
if (!$label.id) {
|
1706
|
+
$label.id = `${this.id}-label`;
|
1707
|
+
}
|
1708
|
+
this.$input.id = `${this.id}-input`;
|
1709
|
+
const $button = document.createElement('button');
|
1710
|
+
$button.classList.add('govuk-file-upload-button');
|
1711
|
+
$button.type = 'button';
|
1712
|
+
$button.id = this.id;
|
1713
|
+
$button.classList.add('govuk-file-upload-button--empty');
|
1714
|
+
const ariaDescribedBy = this.$input.getAttribute('aria-describedby');
|
1715
|
+
if (ariaDescribedBy) {
|
1716
|
+
$button.setAttribute('aria-describedby', ariaDescribedBy);
|
1717
|
+
}
|
1718
|
+
const $status = document.createElement('span');
|
1719
|
+
$status.className = 'govuk-body govuk-file-upload-button__status';
|
1720
|
+
$status.setAttribute('aria-live', 'polite');
|
1721
|
+
$status.innerText = this.i18n.t('noFileChosen');
|
1722
|
+
$button.appendChild($status);
|
1723
|
+
const commaSpan = document.createElement('span');
|
1724
|
+
commaSpan.className = 'govuk-visually-hidden';
|
1725
|
+
commaSpan.innerText = ', ';
|
1726
|
+
commaSpan.id = `${this.id}-comma`;
|
1727
|
+
$button.appendChild(commaSpan);
|
1728
|
+
const containerSpan = document.createElement('span');
|
1729
|
+
containerSpan.className = 'govuk-file-upload-button__pseudo-button-container';
|
1730
|
+
const buttonSpan = document.createElement('span');
|
1731
|
+
buttonSpan.className = 'govuk-button govuk-button--secondary govuk-file-upload-button__pseudo-button';
|
1732
|
+
buttonSpan.innerText = this.i18n.t('chooseFilesButton');
|
1733
|
+
containerSpan.appendChild(buttonSpan);
|
1734
|
+
containerSpan.insertAdjacentText('beforeend', ' ');
|
1735
|
+
const instructionSpan = document.createElement('span');
|
1736
|
+
instructionSpan.className = 'govuk-body govuk-file-upload-button__instruction';
|
1737
|
+
instructionSpan.innerText = this.i18n.t('dropInstruction');
|
1738
|
+
containerSpan.appendChild(instructionSpan);
|
1739
|
+
$button.appendChild(containerSpan);
|
1740
|
+
$button.setAttribute('aria-labelledby', `${$label.id} ${commaSpan.id} ${$button.id}`);
|
1741
|
+
$button.addEventListener('click', this.onClick.bind(this));
|
1742
|
+
$button.addEventListener('dragover', event => {
|
1743
|
+
event.preventDefault();
|
1744
|
+
});
|
1745
|
+
this.$root.insertAdjacentElement('afterbegin', $button);
|
1746
|
+
this.$input.setAttribute('tabindex', '-1');
|
1747
|
+
this.$input.setAttribute('aria-hidden', 'true');
|
1748
|
+
this.$button = $button;
|
1749
|
+
this.$status = $status;
|
1750
|
+
this.$input.addEventListener('change', this.onChange.bind(this));
|
1751
|
+
this.updateDisabledState();
|
1752
|
+
this.observeDisabledState();
|
1753
|
+
this.$announcements = document.createElement('span');
|
1754
|
+
this.$announcements.classList.add('govuk-file-upload-announcements');
|
1755
|
+
this.$announcements.classList.add('govuk-visually-hidden');
|
1756
|
+
this.$announcements.setAttribute('aria-live', 'assertive');
|
1757
|
+
this.$root.insertAdjacentElement('afterend', this.$announcements);
|
1758
|
+
this.$button.addEventListener('drop', this.onDrop.bind(this));
|
1759
|
+
document.addEventListener('dragenter', this.updateDropzoneVisibility.bind(this));
|
1760
|
+
document.addEventListener('dragenter', () => {
|
1761
|
+
this.enteredAnotherElement = true;
|
1762
|
+
});
|
1763
|
+
document.addEventListener('dragleave', () => {
|
1764
|
+
if (!this.enteredAnotherElement && !this.$button.disabled) {
|
1765
|
+
this.hideDraggingState();
|
1766
|
+
this.$announcements.innerText = this.i18n.t('leftDropZone');
|
1767
|
+
}
|
1768
|
+
this.enteredAnotherElement = false;
|
1769
|
+
});
|
1770
|
+
}
|
1771
|
+
updateDropzoneVisibility(event) {
|
1772
|
+
if (this.$button.disabled) return;
|
1773
|
+
if (event.target instanceof Node) {
|
1774
|
+
if (this.$root.contains(event.target)) {
|
1775
|
+
if (event.dataTransfer && isContainingFiles(event.dataTransfer)) {
|
1776
|
+
if (!this.$button.classList.contains('govuk-file-upload-button--dragging')) {
|
1777
|
+
this.showDraggingState();
|
1778
|
+
this.$announcements.innerText = this.i18n.t('enteredDropZone');
|
1779
|
+
}
|
1780
|
+
}
|
1781
|
+
} else {
|
1782
|
+
if (this.$button.classList.contains('govuk-file-upload-button--dragging')) {
|
1783
|
+
this.hideDraggingState();
|
1784
|
+
this.$announcements.innerText = this.i18n.t('leftDropZone');
|
1785
|
+
}
|
1786
|
+
}
|
1787
|
+
}
|
1788
|
+
}
|
1789
|
+
showDraggingState() {
|
1790
|
+
this.$button.classList.add('govuk-file-upload-button--dragging');
|
1791
|
+
}
|
1792
|
+
hideDraggingState() {
|
1793
|
+
this.$button.classList.remove('govuk-file-upload-button--dragging');
|
1794
|
+
}
|
1795
|
+
onDrop(event) {
|
1796
|
+
event.preventDefault();
|
1797
|
+
if (event.dataTransfer && isContainingFiles(event.dataTransfer)) {
|
1798
|
+
this.$input.files = event.dataTransfer.files;
|
1799
|
+
this.$input.dispatchEvent(new CustomEvent('change'));
|
1800
|
+
this.hideDraggingState();
|
1801
|
+
}
|
1802
|
+
}
|
1803
|
+
onChange() {
|
1804
|
+
const fileCount = this.$input.files.length;
|
1805
|
+
if (fileCount === 0) {
|
1806
|
+
this.$status.innerText = this.i18n.t('noFileChosen');
|
1807
|
+
this.$button.classList.add('govuk-file-upload-button--empty');
|
1808
|
+
} else {
|
1809
|
+
if (fileCount === 1) {
|
1810
|
+
this.$status.innerText = this.$input.files[0].name;
|
1811
|
+
} else {
|
1812
|
+
this.$status.innerText = this.i18n.t('multipleFilesChosen', {
|
1813
|
+
count: fileCount
|
1814
|
+
});
|
1815
|
+
}
|
1816
|
+
this.$button.classList.remove('govuk-file-upload-button--empty');
|
1817
|
+
}
|
1818
|
+
}
|
1819
|
+
findLabel() {
|
1820
|
+
const $label = document.querySelector(`label[for="${this.$input.id}"]`);
|
1821
|
+
if (!$label) {
|
1822
|
+
throw new ElementError({
|
1823
|
+
component: FileUpload,
|
1824
|
+
identifier: `Field label (\`<label for=${this.$input.id}>\`)`
|
1825
|
+
});
|
1826
|
+
}
|
1827
|
+
return $label;
|
1828
|
+
}
|
1829
|
+
onClick() {
|
1830
|
+
this.$input.click();
|
1831
|
+
}
|
1832
|
+
observeDisabledState() {
|
1833
|
+
const observer = new MutationObserver(mutationList => {
|
1834
|
+
for (const mutation of mutationList) {
|
1835
|
+
if (mutation.type === 'attributes' && mutation.attributeName === 'disabled') {
|
1836
|
+
this.updateDisabledState();
|
1837
|
+
}
|
1838
|
+
}
|
1839
|
+
});
|
1840
|
+
observer.observe(this.$input, {
|
1841
|
+
attributes: true
|
1842
|
+
});
|
1843
|
+
}
|
1844
|
+
updateDisabledState() {
|
1845
|
+
this.$button.disabled = this.$input.disabled;
|
1846
|
+
this.$root.classList.toggle('govuk-drop-zone--disabled', this.$button.disabled);
|
1847
|
+
}
|
1848
|
+
}
|
1849
|
+
FileUpload.moduleName = 'govuk-file-upload';
|
1850
|
+
FileUpload.defaults = Object.freeze({
|
1851
|
+
i18n: {
|
1852
|
+
chooseFilesButton: 'Choose file',
|
1853
|
+
dropInstruction: 'or drop file',
|
1854
|
+
noFileChosen: 'No file chosen',
|
1855
|
+
multipleFilesChosen: {
|
1856
|
+
one: '%{count} file chosen',
|
1857
|
+
other: '%{count} files chosen'
|
1858
|
+
},
|
1859
|
+
enteredDropZone: 'Entered drop zone',
|
1860
|
+
leftDropZone: 'Left drop zone'
|
1861
|
+
}
|
1862
|
+
});
|
1863
|
+
FileUpload.schema = Object.freeze({
|
1864
|
+
properties: {
|
1865
|
+
i18n: {
|
1866
|
+
type: 'object'
|
1867
|
+
}
|
1868
|
+
}
|
1869
|
+
});
|
1870
|
+
function isContainingFiles(dataTransfer) {
|
1871
|
+
const hasNoTypesInfo = dataTransfer.types.length === 0;
|
1872
|
+
const isDraggingFiles = dataTransfer.types.some(type => type === 'Files');
|
1873
|
+
return hasNoTypesInfo || isDraggingFiles;
|
1874
|
+
}
|
1875
|
+
|
1876
|
+
/**
|
1877
|
+
* @typedef {HTMLInputElement & {files: FileList}} HTMLFileInputElement
|
1878
|
+
*/
|
1879
|
+
|
1880
|
+
/**
|
1881
|
+
* File upload config
|
1882
|
+
*
|
1883
|
+
* @see {@link FileUpload.defaults}
|
1884
|
+
* @typedef {object} FileUploadConfig
|
1885
|
+
* @property {FileUploadTranslations} [i18n=FileUpload.defaults.i18n] - File upload translations
|
1886
|
+
*/
|
1887
|
+
|
1888
|
+
/**
|
1889
|
+
* File upload translations
|
1890
|
+
*
|
1891
|
+
* @see {@link FileUpload.defaults.i18n}
|
1892
|
+
* @typedef {object} FileUploadTranslations
|
1893
|
+
*
|
1894
|
+
* Messages used by the component
|
1895
|
+
* @property {string} [chooseFile] - The text of the button that opens the file picker
|
1896
|
+
* @property {string} [dropInstruction] - The text informing users they can drop files
|
1897
|
+
* @property {TranslationPluralForms} [multipleFilesChosen] - The text displayed when multiple files
|
1898
|
+
* have been chosen by the user
|
1899
|
+
* @property {string} [noFileChosen] - The text to displayed when no file has been chosen by the user
|
1900
|
+
* @property {string} [enteredDropZone] - The text announced by assistive technology
|
1901
|
+
* when user drags files and enters the drop zone
|
1902
|
+
* @property {string} [leftDropZone] - The text announced by assistive technology
|
1903
|
+
* when user drags files and leaves the drop zone without dropping
|
1904
|
+
*/
|
1905
|
+
|
1906
|
+
/**
|
1907
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1908
|
+
* @import { TranslationPluralForms } from '../../i18n.mjs'
|
1909
|
+
*/
|
1910
|
+
|
1610
1911
|
/**
|
1611
1912
|
* Header component
|
1612
1913
|
*
|
1613
1914
|
* @preserve
|
1614
1915
|
*/
|
1615
|
-
class Header extends
|
1916
|
+
class Header extends Component {
|
1616
1917
|
/**
|
1617
1918
|
* Apply a matchMedia for desktop which will trigger a state sync if the
|
1618
1919
|
* browser viewport moves between states.
|
1619
1920
|
*
|
1620
|
-
* @param {Element | null} $
|
1921
|
+
* @param {Element | null} $root - HTML element to use for header
|
1621
1922
|
*/
|
1622
|
-
constructor($
|
1623
|
-
super();
|
1624
|
-
this.$module = void 0;
|
1923
|
+
constructor($root) {
|
1924
|
+
super($root);
|
1625
1925
|
this.$menuButton = void 0;
|
1626
1926
|
this.$menu = void 0;
|
1627
1927
|
this.menuIsOpen = false;
|
1628
1928
|
this.mql = null;
|
1629
|
-
|
1630
|
-
throw new ElementError({
|
1631
|
-
componentName: 'Header',
|
1632
|
-
element: $module,
|
1633
|
-
identifier: 'Root element (`$module`)'
|
1634
|
-
});
|
1635
|
-
}
|
1636
|
-
this.$module = $module;
|
1637
|
-
const $menuButton = $module.querySelector('.govuk-js-header-toggle');
|
1929
|
+
const $menuButton = this.$root.querySelector('.govuk-js-header-toggle');
|
1638
1930
|
if (!$menuButton) {
|
1639
1931
|
return this;
|
1640
1932
|
}
|
1933
|
+
this.$root.classList.add('govuk-header--with-js-navigation');
|
1641
1934
|
const menuId = $menuButton.getAttribute('aria-controls');
|
1642
1935
|
if (!menuId) {
|
1643
1936
|
throw new ElementError({
|
1644
|
-
|
1937
|
+
component: Header,
|
1645
1938
|
identifier: 'Navigation button (`<button class="govuk-js-header-toggle">`) attribute (`aria-controls`)'
|
1646
1939
|
});
|
1647
1940
|
}
|
1648
1941
|
const $menu = document.getElementById(menuId);
|
1649
1942
|
if (!$menu) {
|
1650
1943
|
throw new ElementError({
|
1651
|
-
|
1944
|
+
component: Header,
|
1652
1945
|
element: $menu,
|
1653
1946
|
identifier: `Navigation (\`<ul id="${menuId}">\`)`
|
1654
1947
|
});
|
@@ -1662,7 +1955,7 @@ class Header extends GOVUKFrontendComponent {
|
|
1662
1955
|
const breakpoint = getBreakpoint('desktop');
|
1663
1956
|
if (!breakpoint.value) {
|
1664
1957
|
throw new ElementError({
|
1665
|
-
|
1958
|
+
component: Header,
|
1666
1959
|
identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
|
1667
1960
|
});
|
1668
1961
|
}
|
@@ -1702,27 +1995,17 @@ Header.moduleName = 'govuk-header';
|
|
1702
1995
|
* Notification Banner component
|
1703
1996
|
*
|
1704
1997
|
* @preserve
|
1998
|
+
* @augments ConfigurableComponent<NotificationBannerConfig>
|
1705
1999
|
*/
|
1706
|
-
class NotificationBanner extends
|
2000
|
+
class NotificationBanner extends ConfigurableComponent {
|
1707
2001
|
/**
|
1708
|
-
* @param {Element | null} $
|
2002
|
+
* @param {Element | null} $root - HTML element to use for notification banner
|
1709
2003
|
* @param {NotificationBannerConfig} [config] - Notification banner config
|
1710
2004
|
*/
|
1711
|
-
constructor($
|
1712
|
-
super();
|
1713
|
-
this.$
|
1714
|
-
|
1715
|
-
if (!($module instanceof HTMLElement)) {
|
1716
|
-
throw new ElementError({
|
1717
|
-
componentName: 'Notification banner',
|
1718
|
-
element: $module,
|
1719
|
-
identifier: 'Root element (`$module`)'
|
1720
|
-
});
|
1721
|
-
}
|
1722
|
-
this.$module = $module;
|
1723
|
-
this.config = mergeConfigs(NotificationBanner.defaults, config, normaliseDataset(NotificationBanner, $module.dataset));
|
1724
|
-
if (this.$module.getAttribute('role') === 'alert' && !this.config.disableAutoFocus) {
|
1725
|
-
setFocus(this.$module);
|
2005
|
+
constructor($root, config = {}) {
|
2006
|
+
super($root, config);
|
2007
|
+
if (this.$root.getAttribute('role') === 'alert' && !this.config.disableAutoFocus) {
|
2008
|
+
setFocus(this.$root);
|
1726
2009
|
}
|
1727
2010
|
}
|
1728
2011
|
}
|
@@ -1738,7 +2021,7 @@ class NotificationBanner extends GOVUKFrontendComponent {
|
|
1738
2021
|
*/
|
1739
2022
|
|
1740
2023
|
/**
|
1741
|
-
* @
|
2024
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1742
2025
|
*/
|
1743
2026
|
NotificationBanner.moduleName = 'govuk-notification-banner';
|
1744
2027
|
NotificationBanner.defaults = Object.freeze({
|
@@ -1756,31 +2039,23 @@ NotificationBanner.schema = Object.freeze({
|
|
1756
2039
|
* Password input component
|
1757
2040
|
*
|
1758
2041
|
* @preserve
|
2042
|
+
* @augments ConfigurableComponent<PasswordInputConfig>
|
1759
2043
|
*/
|
1760
|
-
class PasswordInput extends
|
2044
|
+
class PasswordInput extends ConfigurableComponent {
|
1761
2045
|
/**
|
1762
|
-
* @param {Element | null} $
|
2046
|
+
* @param {Element | null} $root - HTML element to use for password input
|
1763
2047
|
* @param {PasswordInputConfig} [config] - Password input config
|
1764
2048
|
*/
|
1765
|
-
constructor($
|
1766
|
-
super();
|
1767
|
-
this.$module = void 0;
|
1768
|
-
this.config = void 0;
|
2049
|
+
constructor($root, config = {}) {
|
2050
|
+
super($root, config);
|
1769
2051
|
this.i18n = void 0;
|
1770
2052
|
this.$input = void 0;
|
1771
2053
|
this.$showHideButton = void 0;
|
1772
2054
|
this.$screenReaderStatusMessage = void 0;
|
1773
|
-
|
1774
|
-
throw new ElementError({
|
1775
|
-
componentName: 'Password input',
|
1776
|
-
element: $module,
|
1777
|
-
identifier: 'Root element (`$module`)'
|
1778
|
-
});
|
1779
|
-
}
|
1780
|
-
const $input = $module.querySelector('.govuk-js-password-input-input');
|
2055
|
+
const $input = this.$root.querySelector('.govuk-js-password-input-input');
|
1781
2056
|
if (!($input instanceof HTMLInputElement)) {
|
1782
2057
|
throw new ElementError({
|
1783
|
-
|
2058
|
+
component: PasswordInput,
|
1784
2059
|
element: $input,
|
1785
2060
|
expectedType: 'HTMLInputElement',
|
1786
2061
|
identifier: 'Form field (`.govuk-js-password-input-input`)'
|
@@ -1789,10 +2064,10 @@ class PasswordInput extends GOVUKFrontendComponent {
|
|
1789
2064
|
if ($input.type !== 'password') {
|
1790
2065
|
throw new ElementError('Password input: Form field (`.govuk-js-password-input-input`) must be of type `password`.');
|
1791
2066
|
}
|
1792
|
-
const $showHideButton =
|
2067
|
+
const $showHideButton = this.$root.querySelector('.govuk-js-password-input-toggle');
|
1793
2068
|
if (!($showHideButton instanceof HTMLButtonElement)) {
|
1794
2069
|
throw new ElementError({
|
1795
|
-
|
2070
|
+
component: PasswordInput,
|
1796
2071
|
element: $showHideButton,
|
1797
2072
|
expectedType: 'HTMLButtonElement',
|
1798
2073
|
identifier: 'Button (`.govuk-js-password-input-toggle`)'
|
@@ -1801,12 +2076,10 @@ class PasswordInput extends GOVUKFrontendComponent {
|
|
1801
2076
|
if ($showHideButton.type !== 'button') {
|
1802
2077
|
throw new ElementError('Password input: Button (`.govuk-js-password-input-toggle`) must be of type `button`.');
|
1803
2078
|
}
|
1804
|
-
this.$module = $module;
|
1805
2079
|
this.$input = $input;
|
1806
2080
|
this.$showHideButton = $showHideButton;
|
1807
|
-
this.config = mergeConfigs(PasswordInput.defaults, config, normaliseDataset(PasswordInput, $module.dataset));
|
1808
2081
|
this.i18n = new I18n(this.config.i18n, {
|
1809
|
-
locale: closestAttributeValue(
|
2082
|
+
locale: closestAttributeValue(this.$root, 'lang')
|
1810
2083
|
});
|
1811
2084
|
this.$showHideButton.removeAttribute('hidden');
|
1812
2085
|
const $screenReaderStatusMessage = document.createElement('div');
|
@@ -1884,8 +2157,7 @@ class PasswordInput extends GOVUKFrontendComponent {
|
|
1884
2157
|
*/
|
1885
2158
|
|
1886
2159
|
/**
|
1887
|
-
* @
|
1888
|
-
* @typedef {import('../../i18n.mjs').TranslationPluralForms} TranslationPluralForms
|
2160
|
+
* @import { Schema } from '../../common/configuration.mjs'
|
1889
2161
|
*/
|
1890
2162
|
PasswordInput.moduleName = 'govuk-password-input';
|
1891
2163
|
PasswordInput.defaults = Object.freeze({
|
@@ -1911,7 +2183,7 @@ PasswordInput.schema = Object.freeze({
|
|
1911
2183
|
*
|
1912
2184
|
* @preserve
|
1913
2185
|
*/
|
1914
|
-
class Radios extends
|
2186
|
+
class Radios extends Component {
|
1915
2187
|
/**
|
1916
2188
|
* Radios can be associated with a 'conditionally revealed' content block –
|
1917
2189
|
* for example, a radio for 'Phone' could reveal an additional form field for
|
@@ -1924,27 +2196,18 @@ class Radios extends GOVUKFrontendComponent {
|
|
1924
2196
|
* (for example if the user has navigated back), and set up event handlers to
|
1925
2197
|
* keep the reveal in sync with the radio state.
|
1926
2198
|
*
|
1927
|
-
* @param {Element | null} $
|
2199
|
+
* @param {Element | null} $root - HTML element to use for radios
|
1928
2200
|
*/
|
1929
|
-
constructor($
|
1930
|
-
super();
|
1931
|
-
this.$module = void 0;
|
2201
|
+
constructor($root) {
|
2202
|
+
super($root);
|
1932
2203
|
this.$inputs = void 0;
|
1933
|
-
|
1934
|
-
throw new ElementError({
|
1935
|
-
componentName: 'Radios',
|
1936
|
-
element: $module,
|
1937
|
-
identifier: 'Root element (`$module`)'
|
1938
|
-
});
|
1939
|
-
}
|
1940
|
-
const $inputs = $module.querySelectorAll('input[type="radio"]');
|
2204
|
+
const $inputs = this.$root.querySelectorAll('input[type="radio"]');
|
1941
2205
|
if (!$inputs.length) {
|
1942
2206
|
throw new ElementError({
|
1943
|
-
|
2207
|
+
component: Radios,
|
1944
2208
|
identifier: 'Form inputs (`<input type="radio">`)'
|
1945
2209
|
});
|
1946
2210
|
}
|
1947
|
-
this.$module = $module;
|
1948
2211
|
this.$inputs = $inputs;
|
1949
2212
|
this.$inputs.forEach($input => {
|
1950
2213
|
const targetId = $input.getAttribute('data-aria-controls');
|
@@ -1953,7 +2216,7 @@ class Radios extends GOVUKFrontendComponent {
|
|
1953
2216
|
}
|
1954
2217
|
if (!document.getElementById(targetId)) {
|
1955
2218
|
throw new ElementError({
|
1956
|
-
|
2219
|
+
component: Radios,
|
1957
2220
|
identifier: `Conditional reveal (\`id="${targetId}"\`)`
|
1958
2221
|
});
|
1959
2222
|
}
|
@@ -1962,7 +2225,7 @@ class Radios extends GOVUKFrontendComponent {
|
|
1962
2225
|
});
|
1963
2226
|
window.addEventListener('pageshow', () => this.syncAllConditionalReveals());
|
1964
2227
|
this.syncAllConditionalReveals();
|
1965
|
-
this.$
|
2228
|
+
this.$root.addEventListener('click', event => this.handleClick(event));
|
1966
2229
|
}
|
1967
2230
|
syncAllConditionalReveals() {
|
1968
2231
|
this.$inputs.forEach($input => this.syncConditionalRevealWithInputState($input));
|
@@ -1999,35 +2262,105 @@ class Radios extends GOVUKFrontendComponent {
|
|
1999
2262
|
Radios.moduleName = 'govuk-radios';
|
2000
2263
|
|
2001
2264
|
/**
|
2002
|
-
*
|
2265
|
+
* Service Navigation component
|
2003
2266
|
*
|
2004
2267
|
* @preserve
|
2005
2268
|
*/
|
2006
|
-
class
|
2269
|
+
class ServiceNavigation extends Component {
|
2007
2270
|
/**
|
2008
|
-
* @param {Element | null} $
|
2009
|
-
* @throws {ElementError} when $module is not set or the wrong type
|
2010
|
-
* @throws {ElementError} when $module.hash does not contain a hash
|
2011
|
-
* @throws {ElementError} when the linked element is missing or the wrong type
|
2271
|
+
* @param {Element | null} $root - HTML element to use for header
|
2012
2272
|
*/
|
2013
|
-
constructor($
|
2014
|
-
|
2015
|
-
|
2016
|
-
this.$
|
2017
|
-
|
2273
|
+
constructor($root) {
|
2274
|
+
super($root);
|
2275
|
+
this.$menuButton = void 0;
|
2276
|
+
this.$menu = void 0;
|
2277
|
+
this.menuIsOpen = false;
|
2278
|
+
this.mql = null;
|
2279
|
+
const $menuButton = this.$root.querySelector('.govuk-js-service-navigation-toggle');
|
2280
|
+
if (!$menuButton) {
|
2281
|
+
return this;
|
2282
|
+
}
|
2283
|
+
const menuId = $menuButton.getAttribute('aria-controls');
|
2284
|
+
if (!menuId) {
|
2018
2285
|
throw new ElementError({
|
2019
|
-
|
2020
|
-
|
2021
|
-
|
2022
|
-
|
2286
|
+
component: ServiceNavigation,
|
2287
|
+
identifier: 'Navigation button (`<button class="govuk-js-service-navigation-toggle">`) attribute (`aria-controls`)'
|
2288
|
+
});
|
2289
|
+
}
|
2290
|
+
const $menu = document.getElementById(menuId);
|
2291
|
+
if (!$menu) {
|
2292
|
+
throw new ElementError({
|
2293
|
+
component: ServiceNavigation,
|
2294
|
+
element: $menu,
|
2295
|
+
identifier: `Navigation (\`<ul id="${menuId}">\`)`
|
2296
|
+
});
|
2297
|
+
}
|
2298
|
+
this.$menu = $menu;
|
2299
|
+
this.$menuButton = $menuButton;
|
2300
|
+
this.setupResponsiveChecks();
|
2301
|
+
this.$menuButton.addEventListener('click', () => this.handleMenuButtonClick());
|
2302
|
+
}
|
2303
|
+
setupResponsiveChecks() {
|
2304
|
+
const breakpoint = getBreakpoint('tablet');
|
2305
|
+
if (!breakpoint.value) {
|
2306
|
+
throw new ElementError({
|
2307
|
+
component: ServiceNavigation,
|
2308
|
+
identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
|
2023
2309
|
});
|
2024
2310
|
}
|
2025
|
-
this
|
2026
|
-
|
2027
|
-
|
2311
|
+
this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`);
|
2312
|
+
if ('addEventListener' in this.mql) {
|
2313
|
+
this.mql.addEventListener('change', () => this.checkMode());
|
2314
|
+
} else {
|
2315
|
+
this.mql.addListener(() => this.checkMode());
|
2316
|
+
}
|
2317
|
+
this.checkMode();
|
2318
|
+
}
|
2319
|
+
checkMode() {
|
2320
|
+
if (!this.mql || !this.$menu || !this.$menuButton) {
|
2321
|
+
return;
|
2322
|
+
}
|
2323
|
+
if (this.mql.matches) {
|
2324
|
+
this.$menu.removeAttribute('hidden');
|
2325
|
+
this.$menuButton.setAttribute('hidden', '');
|
2326
|
+
} else {
|
2327
|
+
this.$menuButton.removeAttribute('hidden');
|
2328
|
+
this.$menuButton.setAttribute('aria-expanded', this.menuIsOpen.toString());
|
2329
|
+
if (this.menuIsOpen) {
|
2330
|
+
this.$menu.removeAttribute('hidden');
|
2331
|
+
} else {
|
2332
|
+
this.$menu.setAttribute('hidden', '');
|
2333
|
+
}
|
2334
|
+
}
|
2335
|
+
}
|
2336
|
+
handleMenuButtonClick() {
|
2337
|
+
this.menuIsOpen = !this.menuIsOpen;
|
2338
|
+
this.checkMode();
|
2339
|
+
}
|
2340
|
+
}
|
2341
|
+
ServiceNavigation.moduleName = 'govuk-service-navigation';
|
2342
|
+
|
2343
|
+
/**
|
2344
|
+
* Skip link component
|
2345
|
+
*
|
2346
|
+
* @preserve
|
2347
|
+
* @augments Component<HTMLAnchorElement>
|
2348
|
+
*/
|
2349
|
+
class SkipLink extends Component {
|
2350
|
+
/**
|
2351
|
+
* @param {Element | null} $root - HTML element to use for skip link
|
2352
|
+
* @throws {ElementError} when $root is not set or the wrong type
|
2353
|
+
* @throws {ElementError} when $root.hash does not contain a hash
|
2354
|
+
* @throws {ElementError} when the linked element is missing or the wrong type
|
2355
|
+
*/
|
2356
|
+
constructor($root) {
|
2357
|
+
var _this$$root$getAttrib;
|
2358
|
+
super($root);
|
2359
|
+
const hash = this.$root.hash;
|
2360
|
+
const href = (_this$$root$getAttrib = this.$root.getAttribute('href')) != null ? _this$$root$getAttrib : '';
|
2028
2361
|
let url;
|
2029
2362
|
try {
|
2030
|
-
url = new window.URL(this.$
|
2363
|
+
url = new window.URL(this.$root.href);
|
2031
2364
|
} catch (error) {
|
2032
2365
|
throw new ElementError(`Skip link: Target link (\`href="${href}"\`) is invalid`);
|
2033
2366
|
}
|
@@ -2041,12 +2374,12 @@ class SkipLink extends GOVUKFrontendComponent {
|
|
2041
2374
|
const $linkedElement = document.getElementById(linkedElementId);
|
2042
2375
|
if (!$linkedElement) {
|
2043
2376
|
throw new ElementError({
|
2044
|
-
|
2377
|
+
component: SkipLink,
|
2045
2378
|
element: $linkedElement,
|
2046
2379
|
identifier: `Target content (\`id="${linkedElementId}"\`)`
|
2047
2380
|
});
|
2048
2381
|
}
|
2049
|
-
this.$
|
2382
|
+
this.$root.addEventListener('click', () => setFocus($linkedElement, {
|
2050
2383
|
onBeforeFocus() {
|
2051
2384
|
$linkedElement.classList.add('govuk-skip-link-focused-element');
|
2052
2385
|
},
|
@@ -2056,6 +2389,7 @@ class SkipLink extends GOVUKFrontendComponent {
|
|
2056
2389
|
}));
|
2057
2390
|
}
|
2058
2391
|
}
|
2392
|
+
SkipLink.elementType = HTMLAnchorElement;
|
2059
2393
|
SkipLink.moduleName = 'govuk-skip-link';
|
2060
2394
|
|
2061
2395
|
/**
|
@@ -2063,13 +2397,12 @@ SkipLink.moduleName = 'govuk-skip-link';
|
|
2063
2397
|
*
|
2064
2398
|
* @preserve
|
2065
2399
|
*/
|
2066
|
-
class Tabs extends
|
2400
|
+
class Tabs extends Component {
|
2067
2401
|
/**
|
2068
|
-
* @param {Element | null} $
|
2402
|
+
* @param {Element | null} $root - HTML element to use for tabs
|
2069
2403
|
*/
|
2070
|
-
constructor($
|
2071
|
-
super();
|
2072
|
-
this.$module = void 0;
|
2404
|
+
constructor($root) {
|
2405
|
+
super($root);
|
2073
2406
|
this.$tabs = void 0;
|
2074
2407
|
this.$tabList = void 0;
|
2075
2408
|
this.$tabListItems = void 0;
|
@@ -2079,36 +2412,28 @@ class Tabs extends GOVUKFrontendComponent {
|
|
2079
2412
|
this.boundTabKeydown = void 0;
|
2080
2413
|
this.boundOnHashChange = void 0;
|
2081
2414
|
this.mql = null;
|
2082
|
-
|
2083
|
-
throw new ElementError({
|
2084
|
-
componentName: 'Tabs',
|
2085
|
-
element: $module,
|
2086
|
-
identifier: 'Root element (`$module`)'
|
2087
|
-
});
|
2088
|
-
}
|
2089
|
-
const $tabs = $module.querySelectorAll('a.govuk-tabs__tab');
|
2415
|
+
const $tabs = this.$root.querySelectorAll('a.govuk-tabs__tab');
|
2090
2416
|
if (!$tabs.length) {
|
2091
2417
|
throw new ElementError({
|
2092
|
-
|
2418
|
+
component: Tabs,
|
2093
2419
|
identifier: 'Links (`<a class="govuk-tabs__tab">`)'
|
2094
2420
|
});
|
2095
2421
|
}
|
2096
|
-
this.$module = $module;
|
2097
2422
|
this.$tabs = $tabs;
|
2098
2423
|
this.boundTabClick = this.onTabClick.bind(this);
|
2099
2424
|
this.boundTabKeydown = this.onTabKeydown.bind(this);
|
2100
2425
|
this.boundOnHashChange = this.onHashChange.bind(this);
|
2101
|
-
const $tabList = this.$
|
2102
|
-
const $tabListItems = this.$
|
2426
|
+
const $tabList = this.$root.querySelector('.govuk-tabs__list');
|
2427
|
+
const $tabListItems = this.$root.querySelectorAll('li.govuk-tabs__list-item');
|
2103
2428
|
if (!$tabList) {
|
2104
2429
|
throw new ElementError({
|
2105
|
-
|
2430
|
+
component: Tabs,
|
2106
2431
|
identifier: 'List (`<ul class="govuk-tabs__list">`)'
|
2107
2432
|
});
|
2108
2433
|
}
|
2109
2434
|
if (!$tabListItems.length) {
|
2110
2435
|
throw new ElementError({
|
2111
|
-
|
2436
|
+
component: Tabs,
|
2112
2437
|
identifier: 'List items (`<li class="govuk-tabs__list-item">`)'
|
2113
2438
|
});
|
2114
2439
|
}
|
@@ -2120,7 +2445,7 @@ class Tabs extends GOVUKFrontendComponent {
|
|
2120
2445
|
const breakpoint = getBreakpoint('tablet');
|
2121
2446
|
if (!breakpoint.value) {
|
2122
2447
|
throw new ElementError({
|
2123
|
-
|
2448
|
+
component: Tabs,
|
2124
2449
|
identifier: `CSS custom property (\`${breakpoint.property}\`) on pseudo-class \`:root\``
|
2125
2450
|
});
|
2126
2451
|
}
|
@@ -2195,7 +2520,7 @@ class Tabs extends GOVUKFrontendComponent {
|
|
2195
2520
|
this.showPanel($tab);
|
2196
2521
|
}
|
2197
2522
|
getTab(hash) {
|
2198
|
-
return this.$
|
2523
|
+
return this.$root.querySelector(`a.govuk-tabs__tab[href="${hash}"]`);
|
2199
2524
|
}
|
2200
2525
|
setAttributes($tab) {
|
2201
2526
|
const panelId = getFragmentFromUrl($tab.href);
|
@@ -2254,16 +2579,12 @@ class Tabs extends GOVUKFrontendComponent {
|
|
2254
2579
|
onTabKeydown(event) {
|
2255
2580
|
switch (event.key) {
|
2256
2581
|
case 'ArrowLeft':
|
2257
|
-
case 'ArrowUp':
|
2258
2582
|
case 'Left':
|
2259
|
-
case 'Up':
|
2260
2583
|
this.activatePreviousTab();
|
2261
2584
|
event.preventDefault();
|
2262
2585
|
break;
|
2263
2586
|
case 'ArrowRight':
|
2264
|
-
case 'ArrowDown':
|
2265
2587
|
case 'Right':
|
2266
|
-
case 'Down':
|
2267
2588
|
this.activateNextTab();
|
2268
2589
|
event.preventDefault();
|
2269
2590
|
break;
|
@@ -2310,7 +2631,7 @@ class Tabs extends GOVUKFrontendComponent {
|
|
2310
2631
|
if (!panelId) {
|
2311
2632
|
return null;
|
2312
2633
|
}
|
2313
|
-
return this.$
|
2634
|
+
return this.$root.querySelector(`#${panelId}`);
|
2314
2635
|
}
|
2315
2636
|
showPanel($tab) {
|
2316
2637
|
const $panel = this.getPanel($tab);
|
@@ -2343,7 +2664,7 @@ class Tabs extends GOVUKFrontendComponent {
|
|
2343
2664
|
$tab.setAttribute('tabindex', '0');
|
2344
2665
|
}
|
2345
2666
|
getCurrentTab() {
|
2346
|
-
return this.$
|
2667
|
+
return this.$root.querySelector('.govuk-tabs__list-item--selected a.govuk-tabs__tab');
|
2347
2668
|
}
|
2348
2669
|
}
|
2349
2670
|
Tabs.moduleName = 'govuk-tabs';
|
@@ -2354,19 +2675,28 @@ Tabs.moduleName = 'govuk-tabs';
|
|
2354
2675
|
* Use the `data-module` attributes to find, instantiate and init all of the
|
2355
2676
|
* components provided as part of GOV.UK Frontend.
|
2356
2677
|
*
|
2357
|
-
* @param {Config & { scope?: Element }} [config] - Config for all components (with optional scope)
|
2678
|
+
* @param {Config & { scope?: Element, onError?: OnErrorCallback<CompatibleClass> }} [config] - Config for all components (with optional scope)
|
2358
2679
|
*/
|
2359
2680
|
function initAll(config) {
|
2360
2681
|
var _config$scope;
|
2361
2682
|
config = typeof config !== 'undefined' ? config : {};
|
2362
2683
|
if (!isSupported()) {
|
2363
|
-
|
2684
|
+
if (config.onError) {
|
2685
|
+
config.onError(new SupportError(), {
|
2686
|
+
config
|
2687
|
+
});
|
2688
|
+
} else {
|
2689
|
+
console.log(new SupportError());
|
2690
|
+
}
|
2364
2691
|
return;
|
2365
2692
|
}
|
2366
|
-
const components = [[Accordion, config.accordion], [Button, config.button], [CharacterCount, config.characterCount], [Checkboxes], [ErrorSummary, config.errorSummary], [ExitThisPage, config.exitThisPage], [Header], [NotificationBanner, config.notificationBanner], [PasswordInput, config.passwordInput], [Radios], [SkipLink], [Tabs]];
|
2367
|
-
const
|
2693
|
+
const components = [[Accordion, config.accordion], [Button, config.button], [CharacterCount, config.characterCount], [Checkboxes], [ErrorSummary, config.errorSummary], [ExitThisPage, config.exitThisPage], [FileUpload, config.fileUpload], [Header], [NotificationBanner, config.notificationBanner], [PasswordInput, config.passwordInput], [Radios], [ServiceNavigation], [SkipLink], [Tabs]];
|
2694
|
+
const options = {
|
2695
|
+
scope: (_config$scope = config.scope) != null ? _config$scope : document,
|
2696
|
+
onError: config.onError
|
2697
|
+
};
|
2368
2698
|
components.forEach(([Component, config]) => {
|
2369
|
-
createAll(Component, config,
|
2699
|
+
createAll(Component, config, options);
|
2370
2700
|
});
|
2371
2701
|
}
|
2372
2702
|
|
@@ -2379,25 +2709,58 @@ function initAll(config) {
|
|
2379
2709
|
*
|
2380
2710
|
* Any component errors will be caught and logged to the console.
|
2381
2711
|
*
|
2382
|
-
* @template {CompatibleClass}
|
2383
|
-
* @param {
|
2384
|
-
* @param {
|
2385
|
-
* @param {Element|Document} [
|
2386
|
-
* @returns {Array<InstanceType<
|
2712
|
+
* @template {CompatibleClass} ComponentClass
|
2713
|
+
* @param {ComponentClass} Component - class of the component to create
|
2714
|
+
* @param {ComponentConfig<ComponentClass>} [config] - Config supplied to component
|
2715
|
+
* @param {OnErrorCallback<ComponentClass> | Element | Document | CreateAllOptions<ComponentClass> } [createAllOptions] - options for createAll including scope of the document to search within and callback function if error throw by component on init
|
2716
|
+
* @returns {Array<InstanceType<ComponentClass>>} - array of instantiated components
|
2387
2717
|
*/
|
2388
|
-
function createAll(Component, config,
|
2718
|
+
function createAll(Component, config, createAllOptions) {
|
2719
|
+
let $scope = document;
|
2720
|
+
let onError;
|
2721
|
+
if (typeof createAllOptions === 'object') {
|
2722
|
+
var _createAllOptions$sco;
|
2723
|
+
createAllOptions = createAllOptions;
|
2724
|
+
$scope = (_createAllOptions$sco = createAllOptions.scope) != null ? _createAllOptions$sco : $scope;
|
2725
|
+
onError = createAllOptions.onError;
|
2726
|
+
}
|
2727
|
+
if (typeof createAllOptions === 'function') {
|
2728
|
+
onError = createAllOptions;
|
2729
|
+
}
|
2730
|
+
if (createAllOptions instanceof HTMLElement) {
|
2731
|
+
$scope = createAllOptions;
|
2732
|
+
}
|
2389
2733
|
const $elements = $scope.querySelectorAll(`[data-module="${Component.moduleName}"]`);
|
2734
|
+
if (!isSupported()) {
|
2735
|
+
if (onError) {
|
2736
|
+
onError(new SupportError(), {
|
2737
|
+
component: Component,
|
2738
|
+
config
|
2739
|
+
});
|
2740
|
+
} else {
|
2741
|
+
console.log(new SupportError());
|
2742
|
+
}
|
2743
|
+
return [];
|
2744
|
+
}
|
2390
2745
|
return Array.from($elements).map($element => {
|
2391
2746
|
try {
|
2392
|
-
return
|
2747
|
+
return typeof config !== 'undefined' ? new Component($element, config) : new Component($element);
|
2393
2748
|
} catch (error) {
|
2394
|
-
|
2749
|
+
if (onError) {
|
2750
|
+
onError(error, {
|
2751
|
+
element: $element,
|
2752
|
+
component: Component,
|
2753
|
+
config
|
2754
|
+
});
|
2755
|
+
} else {
|
2756
|
+
console.log(error);
|
2757
|
+
}
|
2395
2758
|
return null;
|
2396
2759
|
}
|
2397
2760
|
}).filter(Boolean);
|
2398
2761
|
}
|
2399
2762
|
/**
|
2400
|
-
* @typedef {{new (...args: any[]): any,
|
2763
|
+
* @typedef {{new (...args: any[]): any, moduleName: string}} CompatibleClass
|
2401
2764
|
*/
|
2402
2765
|
/**
|
2403
2766
|
* Config for all components via `initAll()`
|
@@ -2408,28 +2771,50 @@ function createAll(Component, config, $scope = document) {
|
|
2408
2771
|
* @property {CharacterCountConfig} [characterCount] - Character Count config
|
2409
2772
|
* @property {ErrorSummaryConfig} [errorSummary] - Error Summary config
|
2410
2773
|
* @property {ExitThisPageConfig} [exitThisPage] - Exit This Page config
|
2774
|
+
* @property {FileUploadConfig} [fileUpload] - File Upload config
|
2411
2775
|
* @property {NotificationBannerConfig} [notificationBanner] - Notification Banner config
|
2412
2776
|
* @property {PasswordInputConfig} [passwordInput] - Password input config
|
2413
2777
|
*/
|
2414
2778
|
/**
|
2415
2779
|
* Config for individual components
|
2416
2780
|
*
|
2417
|
-
* @
|
2418
|
-
* @
|
2419
|
-
* @
|
2420
|
-
* @
|
2421
|
-
* @
|
2422
|
-
* @
|
2423
|
-
* @
|
2424
|
-
* @
|
2425
|
-
* @typedef {import('./components/notification-banner/notification-banner.mjs').NotificationBannerConfig} NotificationBannerConfig
|
2426
|
-
* @typedef {import('./components/password-input/password-input.mjs').PasswordInputConfig} PasswordInputConfig
|
2781
|
+
* @import { AccordionConfig } from './components/accordion/accordion.mjs'
|
2782
|
+
* @import { ButtonConfig } from './components/button/button.mjs'
|
2783
|
+
* @import { CharacterCountConfig } from './components/character-count/character-count.mjs'
|
2784
|
+
* @import { ErrorSummaryConfig } from './components/error-summary/error-summary.mjs'
|
2785
|
+
* @import { ExitThisPageConfig } from './components/exit-this-page/exit-this-page.mjs'
|
2786
|
+
* @import { NotificationBannerConfig } from './components/notification-banner/notification-banner.mjs'
|
2787
|
+
* @import { PasswordInputConfig } from './components/password-input/password-input.mjs'
|
2788
|
+
* @import { FileUploadConfig } from './components/file-upload/file-upload.mjs'
|
2427
2789
|
*/
|
2428
2790
|
/**
|
2429
2791
|
* Component config keys, e.g. `accordion` and `characterCount`
|
2430
2792
|
*
|
2431
2793
|
* @typedef {keyof Config} ConfigKey
|
2432
2794
|
*/
|
2795
|
+
/**
|
2796
|
+
* @template {CompatibleClass} ComponentClass
|
2797
|
+
* @typedef {ConstructorParameters<ComponentClass>[1]} ComponentConfig
|
2798
|
+
*/
|
2799
|
+
/**
|
2800
|
+
* @template {CompatibleClass} ComponentClass
|
2801
|
+
* @typedef {object} ErrorContext
|
2802
|
+
* @property {Element} [element] - Element used for component module initialisation
|
2803
|
+
* @property {ComponentClass} [component] - Class of component
|
2804
|
+
* @property {ComponentConfig<ComponentClass>} config - Config supplied to component
|
2805
|
+
*/
|
2806
|
+
/**
|
2807
|
+
* @template {CompatibleClass} ComponentClass
|
2808
|
+
* @callback OnErrorCallback
|
2809
|
+
* @param {unknown} error - Thrown error
|
2810
|
+
* @param {ErrorContext<ComponentClass>} context - Object containing the element, component class and configuration
|
2811
|
+
*/
|
2812
|
+
/**
|
2813
|
+
* @template {CompatibleClass} ComponentClass
|
2814
|
+
* @typedef {object} CreateAllOptions
|
2815
|
+
* @property {Element | Document} [scope] - scope of the document to search within
|
2816
|
+
* @property {OnErrorCallback<ComponentClass>} [onError] - callback function if error throw by component on init
|
2817
|
+
*/
|
2433
2818
|
|
2434
|
-
export { Accordion, Button, CharacterCount, Checkboxes, ErrorSummary, ExitThisPage, Header, NotificationBanner, PasswordInput, Radios, SkipLink, Tabs, createAll, initAll, version };
|
2819
|
+
export { Accordion, Button, CharacterCount, Checkboxes, Component, ConfigurableComponent, ErrorSummary, ExitThisPage, FileUpload, Header, NotificationBanner, PasswordInput, Radios, ServiceNavigation, SkipLink, Tabs, createAll, initAll, isSupported, version };
|
2435
2820
|
//# sourceMappingURL=all.bundle.mjs.map
|