@schukai/monster
Version:
Monster is a simple library for creating fast, robust and lightweight websites.
751 lines (709 loc) • 29.9 kB
JavaScript
/**
* Copyright © Volker Schukai and all contributing authors, {{copyRightYear}}. All rights reserved.
* Node module: @schukai/monster
*
* This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
* The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
*
* For those who do not wish to adhere to the AGPLv3, a commercial license is available.
* Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
* For more information about purchasing a commercial license, please contact Volker Schukai.
*
* SPDX-License-Identifier: AGPL-3.0
*/
import { instanceSymbol } from "../../constants.mjs";
import {
assembleMethodSymbol,
registerCustomElement,
} from "../../dom/customelement.mjs";
import { ATTRIBUTE_ROLE } from "../../dom/constants.mjs";
import { fireCustomEvent } from "../../dom/events.mjs";
import { getLocaleOfDocument } from "../../dom/locale.mjs";
import { isFunction, isObject, isString } from "../../types/is.mjs";
import { validateString } from "../../types/validate.mjs";
import { getGlobal } from "../../types/global.mjs";
import { PopperButton } from "./popper-button.mjs";
import { AccessibilityStyleSheet } from "../stylesheet/accessibility.mjs";
import "./form.mjs";
import "./field-set.mjs";
import "./password.mjs";
import "./message-state-button.mjs";
export { CredentialButton };
/**
* @private
* @type {symbol}
*/
const passwordElementSymbol = Symbol("passwordElement");
const passwordInputElementSymbol = Symbol("passwordInputElement");
const submitButtonElementSymbol = Symbol("submitButtonElement");
const formElementSymbol = Symbol("formElement");
const fieldSetElementSymbol = Symbol("fieldSetElement");
const inFlightSymbol = Symbol("inFlight");
const wiredSymbol = Symbol("wired");
const mutationObserverSymbol = Symbol("mutationObserver");
const formWiredSymbol = Symbol("formWired");
const passwordWiredSymbol = Symbol("passwordWired");
/**
* A password credential button control.
*
* @fragments /fragments/components/form/credential-button/
*
* @example /examples/components/form/credential-button-simple
*
* @since 3.91.0
* @copyright Volker Schukai
* @summary A popper button that opens a password change form.
* @fires monster-credential-submit
* @fires monster-credential-successful
* @fires monster-credential-failed
*/
class CredentialButton extends PopperButton {
/**
* This method is called by the `instanceof` operator.
* @return {symbol}
*/
static get [instanceSymbol]() {
return Symbol.for(
"@schukai/monster/components/form/credential-button@@instance",
);
}
/**
* To set the options via the HTML tag, the attribute `data-monster-options` must be used.
* @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
*
* The individual configuration values can be found in the table.
*
* @property {Object} templates Template definitions
* @property {string} templates.main Main template
* @property {Object} labels Label definitions
* @property {string} labels.button Button label
* @property {string} labels.title Field-set title
* @property {string} labels.password Password label
* @property {string} labels.description Description text
* @property {string} labels.submit Submit button label
* @property {string} labels.messageEmptyPassword Empty password message
* @property {string} labels.messageNotConfigured Not configured message
* @property {string} labels.messageSuccess Success message
* @property {string} labels.messageFailed Failure message
* @property {string} url API URL
* @property {Object} fetch Fetch options
* @property {string} fetch.redirect Fetch redirect option
* @property {string} fetch.method Fetch method
* @property {string} fetch.mode Fetch mode
* @property {string} fetch.credentials Fetch credentials
* @property {Object} fetch.headers Fetch headers
* @property {Object} mapping Mapping configuration
* @property {string} mapping.password Key for the password field in the payload
* @property {Object|Function} mapping.data Additional payload data or builder
* @property {Object} payload Payload configuration
* @property {string} payload.password Key for the password field in the payload
* @property {Object|Function} payload.data Additional payload data or builder
* @property {Object} placeholder Placeholder configuration
* @property {string} placeholder.password Password placeholder
* @property {Object} autocomplete Autocomplete configuration
* @property {string} autocomplete.password Password autocomplete
* @property {Object} classes Class definitions
* @property {Object} layout Layout configuration
* @property {string} layout.containerStyle Inline style for the container
* @property {string} layout.submitStyle Inline style for the submit button
* @property {number} timeoutForMessage Duration in milliseconds to show messages
* @property {number} timeoutForSuccess Duration in milliseconds for success state
* @property {Object} features Feature flags
* @property {boolean} features.closeOnSuccess Close popper on success
* @property {boolean} features.clearOnSuccess Clear password on success
*/
get defaults() {
const base = super.defaults;
const labels = getTranslations();
return Object.assign({}, base, {
templates: {
main: getTemplate(),
},
labels,
aria: Object.assign({}, base.aria, {
label: labels.button,
}),
layout: {
containerStyle: "width: 20rem;",
submitStyle: "margin-top: var(--monster-space-4);",
},
url: "",
fetch: {
redirect: "error",
method: "POST",
mode: "same-origin",
credentials: "same-origin",
headers: {
accept: "application/json",
"content-type": "application/json",
},
},
mapping: {},
payload: {
password: "password",
data: null,
},
placeholder: {
password: "",
},
autocomplete: {
password: "new-password",
},
timeoutForMessage: 3500,
timeoutForSuccess: 1200,
features: {
closeOnSuccess: true,
clearOnSuccess: true,
},
content: getContentTemplate(labels),
});
}
/**
* @return {CredentialButton}
*/
[assembleMethodSymbol]() {
super[assembleMethodSymbol]();
initControlReferences.call(this);
initEventHandler.call(this);
return this;
}
/**
* @return {string}
*/
static getTag() {
return "monster-credential-button";
}
/**
* @return {CSSStyleSheet[]}
*/
static getCSSStyleSheet() {
const styles = super.getCSSStyleSheet();
styles.push(AccessibilityStyleSheet);
return styles;
}
}
/**
* @private
* @return {CredentialButton}
*/
function initControlReferences() {
this[passwordElementSymbol] = this.shadowRoot.querySelector(
`[${ATTRIBUTE_ROLE}=password]`,
);
this[submitButtonElementSymbol] = this.shadowRoot.querySelector(
`[${ATTRIBUTE_ROLE}=submit-button]`,
);
this[formElementSymbol] = this.shadowRoot.querySelector(
`[${ATTRIBUTE_ROLE}=form]`,
);
this[fieldSetElementSymbol] = this.shadowRoot.querySelector(
`[${ATTRIBUTE_ROLE}=field-set]`,
);
return this;
}
/**
* @private
* @return {CredentialButton}
*/
function initEventHandler() {
const wireUp = () => {
initControlReferences.call(this);
if (this[formElementSymbol]) {
if (!this[formWiredSymbol]) {
this[formWiredSymbol] = true;
this[formElementSymbol].addEventListener("keydown", (event) => {
if (event.key === "Enter") {
this[submitButtonElementSymbol]?.click?.();
}
});
}
}
if (this[fieldSetElementSymbol]) {
const title = this.getOption("labels.title");
if (title !== undefined) {
this[fieldSetElementSymbol].setOption("labels.title", title);
}
}
if (this[passwordElementSymbol]) {
const input =
this[passwordElementSymbol]?.shadowRoot?.querySelector?.("input");
if (input instanceof HTMLElement) {
this[passwordInputElementSymbol] = input;
}
if (this[passwordInputElementSymbol] && !this[passwordWiredSymbol]) {
this[passwordWiredSymbol] = true;
const sync = () => {
const value = this[passwordElementSymbol]?.value ?? "";
this.value = value;
fireCustomEvent(this, "monster-change", { value });
this.dispatchEvent(
new Event("input", { bubbles: true, composed: true }),
);
};
this[passwordInputElementSymbol].addEventListener("input", sync);
this[passwordInputElementSymbol].addEventListener("change", () => {
this.dispatchEvent(
new Event("change", { bubbles: true, composed: true }),
);
});
}
}
if (!this[submitButtonElementSymbol] || this[wiredSymbol]) {
return;
}
this[wiredSymbol] = true;
this[submitButtonElementSymbol].setOption("actions.click", () => {
handleSubmit.call(this);
});
};
queueMicrotask(wireUp);
if (!this[mutationObserverSymbol]) {
this[mutationObserverSymbol] = new MutationObserver(() => {
wireUp();
});
this[mutationObserverSymbol].observe(this.shadowRoot, {
childList: true,
subtree: true,
});
}
return this;
}
/**
* @private
*/
function handleSubmit() {
if (this[inFlightSymbol]) {
return;
}
const password = this[passwordElementSymbol]?.value;
const timeout = this.getOption("timeoutForMessage");
if (!password) {
this[submitButtonElementSymbol].setMessage(
this.getOption("labels.messageEmptyPassword"),
);
this[submitButtonElementSymbol].showMessage(timeout);
this[submitButtonElementSymbol].setState("failed", timeout);
queueMicrotask(() => this[passwordElementSymbol]?.focus?.());
return;
}
this.value = password;
this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
let url = this.getOption("url") || this.getOption("fetch.url");
if (isString(url)) {
url = validateString(url);
}
const mapping = this.getOption("mapping");
const passwordField =
mapping?.password || this.getOption("payload.password") || "password";
let payload = { [passwordField]: password };
let extraPayload = mapping?.data ?? this.getOption("payload.data");
if (isFunction(extraPayload)) {
extraPayload = extraPayload({ password, element: this });
}
if (isObject(extraPayload)) {
payload = Object.assign({}, extraPayload, payload);
}
if (!url) {
const timeoutSuccess = this.getOption("timeoutForSuccess");
this[submitButtonElementSymbol].setState("successful", timeoutSuccess);
const successMessage = this.getOption("labels.messageSuccess");
if (successMessage) {
this[submitButtonElementSymbol].setMessage(successMessage);
this[submitButtonElementSymbol].showMessage(timeout);
}
if (this.getOption("features.clearOnSuccess")) {
this[passwordElementSymbol].value = "";
}
if (this.getOption("features.closeOnSuccess")) {
setTimeout(() => {
this.hideDialog();
}, timeoutSuccess);
}
fireCustomEvent(this, "monster-credential-successful", {
password,
payload,
url: null,
local: true,
});
return;
}
const fetchOptions = Object.assign({}, this.getOption("fetch"));
if (fetchOptions.url) {
delete fetchOptions.url;
}
fetchOptions.headers = isObject(fetchOptions.headers)
? Object.assign({}, fetchOptions.headers)
: {};
if (!fetchOptions.headers.accept) {
fetchOptions.headers.accept = "application/json";
}
if (!fetchOptions.headers["content-type"]) {
fetchOptions.headers["content-type"] = "application/json";
}
fetchOptions.body = JSON.stringify(payload);
this[inFlightSymbol] = true;
this[submitButtonElementSymbol].setState("activity");
fireCustomEvent(this, "monster-credential-submit", {
password,
payload,
url,
});
const global = getGlobal();
global
.fetch(url, fetchOptions)
.then((response) => {
if (!response.ok) {
return Promise.reject(response);
}
const timeoutSuccess = this.getOption("timeoutForSuccess");
this[submitButtonElementSymbol].setState("successful", timeoutSuccess);
const successMessage = this.getOption("labels.messageSuccess");
if (successMessage) {
this[submitButtonElementSymbol].setMessage(successMessage);
this[submitButtonElementSymbol].showMessage(timeout);
}
if (this.getOption("features.clearOnSuccess")) {
this[passwordElementSymbol].value = "";
}
if (this.getOption("features.closeOnSuccess")) {
setTimeout(() => {
this.hideDialog();
}, timeoutSuccess);
}
fireCustomEvent(this, "monster-credential-successful", {
password,
payload,
url,
response,
});
return response;
})
.catch((error) => {
const message = this.getOption("labels.messageFailed");
this[submitButtonElementSymbol].setMessage(message);
this[submitButtonElementSymbol].showMessage(timeout);
this[submitButtonElementSymbol].setState("failed", timeout);
fireCustomEvent(this, "monster-credential-failed", {
password,
payload,
url,
error,
});
})
.finally(() => {
this[inFlightSymbol] = false;
});
}
function getTranslations() {
const locale = getLocaleOfDocument();
switch (locale.language) {
case "de":
return {
button: "Passwort ändern",
title: "Passwort ändern",
password: "Neues Passwort",
description:
"Wählen Sie ein sicheres Passwort, damit Ihr Konto gut geschützt ist. Es könnte aus Groß- und Kleinbuchstaben, Zahlen und Sonderzeichen bestehen. Auch wäre es besser, kein leicht zu erratendes Wort wie einen Namen oder ein Geburtsdatum zu verwenden.",
submit: "Passwort ändern",
messageEmptyPassword: "Bitte geben Sie ein neues Passwort ein",
messageNotConfigured: "Dieses Formular ist nicht konfiguriert.",
messageSuccess: "Passwort wurde erfolgreich geändert.",
messageFailed:
"Etwas ist schief gelaufen, bitte versuchen Sie es später erneut",
};
case "es":
return {
button: "Cambiar contraseña",
title: "Cambiar contraseña",
password: "Nueva contraseña",
description:
"Elige una contraseña segura para proteger tu cuenta. Usa una combinación de mayúsculas, minúsculas, números y símbolos. Evita palabras fáciles de adivinar como nombres o fechas de nacimiento.",
submit: "Cambiar contraseña",
messageEmptyPassword: "Por favor ingrese una nueva contraseña",
messageNotConfigured: "Este formulario no está configurado.",
messageSuccess: "La contraseña se cambió correctamente.",
messageFailed: "Algo salió mal, por favor intenta de nuevo más tarde.",
};
case "zh":
return {
button: "更改密码",
title: "更改密码",
password: "新密码",
description:
"请选择一个安全密码以保护您的账户。建议包含大小写字母、数字和符号。避免使用容易猜到的词语,例如姓名或生日。",
submit: "更改密码",
messageEmptyPassword: "请输入新密码",
messageNotConfigured: "此表单尚未配置。",
messageSuccess: "密码修改成功。",
messageFailed: "出了点问题,请稍后再试。",
};
case "hi":
return {
button: "पासवर्ड बदलें",
title: "पासवर्ड बदलें",
password: "नया पासवर्ड",
description:
"अपने खाते की सुरक्षा के लिए एक मजबूत पासवर्ड चुनें। इसमें बड़े/छोटे अक्षर, संख्या और प्रतीक शामिल करें। नाम या जन्मतिथि जैसे आसानी से अनुमानित शब्दों से बचें।",
submit: "पासवर्ड बदलें",
messageEmptyPassword: "कृपया नया पासवर्ड दर्ज करें",
messageNotConfigured: "यह फॉर्म कॉन्फ़िगर नहीं है।",
messageSuccess: "पासवर्ड सफलतापूर्वक बदल दिया गया है।",
messageFailed: "कुछ गलत हुआ, कृपया बाद में फिर से प्रयास करें।",
};
case "bn":
return {
button: "পাসওয়ার্ড পরিবর্তন করুন",
title: "পাসওয়ার্ড পরিবর্তন করুন",
password: "নতুন পাসওয়ার্ড",
description:
"আপনার অ্যাকাউন্ট সুরক্ষিত রাখতে একটি শক্তিশালী পাসওয়ার্ড বেছে নিন। বড় ও ছোট হাতের অক্ষর, সংখ্যা এবং প্রতীক ব্যবহার করুন। নাম বা জন্মতারিখের মতো সহজে অনুমানযোগ্য শব্দ এড়িয়ে চলুন।",
submit: "পাসওয়ার্ড পরিবর্তন করুন",
messageEmptyPassword: "অনুগ্রহ করে একটি নতুন পাসওয়ার্ড লিখুন",
messageNotConfigured: "এই ফর্মটি কনফিগার করা হয়নি।",
messageSuccess: "পাসওয়ার্ড সফলভাবে পরিবর্তন হয়েছে।",
messageFailed: "কিছু ভুল হয়েছে, পরে আবার চেষ্টা করুন।",
};
case "pt":
return {
button: "Alterar senha",
title: "Alterar senha",
password: "Nova senha",
description:
"Escolha uma senha forte para manter sua conta segura. Use letras maiúsculas e minúsculas, números e símbolos. Evite palavras fáceis de adivinhar, como nomes ou datas de nascimento.",
submit: "Alterar senha",
messageEmptyPassword: "Por favor, insira uma nova senha",
messageNotConfigured: "Este formulário não está configurado.",
messageSuccess: "Senha alterada com sucesso.",
messageFailed: "Algo deu errado, tente novamente mais tarde.",
};
case "ru":
return {
button: "Изменить пароль",
title: "Изменить пароль",
password: "Новый пароль",
description:
"Выберите надежный пароль, чтобы защитить учетную запись. Используйте заглавные и строчные буквы, цифры и символы. Избегайте легко угадываемых слов, таких как имена или даты рождения.",
submit: "Изменить пароль",
messageEmptyPassword: "Пожалуйста, введите новый пароль",
messageNotConfigured: "Эта форма не настроена.",
messageSuccess: "Пароль успешно изменен.",
messageFailed: "Что-то пошло не так, попробуйте позже.",
};
case "ja":
return {
button: "パスワードを変更",
title: "パスワードを変更",
password: "新しいパスワード",
description:
"アカウントを安全に保つため、強力なパスワードを設定してください。大文字・小文字、数字、記号を組み合わせ、名前や誕生日など推測しやすい語は避けてください。",
submit: "パスワードを変更",
messageEmptyPassword: "新しいパスワードを入力してください",
messageNotConfigured: "このフォームは設定されていません。",
messageSuccess: "パスワードを変更しました。",
messageFailed: "問題が発生しました。後でもう一度お試しください。",
};
case "pa":
return {
button: "ਪਾਸਵਰਡ ਬਦਲੋ",
title: "ਪਾਸਵਰਡ ਬਦਲੋ",
password: "ਨਵਾਂ ਪਾਸਵਰਡ",
description:
"ਆਪਣਾ ਖਾਤਾ ਸੁਰੱਖਿਅਤ ਰੱਖਣ ਲਈ ਇੱਕ ਮਜ਼ਬੂਤ ਪਾਸਵਰਡ ਚੁਣੋ। ਵੱਡੇ/ਛੋਟੇ ਅੱਖਰ, ਅੰਕ ਅਤੇ ਚਿੰਨ੍ਹ ਵਰਤੋ। ਨਾਮ ਜਾਂ ਜਨਮ ਤਾਰੀਖ ਵਰਗੇ ਆਸਾਨੀ ਨਾਲ ਅਨੁਮਾਨਯੋਗ ਸ਼ਬਦਾਂ ਤੋਂ ਬਚੋ।",
submit: "ਪਾਸਵਰਡ ਬਦਲੋ",
messageEmptyPassword: "ਕਿਰਪਾ ਕਰਕੇ ਨਵਾਂ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ",
messageNotConfigured: "ਇਹ ਫਾਰਮ ਸੰਰਚਿਤ ਨਹੀਂ ਹੈ।",
messageSuccess: "ਪਾਸਵਰਡ ਸਫਲਤਾਪੂਰਵਕ ਬਦਲਿਆ ਗਿਆ।",
messageFailed: "ਕੁਝ ਗਲਤ ਹੋ ਗਿਆ, ਕਿਰਪਾ ਕਰਕੇ ਬਾਅਦ ਵਿੱਚ ਕੋਸ਼ਿਸ਼ ਕਰੋ।",
};
case "mr":
return {
button: "पासवर्ड बदला",
title: "पासवर्ड बदला",
password: "नवीन पासवर्ड",
description:
"आपले खाते सुरक्षित ठेवण्यासाठी मजबूत पासवर्ड निवडा. मोठी/लहान अक्षरे, संख्या आणि चिन्हे वापरा. नाव किंवा जन्मतारीखसारखे सहज अंदाज लावता येणारे शब्द टाळा.",
submit: "पासवर्ड बदला",
messageEmptyPassword: "कृपया नवीन पासवर्ड प्रविष्ट करा",
messageNotConfigured: "हा फॉर्म कॉन्फिगर केलेला नाही.",
messageSuccess: "पासवर्ड यशस्वीरित्या बदलला.",
messageFailed: "काहीतरी चूक झाली, कृपया नंतर पुन्हा प्रयत्न करा.",
};
case "fr":
return {
button: "Changer le mot de passe",
title: "Changer le mot de passe",
password: "Nouveau mot de passe",
description:
"Choisissez un mot de passe fort pour protéger votre compte. Utilisez des majuscules, minuscules, chiffres et symboles. Évitez les mots faciles à deviner comme des noms ou des dates de naissance.",
submit: "Changer le mot de passe",
messageEmptyPassword: "Veuillez saisir un nouveau mot de passe",
messageNotConfigured: "Ce formulaire n'est pas configuré.",
messageSuccess: "Mot de passe modifié avec succès.",
messageFailed:
"Une erreur s'est produite, veuillez réessayer plus tard.",
};
case "it":
return {
button: "Cambia password",
title: "Cambia password",
password: "Nuova password",
description:
"Scegli una password sicura per proteggere il tuo account. Usa lettere maiuscole e minuscole, numeri e simboli. Evita parole facili da indovinare come nomi o date di nascita.",
submit: "Cambia password",
messageEmptyPassword: "Per favore, inserisci una nuova password",
messageNotConfigured: "Questo modulo non è configurato.",
messageSuccess: "Password aggiornata con successo.",
messageFailed: "Qualcosa è andato storto, riprova più tardi.",
};
case "nl":
return {
button: "Wachtwoord wijzigen",
title: "Wachtwoord wijzigen",
password: "Nieuw wachtwoord",
description:
"Kies een sterk wachtwoord om je account te beveiligen. Gebruik hoofdletters, kleine letters, cijfers en symbolen. Vermijd gemakkelijk te raden woorden zoals namen of geboortedata.",
submit: "Wachtwoord wijzigen",
messageEmptyPassword: "Voer een nieuw wachtwoord in",
messageNotConfigured: "Dit formulier is niet geconfigureerd.",
messageSuccess: "Wachtwoord succesvol gewijzigd.",
messageFailed: "Er is iets misgegaan, probeer het later opnieuw.",
};
case "sv":
return {
button: "Ändra lösenord",
title: "Ändra lösenord",
password: "Nytt lösenord",
description:
"Välj ett starkt lösenord för att skydda ditt konto. Använd stora och små bokstäver, siffror och symboler. Undvik lättgissade ord som namn eller födelsedatum.",
submit: "Ändra lösenord",
messageEmptyPassword: "Ange ett nytt lösenord",
messageNotConfigured: "Det här formuläret är inte konfigurerat.",
messageSuccess: "Lösenordet har ändrats.",
messageFailed: "Något gick fel, försök igen senare.",
};
case "pl":
return {
button: "Zmień hasło",
title: "Zmień hasło",
password: "Nowe hasło",
description:
"Wybierz silne hasło, aby chronić swoje konto. Używaj wielkich i małych liter, cyfr oraz symboli. Unikaj łatwych do odgadnięcia słów, takich jak imiona czy daty urodzenia.",
submit: "Zmień hasło",
messageEmptyPassword: "Wpisz nowe hasło",
messageNotConfigured: "Ten formularz nie jest skonfigurowany.",
messageSuccess: "Hasło zostało zmienione.",
messageFailed: "Coś poszło nie tak, spróbuj ponownie później.",
};
case "da":
return {
button: "Skift adgangskode",
title: "Skift adgangskode",
password: "Ny adgangskode",
description:
"Vælg en stærk adgangskode for at beskytte din konto. Brug store og små bogstaver, tal og symboler. Undgå let gættelige ord som navne eller fødselsdatoer.",
submit: "Skift adgangskode",
messageEmptyPassword: "Indtast en ny adgangskode",
messageNotConfigured: "Denne formular er ikke konfigureret.",
messageSuccess: "Adgangskoden er ændret.",
messageFailed: "Noget gik galt, prøv igen senere.",
};
case "no":
return {
button: "Endre passord",
title: "Endre passord",
password: "Nytt passord",
description:
"Velg et sterkt passord for å beskytte kontoen din. Bruk store og små bokstaver, tall og symboler. Unngå lett gjettelige ord som navn eller fødselsdato.",
submit: "Endre passord",
messageEmptyPassword: "Skriv inn et nytt passord",
messageNotConfigured: "Dette skjemaet er ikke konfigurert.",
messageSuccess: "Passordet er endret.",
messageFailed: "Noe gikk galt, prøv igjen senere.",
};
case "cs":
return {
button: "Změnit heslo",
title: "Změnit heslo",
password: "Nové heslo",
description:
"Zvolte silné heslo, aby byl váš účet v bezpečí. Použijte velká a malá písmena, čísla a symboly. Vyhněte se snadno uhodnutelným slovům, jako jsou jména nebo data narození.",
submit: "Změnit heslo",
messageEmptyPassword: "Zadejte nové heslo",
messageNotConfigured: "Tento formulář není nakonfigurován.",
messageSuccess: "Heslo bylo úspěšně změněno.",
messageFailed: "Něco se pokazilo, zkuste to prosím později.",
};
default:
case "en":
return {
button: "Change password",
title: "Change password",
password: "New password",
description:
"Choose a strong password to keep your account secure. Use a mix of upper- and lowercase letters, numbers, and symbols. Avoid easy-to-guess words like names or birthdays.",
submit: "Change password",
messageEmptyPassword: "Please enter a new password",
messageNotConfigured: "This form is not configured.",
messageSuccess: "Password updated successfully.",
messageFailed: "Something went wrong. Please try again later.",
};
}
}
/**
* @private
* @return {string}
*/
function getContentTemplate(labels) {
const title = labels?.title ?? "";
const password = labels?.password ?? "";
const description = labels?.description ?? "";
const submit = labels?.submit ?? "";
// language=HTML
return `
<div data-monster-role="container" part="container"
data-monster-attributes="style path:layout.containerStyle">
<monster-form data-monster-role="form">
<monster-field-set
part="field-set"
data-monster-role="field-set"
data-monster-option-labels-title="${title}">
<label part="password-label">${password}</label>
<monster-password part="password"
data-monster-role="password"
data-monster-attributes="data-monster-option-placeholder path:placeholder.password,
data-monster-option-autocomplete path:autocomplete.password">
</monster-password>
<p part="description">${description}</p>
<monster-message-state-button
data-monster-role="submit-button"
part="submit-button"
data-monster-attributes="style path:layout.submitStyle">
${submit}
</monster-message-state-button>
</monster-field-set>
</monster-form>
</div>
`;
}
/**
* @private
* @return {string}
*/
function getTemplate() {
return `
<div data-monster-role="control" part="control">
<button data-monster-attributes="disabled path:disabled | if:true, class path:classes.button"
data-monster-role="button"
part="button"
aria-labelledby="monster-credential-button-aria-label"
data-monster-replace="path:labels.button"></button>
<div id="monster-credential-button-aria-label"
class="visually-hidden" data-monster-replace="path:aria.label">change password</div>
<div data-monster-role="popper" part="popper" tabindex="-1" class="monster-color-primary-1">
<div data-monster-role="arrow"></div>
<div part="content" class="flex" data-monster-replace="path:content"></div>
</div>
</div>
`;
}
registerCustomElement(CredentialButton);