UNPKG

govuk-frontend

Version:

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

1 lines 12.1 kB
{"version":3,"file":"password-input.mjs","sources":["../../../../src/govuk/components/password-input/password-input.mjs"],"sourcesContent":["import { closestAttributeValue } from '../../common/closest-attribute-value.mjs'\nimport { ConfigurableComponent } from '../../common/configuration.mjs'\nimport { ElementError } from '../../errors/index.mjs'\nimport { I18n } from '../../i18n.mjs'\n\n/**\n * Password input component\n *\n * @preserve\n * @augments ConfigurableComponent<PasswordInputConfig>\n */\nexport class PasswordInput extends ConfigurableComponent {\n /** @private */\n i18n\n\n /**\n * @private\n * @type {HTMLInputElement}\n */\n $input\n\n /**\n * @private\n * @type {HTMLButtonElement}\n */\n $showHideButton\n\n /** @private */\n $screenReaderStatusMessage\n\n /**\n * @param {Element | null} $root - HTML element to use for password input\n * @param {PasswordInputConfig} [config] - Password input config\n */\n constructor($root, config = {}) {\n super($root, config)\n\n const $input = this.$root.querySelector('.govuk-js-password-input-input')\n if (!($input instanceof HTMLInputElement)) {\n throw new ElementError({\n component: PasswordInput,\n element: $input,\n expectedType: 'HTMLInputElement',\n identifier: 'Form field (`.govuk-js-password-input-input`)'\n })\n }\n\n if ($input.type !== 'password') {\n throw new ElementError(\n 'Password input: Form field (`.govuk-js-password-input-input`) must be of type `password`.'\n )\n }\n\n const $showHideButton = this.$root.querySelector(\n '.govuk-js-password-input-toggle'\n )\n if (!($showHideButton instanceof HTMLButtonElement)) {\n throw new ElementError({\n component: PasswordInput,\n element: $showHideButton,\n expectedType: 'HTMLButtonElement',\n identifier: 'Button (`.govuk-js-password-input-toggle`)'\n })\n }\n\n if ($showHideButton.type !== 'button') {\n throw new ElementError(\n 'Password input: Button (`.govuk-js-password-input-toggle`) must be of type `button`.'\n )\n }\n\n this.$input = $input\n this.$showHideButton = $showHideButton\n\n this.i18n = new I18n(this.config.i18n, {\n // Read the fallback if necessary rather than have it set in the defaults\n locale: closestAttributeValue(this.$root, 'lang')\n })\n\n // Show the toggle button element\n this.$showHideButton.removeAttribute('hidden')\n\n // Create and append the status text for screen readers.\n // This is injected between the input and button so that users get a sensible reading order if\n // moving through the page content linearly:\n // [password input] -> [your password is visible/hidden] -> [show/hide password]\n const $screenReaderStatusMessage = document.createElement('div')\n $screenReaderStatusMessage.className =\n 'govuk-password-input__sr-status govuk-visually-hidden'\n $screenReaderStatusMessage.setAttribute('aria-live', 'polite')\n this.$screenReaderStatusMessage = $screenReaderStatusMessage\n this.$input.insertAdjacentElement('afterend', $screenReaderStatusMessage)\n\n // Bind toggle button\n this.$showHideButton.addEventListener('click', this.toggle.bind(this))\n\n // Bind event to revert the password visibility to hidden\n if (this.$input.form) {\n this.$input.form.addEventListener('submit', () => this.hide())\n }\n\n // If the page is restored from bfcache and the password is visible, hide it again\n window.addEventListener('pageshow', (event) => {\n if (event.persisted && this.$input.type !== 'password') {\n this.hide()\n }\n })\n\n // Default the component to having the password hidden.\n this.hide()\n }\n\n /**\n * Toggle the visibility of the password input\n *\n * @private\n * @param {MouseEvent} event - Click event\n */\n toggle(event) {\n event.preventDefault()\n\n // If on this click, the field is type=\"password\", show the value\n if (this.$input.type === 'password') {\n this.show()\n return\n }\n\n // Otherwise, hide it\n // Being defensive - hiding should always be the default\n this.hide()\n }\n\n /**\n * Show the password input value in plain text.\n *\n * @private\n */\n show() {\n this.setType('text')\n }\n\n /**\n * Hide the password input value.\n *\n * @private\n */\n hide() {\n this.setType('password')\n }\n\n /**\n * Set the password input type\n *\n * @param {'text' | 'password'} type - Input type\n * @private\n */\n setType(type) {\n if (type === this.$input.type) {\n return\n }\n\n // Update input type\n this.$input.setAttribute('type', type)\n\n const isHidden = type === 'password'\n const prefixButton = isHidden ? 'show' : 'hide'\n const prefixStatus = isHidden ? 'passwordHidden' : 'passwordShown'\n\n // Update button text\n this.$showHideButton.innerText = this.i18n.t(`${prefixButton}Password`)\n\n // Update button aria-label\n this.$showHideButton.setAttribute(\n 'aria-label',\n this.i18n.t(`${prefixButton}PasswordAriaLabel`)\n )\n\n // Update status change text\n this.$screenReaderStatusMessage.innerText = this.i18n.t(\n `${prefixStatus}Announcement`\n )\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-password-input'\n\n /**\n * Password input default config\n *\n * @see {@link PasswordInputConfig}\n * @constant\n * @default\n * @type {PasswordInputConfig}\n */\n static defaults = Object.freeze({\n i18n: {\n showPassword: 'Show',\n hidePassword: 'Hide',\n showPasswordAriaLabel: 'Show password',\n hidePasswordAriaLabel: 'Hide password',\n passwordShownAnnouncement: 'Your password is visible',\n passwordHiddenAnnouncement: 'Your password is hidden'\n }\n })\n\n /**\n * Password input config schema\n *\n * @constant\n * @satisfies {Schema<PasswordInputConfig>}\n */\n static schema = Object.freeze({\n properties: {\n i18n: { type: 'object' }\n }\n })\n}\n\n/**\n * Password input config\n *\n * @typedef {object} PasswordInputConfig\n * @property {PasswordInputTranslations} [i18n=PasswordInput.defaults.i18n] - Password input translations\n */\n\n/**\n * Password input translations\n *\n * @see {@link PasswordInput.defaults.i18n}\n * @typedef {object} PasswordInputTranslations\n *\n * Messages displayed to the user indicating the state of the show/hide toggle.\n * @property {string} [showPassword] - Visible text of the button when the\n * password is currently hidden. Plain text only.\n * @property {string} [hidePassword] - Visible text of the button when the\n * password is currently visible. Plain text only.\n * @property {string} [showPasswordAriaLabel] - aria-label of the button when\n * the password is currently hidden. Plain text only.\n * @property {string} [hidePasswordAriaLabel] - aria-label of the button when\n * the password is currently visible. Plain text only.\n * @property {string} [passwordShownAnnouncement] - Screen reader\n * announcement to make when the password has just become visible.\n * Plain text only.\n * @property {string} [passwordHiddenAnnouncement] - Screen reader\n * announcement to make when the password has just been hidden.\n * Plain text only.\n */\n\n/**\n * @import { Schema } from '../../common/configuration.mjs'\n */\n"],"names":["PasswordInput","ConfigurableComponent","constructor","$root","config","i18n","$input","$showHideButton","$screenReaderStatusMessage","querySelector","HTMLInputElement","ElementError","component","element","expectedType","identifier","type","HTMLButtonElement","I18n","locale","closestAttributeValue","removeAttribute","document","createElement","className","setAttribute","insertAdjacentElement","addEventListener","toggle","bind","form","hide","window","event","persisted","preventDefault","show","setType","isHidden","prefixButton","prefixStatus","innerText","t","moduleName","defaults","Object","freeze","showPassword","hidePassword","showPasswordAriaLabel","hidePasswordAriaLabel","passwordShownAnnouncement","passwordHiddenAnnouncement","schema","properties"],"mappings":";;;;;AAKA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMA,aAAa,SAASC,qBAAqB,CAAC;AAmBvD;AACF;AACA;AACA;AACEC,EAAAA,WAAWA,CAACC,KAAK,EAAEC,MAAM,GAAG,EAAE,EAAE;AAC9B,IAAA,KAAK,CAACD,KAAK,EAAEC,MAAM,CAAC;AAAA,IAAA,IAAA,CAtBtBC,IAAI,GAAA,MAAA;AAAA,IAAA,IAAA,CAMJC,MAAM,GAAA,MAAA;AAAA,IAAA,IAAA,CAMNC,eAAe,GAAA,MAAA;AAAA,IAAA,IAAA,CAGfC,0BAA0B,GAAA,MAAA;IASxB,MAAMF,MAAM,GAAG,IAAI,CAACH,KAAK,CAACM,aAAa,CAAC,gCAAgC,CAAC;AACzE,IAAA,IAAI,EAAEH,MAAM,YAAYI,gBAAgB,CAAC,EAAE;MACzC,MAAM,IAAIC,YAAY,CAAC;AACrBC,QAAAA,SAAS,EAAEZ,aAAa;AACxBa,QAAAA,OAAO,EAAEP,MAAM;AACfQ,QAAAA,YAAY,EAAE,kBAAkB;AAChCC,QAAAA,UAAU,EAAE;AACd,OAAC,CAAC;AACJ,IAAA;AAEA,IAAA,IAAIT,MAAM,CAACU,IAAI,KAAK,UAAU,EAAE;AAC9B,MAAA,MAAM,IAAIL,YAAY,CACpB,2FACF,CAAC;AACH,IAAA;IAEA,MAAMJ,eAAe,GAAG,IAAI,CAACJ,KAAK,CAACM,aAAa,CAC9C,iCACF,CAAC;AACD,IAAA,IAAI,EAAEF,eAAe,YAAYU,iBAAiB,CAAC,EAAE;MACnD,MAAM,IAAIN,YAAY,CAAC;AACrBC,QAAAA,SAAS,EAAEZ,aAAa;AACxBa,QAAAA,OAAO,EAAEN,eAAe;AACxBO,QAAAA,YAAY,EAAE,mBAAmB;AACjCC,QAAAA,UAAU,EAAE;AACd,OAAC,CAAC;AACJ,IAAA;AAEA,IAAA,IAAIR,eAAe,CAACS,IAAI,KAAK,QAAQ,EAAE;AACrC,MAAA,MAAM,IAAIL,YAAY,CACpB,sFACF,CAAC;AACH,IAAA;IAEA,IAAI,CAACL,MAAM,GAAGA,MAAM;IACpB,IAAI,CAACC,eAAe,GAAGA,eAAe;IAEtC,IAAI,CAACF,IAAI,GAAG,IAAIa,IAAI,CAAC,IAAI,CAACd,MAAM,CAACC,IAAI,EAAE;AAErCc,MAAAA,MAAM,EAAEC,qBAAqB,CAAC,IAAI,CAACjB,KAAK,EAAE,MAAM;AAClD,KAAC,CAAC;AAGF,IAAA,IAAI,CAACI,eAAe,CAACc,eAAe,CAAC,QAAQ,CAAC;AAM9C,IAAA,MAAMb,0BAA0B,GAAGc,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;IAChEf,0BAA0B,CAACgB,SAAS,GAClC,uDAAuD;AACzDhB,IAAAA,0BAA0B,CAACiB,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC;IAC9D,IAAI,CAACjB,0BAA0B,GAAGA,0BAA0B;IAC5D,IAAI,CAACF,MAAM,CAACoB,qBAAqB,CAAC,UAAU,EAAElB,0BAA0B,CAAC;AAGzE,IAAA,IAAI,CAACD,eAAe,CAACoB,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAACC,MAAM,CAACC,IAAI,CAAC,IAAI,CAAC,CAAC;AAGtE,IAAA,IAAI,IAAI,CAACvB,MAAM,CAACwB,IAAI,EAAE;AACpB,MAAA,IAAI,CAACxB,MAAM,CAACwB,IAAI,CAACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,IAAI,CAACI,IAAI,EAAE,CAAC;AAChE,IAAA;AAGAC,IAAAA,MAAM,CAACL,gBAAgB,CAAC,UAAU,EAAGM,KAAK,IAAK;MAC7C,IAAIA,KAAK,CAACC,SAAS,IAAI,IAAI,CAAC5B,MAAM,CAACU,IAAI,KAAK,UAAU,EAAE;QACtD,IAAI,CAACe,IAAI,EAAE;AACb,MAAA;AACF,IAAA,CAAC,CAAC;IAGF,IAAI,CAACA,IAAI,EAAE;AACb,EAAA;EAQAH,MAAMA,CAACK,KAAK,EAAE;IACZA,KAAK,CAACE,cAAc,EAAE;AAGtB,IAAA,IAAI,IAAI,CAAC7B,MAAM,CAACU,IAAI,KAAK,UAAU,EAAE;MACnC,IAAI,CAACoB,IAAI,EAAE;AACX,MAAA;AACF,IAAA;IAIA,IAAI,CAACL,IAAI,EAAE;AACb,EAAA;AAOAK,EAAAA,IAAIA,GAAG;AACL,IAAA,IAAI,CAACC,OAAO,CAAC,MAAM,CAAC;AACtB,EAAA;AAOAN,EAAAA,IAAIA,GAAG;AACL,IAAA,IAAI,CAACM,OAAO,CAAC,UAAU,CAAC;AAC1B,EAAA;EAQAA,OAAOA,CAACrB,IAAI,EAAE;AACZ,IAAA,IAAIA,IAAI,KAAK,IAAI,CAACV,MAAM,CAACU,IAAI,EAAE;AAC7B,MAAA;AACF,IAAA;IAGA,IAAI,CAACV,MAAM,CAACmB,YAAY,CAAC,MAAM,EAAET,IAAI,CAAC;AAEtC,IAAA,MAAMsB,QAAQ,GAAGtB,IAAI,KAAK,UAAU;AACpC,IAAA,MAAMuB,YAAY,GAAGD,QAAQ,GAAG,MAAM,GAAG,MAAM;AAC/C,IAAA,MAAME,YAAY,GAAGF,QAAQ,GAAG,gBAAgB,GAAG,eAAe;AAGlE,IAAA,IAAI,CAAC/B,eAAe,CAACkC,SAAS,GAAG,IAAI,CAACpC,IAAI,CAACqC,CAAC,CAAC,CAAA,EAAGH,YAAY,UAAU,CAAC;AAGvE,IAAA,IAAI,CAAChC,eAAe,CAACkB,YAAY,CAC/B,YAAY,EACZ,IAAI,CAACpB,IAAI,CAACqC,CAAC,CAAC,GAAGH,YAAY,CAAA,iBAAA,CAAmB,CAChD,CAAC;AAGD,IAAA,IAAI,CAAC/B,0BAA0B,CAACiC,SAAS,GAAG,IAAI,CAACpC,IAAI,CAACqC,CAAC,CACrD,CAAA,EAAGF,YAAY,cACjB,CAAC;AACH,EAAA;AAqCF;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AAjPaxC,aAAa,CA+KjB2C,UAAU,GAAG,sBAAsB;AA/K/B3C,aAAa,CAyLjB4C,QAAQ,GAAGC,MAAM,CAACC,MAAM,CAAC;AAC9BzC,EAAAA,IAAI,EAAE;AACJ0C,IAAAA,YAAY,EAAE,MAAM;AACpBC,IAAAA,YAAY,EAAE,MAAM;AACpBC,IAAAA,qBAAqB,EAAE,eAAe;AACtCC,IAAAA,qBAAqB,EAAE,eAAe;AACtCC,IAAAA,yBAAyB,EAAE,0BAA0B;AACrDC,IAAAA,0BAA0B,EAAE;AAC9B;AACF,CAAC,CAAC;AAlMSpD,aAAa,CA0MjBqD,MAAM,GAAGR,MAAM,CAACC,MAAM,CAAC;AAC5BQ,EAAAA,UAAU,EAAE;AACVjD,IAAAA,IAAI,EAAE;AAAEW,MAAAA,IAAI,EAAE;AAAS;AACzB;AACF,CAAC,CAAC;;;;"}