UNPKG

govuk-frontend

Version:

GOV.UK Frontend contains the code you need to start building a user interface for government platforms and services.

167 lines (163 loc) 7.3 kB
import { isSupported } from './common/index.mjs'; import { Accordion } from './components/accordion/accordion.mjs'; import { Button } from './components/button/button.mjs'; import { CharacterCount } from './components/character-count/character-count.mjs'; import { Checkboxes } from './components/checkboxes/checkboxes.mjs'; import { ErrorSummary } from './components/error-summary/error-summary.mjs'; import { ExitThisPage } from './components/exit-this-page/exit-this-page.mjs'; import { Header } from './components/header/header.mjs'; import { NotificationBanner } from './components/notification-banner/notification-banner.mjs'; import { PasswordInput } from './components/password-input/password-input.mjs'; import { Radios } from './components/radios/radios.mjs'; import { ServiceNavigation } from './components/service-navigation/service-navigation.mjs'; import { SkipLink } from './components/skip-link/skip-link.mjs'; import { Tabs } from './components/tabs/tabs.mjs'; import { SupportError } from './errors/index.mjs'; /** * Initialise all components * * Use the `data-module` attributes to find, instantiate and init all of the * components provided as part of GOV.UK Frontend. * * @param {Config & { scope?: Element, onError?: OnErrorCallback<CompatibleClass> }} [config] - Config for all components (with optional scope) */ function initAll(config) { var _config$scope; config = typeof config !== 'undefined' ? config : {}; if (!isSupported()) { if (config.onError) { config.onError(new SupportError(), { config }); } else { console.log(new SupportError()); } return; } 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], [ServiceNavigation], [SkipLink], [Tabs]]; const options = { scope: (_config$scope = config.scope) != null ? _config$scope : document, onError: config.onError }; components.forEach(([Component, config]) => { createAll(Component, config, options); }); } /** * Create all instances of a specific component on the page * * Uses the `data-module` attribute to find all elements matching the specified * component on the page, creating instances of the component object for each * of them. * * Any component errors will be caught and logged to the console. * * @template {CompatibleClass} ComponentClass * @param {ComponentClass} Component - class of the component to create * @param {ComponentConfig<ComponentClass>} [config] - Config supplied to component * @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 * @returns {Array<InstanceType<ComponentClass>>} - array of instantiated components */ function createAll(Component, config, createAllOptions) { let $scope = document; let onError; if (typeof createAllOptions === 'object') { var _createAllOptions$sco; createAllOptions = createAllOptions; $scope = (_createAllOptions$sco = createAllOptions.scope) != null ? _createAllOptions$sco : $scope; onError = createAllOptions.onError; } if (typeof createAllOptions === 'function') { onError = createAllOptions; } if (createAllOptions instanceof HTMLElement) { $scope = createAllOptions; } const $elements = $scope.querySelectorAll(`[data-module="${Component.moduleName}"]`); if (!isSupported()) { if (onError) { onError(new SupportError(), { component: Component, config }); } else { console.log(new SupportError()); } return []; } return Array.from($elements).map($element => { try { return typeof config !== 'undefined' ? new Component($element, config) : new Component($element); } catch (error) { if (onError) { onError(error, { element: $element, component: Component, config }); } else { console.log(error); } return null; } }).filter(Boolean); } /** * @typedef {{new (...args: any[]): any, moduleName: string}} CompatibleClass */ /** * Config for all components via `initAll()` * * @typedef {object} Config * @property {AccordionConfig} [accordion] - Accordion config * @property {ButtonConfig} [button] - Button config * @property {CharacterCountConfig} [characterCount] - Character Count config * @property {ErrorSummaryConfig} [errorSummary] - Error Summary config * @property {ExitThisPageConfig} [exitThisPage] - Exit This Page config * @property {NotificationBannerConfig} [notificationBanner] - Notification Banner config * @property {PasswordInputConfig} [passwordInput] - Password input config */ /** * Config for individual components * * @typedef {import('./components/accordion/accordion.mjs').AccordionConfig} AccordionConfig * @typedef {import('./components/accordion/accordion.mjs').AccordionTranslations} AccordionTranslations * @typedef {import('./components/button/button.mjs').ButtonConfig} ButtonConfig * @typedef {import('./components/character-count/character-count.mjs').CharacterCountConfig} CharacterCountConfig * @typedef {import('./components/character-count/character-count.mjs').CharacterCountTranslations} CharacterCountTranslations * @typedef {import('./components/error-summary/error-summary.mjs').ErrorSummaryConfig} ErrorSummaryConfig * @typedef {import('./components/exit-this-page/exit-this-page.mjs').ExitThisPageConfig} ExitThisPageConfig * @typedef {import('./components/exit-this-page/exit-this-page.mjs').ExitThisPageTranslations} ExitThisPageTranslations * @typedef {import('./components/notification-banner/notification-banner.mjs').NotificationBannerConfig} NotificationBannerConfig * @typedef {import('./components/password-input/password-input.mjs').PasswordInputConfig} PasswordInputConfig */ /** * Component config keys, e.g. `accordion` and `characterCount` * * @typedef {keyof Config} ConfigKey */ /** * @template {CompatibleClass} ComponentClass * @typedef {ConstructorParameters<ComponentClass>[1]} ComponentConfig */ /** * @template {CompatibleClass} ComponentClass * @typedef {object} ErrorContext * @property {Element} [element] - Element used for component module initialisation * @property {ComponentClass} [component] - Class of component * @property {ComponentConfig<ComponentClass>} config - Config supplied to component */ /** * @template {CompatibleClass} ComponentClass * @callback OnErrorCallback * @param {unknown} error - Thrown error * @param {ErrorContext<ComponentClass>} context - Object containing the element, component class and configuration */ /** * @template {CompatibleClass} ComponentClass * @typedef {object} CreateAllOptions * @property {Element | Document} [scope] - scope of the document to search within * @property {OnErrorCallback<ComponentClass>} [onError] - callback function if error throw by component on init */ export { createAll, initAll }; //# sourceMappingURL=init.mjs.map