From 3142e1a8f1b7137de7dea9f2fa0041c83bc2a4b5 Mon Sep 17 00:00:00 2001 From: Felix Evers Date: Wed, 28 Jan 2026 21:45:47 +0100 Subject: [PATCH 1/2] implement remaining views --- .gitignore | 1 + .storybook/preview.ts | 18 +- email/html/email-update-confirmation.ftl | 9 + email/html/email-verification-with-code.ftl | 7 + email/html/email-verification.ftl | 10 + email/html/event-login_error.ftl | 9 + email/html/event-update_password.ftl | 9 + email/html/executeActions.ftl | 16 + email/html/identity-provider-link.ftl | 9 + email/html/org-invite.ftl | 9 + email/html/password-reset.ftl | 10 + email/html/template.ftl | 178 ++++ index.html | 3 +- locales/de.arb | 252 ++++++ locales/en.arb | 252 ++++++ package-lock.json | 788 +++++++++++------- package.json | 7 +- public/favicon.ico | Bin 0 -> 2922 bytes src/.gitignore | 69 ++ src/i18n/translations.ts | 193 ++++- src/index.css | 14 + src/login/KcPage.tsx | 105 +++ src/login/components/Branding.tsx | 12 + src/login/components/Footer.tsx | 40 + src/login/components/LanguageSwitcher.tsx | 50 ++ src/login/components/PageLayout.tsx | 44 + src/login/components/RealmChip.tsx | 14 +- src/login/components/ThemeSwitcher.tsx | 22 + src/login/pages/Code.tsx | 85 ++ src/login/pages/DeleteAccountConfirm.tsx | 41 + src/login/pages/DeleteCredential.tsx | 41 + src/login/pages/Error.tsx | 69 ++ src/login/pages/ForgotPassword.tsx | 74 +- src/login/pages/FrontchannelLogout.tsx | 49 ++ src/login/pages/IdpReviewUserProfile.tsx | 113 +++ src/login/pages/Info.tsx | 71 ++ src/login/pages/LinkIdpAction.tsx | 46 + src/login/pages/Login.tsx | 82 +- src/login/pages/LoginConfigTotp.tsx | 96 +++ src/login/pages/LoginIdpLinkConfirm.tsx | 41 + .../pages/LoginIdpLinkConfirmOverride.tsx | 41 + src/login/pages/LoginIdpLinkEmail.tsx | 87 ++ .../pages/LoginOauth2DeviceVerifyUserCode.tsx | 90 ++ src/login/pages/LoginOauthGrant.tsx | 55 ++ src/login/pages/LoginOtp.tsx | 88 ++ src/login/pages/LoginPageExpired.tsx | 42 + .../LoginPasskeysConditionalAuthenticate.tsx | 49 ++ src/login/pages/LoginPassword.tsx | 87 ++ .../pages/LoginRecoveryAuthnCodeConfig.tsx | 90 ++ .../pages/LoginRecoveryAuthnCodeInput.tsx | 86 ++ src/login/pages/LoginResetOtp.tsx | 40 + src/login/pages/LoginUpdatePassword.tsx | 112 +++ src/login/pages/LoginUpdateProfile.tsx | 111 +++ src/login/pages/LoginUsername.tsx | 90 ++ src/login/pages/LoginVerifyEmail.tsx | 56 ++ src/login/pages/LoginX509Info.tsx | 40 + src/login/pages/LogoutConfirm.tsx | 42 + src/login/pages/Register.tsx | 161 ++-- src/login/pages/SamlPostForm.tsx | 49 ++ src/login/pages/SelectAuthenticator.tsx | 48 ++ src/login/pages/SelectOrganization.tsx | 48 ++ src/login/pages/Terms.tsx | 73 ++ src/login/pages/UpdateEmail.tsx | 87 ++ src/login/pages/WebauthnAuthenticate.tsx | 50 ++ src/login/pages/WebauthnError.tsx | 57 ++ src/login/pages/WebauthnRegister.tsx | 50 ++ src/login/utils/hideKeycloakStyles.ts | 20 + src/login/utils/realmColor.ts | 12 + src/main.tsx | 29 +- vite.config.ts | 2 + 70 files changed, 4348 insertions(+), 502 deletions(-) create mode 100644 email/html/email-update-confirmation.ftl create mode 100644 email/html/email-verification-with-code.ftl create mode 100644 email/html/email-verification.ftl create mode 100644 email/html/event-login_error.ftl create mode 100644 email/html/event-update_password.ftl create mode 100644 email/html/executeActions.ftl create mode 100644 email/html/identity-provider-link.ftl create mode 100644 email/html/org-invite.ftl create mode 100644 email/html/password-reset.ftl create mode 100644 email/html/template.ftl create mode 100644 public/favicon.ico create mode 100644 src/.gitignore create mode 100644 src/index.css create mode 100644 src/login/components/Branding.tsx create mode 100644 src/login/components/Footer.tsx create mode 100644 src/login/components/LanguageSwitcher.tsx create mode 100644 src/login/components/PageLayout.tsx create mode 100644 src/login/components/ThemeSwitcher.tsx create mode 100644 src/login/pages/Code.tsx create mode 100644 src/login/pages/DeleteAccountConfirm.tsx create mode 100644 src/login/pages/DeleteCredential.tsx create mode 100644 src/login/pages/Error.tsx create mode 100644 src/login/pages/FrontchannelLogout.tsx create mode 100644 src/login/pages/IdpReviewUserProfile.tsx create mode 100644 src/login/pages/Info.tsx create mode 100644 src/login/pages/LinkIdpAction.tsx create mode 100644 src/login/pages/LoginConfigTotp.tsx create mode 100644 src/login/pages/LoginIdpLinkConfirm.tsx create mode 100644 src/login/pages/LoginIdpLinkConfirmOverride.tsx create mode 100644 src/login/pages/LoginIdpLinkEmail.tsx create mode 100644 src/login/pages/LoginOauth2DeviceVerifyUserCode.tsx create mode 100644 src/login/pages/LoginOauthGrant.tsx create mode 100644 src/login/pages/LoginOtp.tsx create mode 100644 src/login/pages/LoginPageExpired.tsx create mode 100644 src/login/pages/LoginPasskeysConditionalAuthenticate.tsx create mode 100644 src/login/pages/LoginPassword.tsx create mode 100644 src/login/pages/LoginRecoveryAuthnCodeConfig.tsx create mode 100644 src/login/pages/LoginRecoveryAuthnCodeInput.tsx create mode 100644 src/login/pages/LoginResetOtp.tsx create mode 100644 src/login/pages/LoginUpdatePassword.tsx create mode 100644 src/login/pages/LoginUpdateProfile.tsx create mode 100644 src/login/pages/LoginUsername.tsx create mode 100644 src/login/pages/LoginVerifyEmail.tsx create mode 100644 src/login/pages/LoginX509Info.tsx create mode 100644 src/login/pages/LogoutConfirm.tsx create mode 100644 src/login/pages/SamlPostForm.tsx create mode 100644 src/login/pages/SelectAuthenticator.tsx create mode 100644 src/login/pages/SelectOrganization.tsx create mode 100644 src/login/pages/Terms.tsx create mode 100644 src/login/pages/UpdateEmail.tsx create mode 100644 src/login/pages/WebauthnAuthenticate.tsx create mode 100644 src/login/pages/WebauthnError.tsx create mode 100644 src/login/pages/WebauthnRegister.tsx create mode 100644 src/login/utils/hideKeycloakStyles.ts diff --git a/.gitignore b/.gitignore index 4bfd487..e185cde 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,4 @@ jspm_packages # build output of `jsx-email` /.rendered +.cursor diff --git a/.storybook/preview.ts b/.storybook/preview.ts index a8f82a4..fc5ec12 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,9 +1,11 @@ import type { Preview } from '@storybook/react-vite' +import React from 'react' import '@helpwave/hightide/style/globals.css' +import '../src/index.css' +import { ThemeProvider, LocaleProvider } from '@helpwave/hightide' -if (typeof window !== 'undefined' && typeof process === 'undefined') { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (window as any).process = { env: {} } +if (typeof window !== 'undefined' && typeof (globalThis as { process?: { env: Record } }).process === 'undefined') { + (globalThis as { process: { env: Record } }).process = { env: {} } } const hideLanguageSwitcherCss = ` @@ -42,7 +44,15 @@ const preview: Preview = { document.head.appendChild(style) } } - return Story() + return React.createElement( + ThemeProvider, + {}, + React.createElement( + LocaleProvider, + { locale: 'en-US' }, + React.createElement(Story) + ) + ) } ] } diff --git a/email/html/email-update-confirmation.ftl b/email/html/email-update-confirmation.ftl new file mode 100644 index 0000000..111f0fc --- /dev/null +++ b/email/html/email-update-confirmation.ftl @@ -0,0 +1,9 @@ +<#import "template.ftl" as layout> +<@layout.main> +

${msg("emailUpdateConfirmationTitle")}

+

${msg("emailUpdateConfirmationBody1", realm.displayName, newEmail)}

+

+ ${msg("doClickHere")} +

+

${msg("emailUpdateConfirmationBody2")}

+ \ No newline at end of file diff --git a/email/html/email-verification-with-code.ftl b/email/html/email-verification-with-code.ftl new file mode 100644 index 0000000..2b07dbc --- /dev/null +++ b/email/html/email-verification-with-code.ftl @@ -0,0 +1,7 @@ +<#import "template.ftl" as layout> +<@layout.main> +

${msg("emailVerificationTitle")}

+

${msg("emailVerificationBody1", realm.displayName)}

+

${msg("emailVerificationCode")}: ${code}

+

${msg("emailVerificationBody2")}

+ \ No newline at end of file diff --git a/email/html/email-verification.ftl b/email/html/email-verification.ftl new file mode 100644 index 0000000..cfd97c9 --- /dev/null +++ b/email/html/email-verification.ftl @@ -0,0 +1,10 @@ +<#import "template.ftl" as layout> +<@layout.main> +

${msg("emailVerificationTitle")}

+

${msg("emailVerificationBody1", realm.displayName)}

+

+ ${msg("doClickHere")} +

+

${msg("emailVerificationBody2")}

+

${msg("emailVerificationBody3")}

+ \ No newline at end of file diff --git a/email/html/event-login_error.ftl b/email/html/event-login_error.ftl new file mode 100644 index 0000000..4446e45 --- /dev/null +++ b/email/html/event-login_error.ftl @@ -0,0 +1,9 @@ +<#import "template.ftl" as layout> +<@layout.main> +

${msg("eventLoginErrorTitle")}

+

${msg("eventLoginErrorBody1", realm.displayName)}

+

${msg("eventLoginErrorBody2")}

+ <#if ipAddress??> +

${msg("eventLoginErrorBody3", ipAddress)}

+ + \ No newline at end of file diff --git a/email/html/event-update_password.ftl b/email/html/event-update_password.ftl new file mode 100644 index 0000000..1648b66 --- /dev/null +++ b/email/html/event-update_password.ftl @@ -0,0 +1,9 @@ +<#import "template.ftl" as layout> +<@layout.main> +

${msg("eventUpdatePasswordTitle")}

+

${msg("eventUpdatePasswordBody1", realm.displayName)}

+

${msg("eventUpdatePasswordBody2")}

+ <#if ipAddress??> +

${msg("eventUpdatePasswordBody3", ipAddress)}

+ + \ No newline at end of file diff --git a/email/html/executeActions.ftl b/email/html/executeActions.ftl new file mode 100644 index 0000000..51b9431 --- /dev/null +++ b/email/html/executeActions.ftl @@ -0,0 +1,16 @@ +<#import "template.ftl" as layout> +<@layout.main> +

${msg("executeActionsTitle")}

+

${msg("executeActionsBody1", realm.displayName)}

+ <#if requiredActions??> +
    + <#list requiredActions as action> +
  • ${msg("requiredAction.${action}")}
  • + +
+ +

+ ${msg("doClickHere")} +

+

${msg("executeActionsBody2")}

+ \ No newline at end of file diff --git a/email/html/identity-provider-link.ftl b/email/html/identity-provider-link.ftl new file mode 100644 index 0000000..76f0aca --- /dev/null +++ b/email/html/identity-provider-link.ftl @@ -0,0 +1,9 @@ +<#import "template.ftl" as layout> +<@layout.main> +

${msg("identityProviderLinkTitle")}

+

${msg("identityProviderLinkBody1", realm.displayName, identityProviderAlias)}

+

+ ${msg("doClickHere")} +

+

${msg("identityProviderLinkBody2")}

+ \ No newline at end of file diff --git a/email/html/org-invite.ftl b/email/html/org-invite.ftl new file mode 100644 index 0000000..e689531 --- /dev/null +++ b/email/html/org-invite.ftl @@ -0,0 +1,9 @@ +<#import "template.ftl" as layout> +<@layout.main> +

${msg("orgInviteTitle")}

+

${msg("orgInviteBody1", realm.displayName, orgName)}

+

+ ${msg("doClickHere")} +

+

${msg("orgInviteBody2")}

+ \ No newline at end of file diff --git a/email/html/password-reset.ftl b/email/html/password-reset.ftl new file mode 100644 index 0000000..d8983c0 --- /dev/null +++ b/email/html/password-reset.ftl @@ -0,0 +1,10 @@ +<#import "template.ftl" as layout> +<@layout.main> +

${msg("emailResetPasswordTitle")}

+

${msg("emailResetPasswordBody1", realm.displayName)}

+

+ ${msg("doClickHere")} +

+

${msg("emailResetPasswordBody2")}

+

${msg("emailResetPasswordBody3")}

+ \ No newline at end of file diff --git a/email/html/template.ftl b/email/html/template.ftl new file mode 100644 index 0000000..1fb78b1 --- /dev/null +++ b/email/html/template.ftl @@ -0,0 +1,178 @@ + + + + ${msg("emailTitle")} + + + + + + + + + + + + +
 
+ +
+
+ helpwave logo +
+ helpwave +
+ + <#nested> +
+ + + +
${trackView}
+ + \ No newline at end of file diff --git a/index.html b/index.html index 089aa15..701c9cc 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,8 @@ - + + diff --git a/locales/de.arb b/locales/de.arb index 7bd65e7..218bc49 100644 --- a/locales/de.arb +++ b/locales/de.arb @@ -11,5 +11,257 @@ "type": "number" } } + }, + "imprint": "Impressum", + "@imprint": { + "description": "Link-Text für Impressum" + }, + "privacy": "Datenschutz", + "@privacy": { + "description": "Link-Text für Datenschutzerklärung" + }, + "forgotPassword": "Passwort vergessen?", + "@forgotPassword": { + "description": "Link-Text für Passwort vergessen" + }, + "noAccount": "Kein Konto?", + "@noAccount": { + "description": "Text vor Registrierungs-Link" + }, + "register": "Registrieren", + "@register": { + "description": "Registrierungs-Button Text" + }, + "backToLogin": "Zurück zur Anmeldung", + "@backToLogin": { + "description": "Zurück zur Anmeldung Link-Text" + }, + "usernameOrEmail": "Benutzername oder E-Mail", + "@usernameOrEmail": { + "description": "Label für Benutzername oder E-Mail Eingabefeld" + }, + "username": "Benutzername", + "@username": { + "description": "Label für Benutzername Eingabefeld" + }, + "password": "Passwort", + "@password": { + "description": "Label für Passwort Eingabefeld" + }, + "rememberMe": "Angemeldet bleiben", + "@rememberMe": { + "description": "Label für Angemeldet bleiben Checkbox" + }, + "doLogIn": "Anmelden", + "@doLogIn": { + "description": "Anmelden Button Text" + }, + "doForgotPassword": "Passwort vergessen?", + "@doForgotPassword": { + "description": "Passwort vergessen Button Text" + }, + "doRegister": "Registrieren", + "@doRegister": { + "description": "Registrieren Button Text" + }, + "identity-provider-redirector": "Oder anmelden mit", + "@identity-provider-redirector": { + "description": "Text vor Social-Login Anbietern" + }, + "acceptTerms": "Ich akzeptiere die Allgemeinen Geschäftsbedingungen", + "@acceptTerms": { + "description": "Text für AGB-Akzeptanz Checkbox" + }, + "passwordNew": "Neues Passwort", + "@passwordNew": { + "description": "Label für neues Passwort Eingabefeld" + }, + "passwordConfirm": "Passwort bestätigen", + "@passwordConfirm": { + "description": "Label für Passwort-Bestätigung Eingabefeld" + }, + "doSubmit": "Absenden", + "@doSubmit": { + "description": "Absenden Button Text" + }, + "otp": "Einmalpasswort", + "@otp": { + "description": "Label für OTP Eingabefeld" + }, + "loginOtp": "Bestätigungscode", + "@loginOtp": { + "description": "Label für Login OTP/Bestätigungscode Eingabefeld" + }, + "termsText": "Allgemeine Geschäftsbedingungen Text", + "@termsText": { + "description": "Standard AGB Text" + }, + "doAccept": "Akzeptieren", + "@doAccept": { + "description": "Akzeptieren Button Text" + }, + "doDecline": "Ablehnen", + "@doDecline": { + "description": "Ablehnen Button Text" + }, + "logoutConfirmHeader": "Möchten Sie sich wirklich abmelden?", + "@logoutConfirmHeader": { + "description": "Abmelde-Bestätigungsnachricht" + }, + "doLogout": "Abmelden", + "@doLogout": { + "description": "Abmelden Button Text" + }, + "doCancel": "Abbrechen", + "@doCancel": { + "description": "Abbrechen Button Text" + }, + "backToApplication": "Zurück zur Anwendung", + "@backToApplication": { + "description": "Zurück zur Anwendung Button Text" + }, + "doContinue": "Weiter", + "@doContinue": { + "description": "Weiter Button Text" + }, + "emailVerificationBody1": "Bitte überprüfen Sie Ihre E-Mail für einen Bestätigungslink.", + "@emailVerificationBody1": { + "description": "E-Mail-Bestätigungsanweisungstext" + }, + "emailVerificationBody": "Bitte überprüfen Sie Ihre E-Mail für einen Bestätigungslink.", + "@emailVerificationBody": { + "description": "E-Mail-Bestätigungsanweisungstext (alternativer Schlüssel)" + }, + "doClickHere": "Hier klicken", + "@doClickHere": { + "description": "Hier klicken Button/Link Text" + }, + "doRestart": "Neu starten", + "@doRestart": { + "description": "Neu starten Button Text" + }, + "deleteAccountConfirm": "Möchten Sie Ihr Konto wirklich löschen?", + "@deleteAccountConfirm": { + "description": "Konto-Löschungsbestätigungsnachricht" + }, + "doDeleteAccount": "Konto löschen", + "@doDeleteAccount": { + "description": "Konto löschen Button Text" + }, + "deleteCredentialConfirm": "Möchten Sie diese Anmeldedaten wirklich löschen?", + "@deleteCredentialConfirm": { + "description": "Anmeldedaten-Löschungsbestätigungsnachricht" + }, + "doDelete": "Löschen", + "@doDelete": { + "description": "Löschen Button Text" + }, + "frontchannelLogoutMessage": "Abmelden...", + "@frontchannelLogoutMessage": { + "description": "Frontchannel Abmeldungsnachricht" + }, + "linkIdpMessage": "Identitätsanbieter verknüpfen...", + "@linkIdpMessage": { + "description": "Identitätsanbieter verknüpfen Nachricht" + }, + "idpLinkConfirmMessage": "Möchten Sie diesen Identitätsanbieter mit Ihrem Konto verknüpfen?", + "@idpLinkConfirmMessage": { + "description": "IDP-Verknüpfungsbestätigungsnachricht" + }, + "doLink": "Verknüpfen", + "@doLink": { + "description": "Verknüpfen Button Text" + }, + "idpLinkConfirmOverrideMessage": "Dieser Identitätsanbieter ist bereits mit einem anderen Konto verknüpft. Möchten Sie dies überschreiben?", + "@idpLinkConfirmOverrideMessage": { + "description": "IDP-Verknüpfungsüberschreibungsbestätigungsnachricht" + }, + "doOverride": "Überschreiben", + "@doOverride": { + "description": "Überschreiben Button Text" + }, + "email": "E-Mail", + "@email": { + "description": "Label für E-Mail Eingabefeld" + }, + "oauthGrantTitle": "Zugriff gewähren", + "@oauthGrantTitle": { + "description": "OAuth-Gewährung Titel" + }, + "oauthGrantMessage": "Die Anwendung fordert Zugriff auf Ihr Konto an", + "@oauthGrantMessage": { + "description": "OAuth-Gewährungsnachricht" + }, + "oauthGrantScopes": "Angeforderte Berechtigungen", + "@oauthGrantScopes": { + "description": "OAuth-Gewährungsberechtigungen Label" + }, + "pageExpiredMessage": "Diese Seite ist abgelaufen. Bitte starten Sie den Anmeldevorgang neu.", + "@pageExpiredMessage": { + "description": "Seite abgelaufen Nachricht" + }, + "passkeysConditionalAuthenticateMessage": "Authentifizierung mit Passkey...", + "@passkeysConditionalAuthenticateMessage": { + "description": "Passkeys bedingte Authentifizierungsnachricht" + }, + "recoveryAuthnCodeConfigMessage": "Konfigurieren Sie Ihren Wiederherstellungsauthentifizierungscode", + "@recoveryAuthnCodeConfigMessage": { + "description": "Wiederherstellungsauthentifizierungscode-Konfigurationsnachricht" + }, + "recoveryCode": "Wiederherstellungscode", + "@recoveryCode": { + "description": "Label für Wiederherstellungscode Eingabefeld" + }, + "resetOtpMessage": "Ihr OTP wurde zurückgesetzt. Bitte konfigurieren Sie ein neues.", + "@resetOtpMessage": { + "description": "OTP zurücksetzen Nachricht" + }, + "loginTotpScanBarcode": "Scannen Sie diesen QR-Code mit Ihrer Authenticator-App", + "@loginTotpScanBarcode": { + "description": "TOTP QR-Code scannen Anweisung" + }, + "loginTotpOneTime": "Einmalcode", + "@loginTotpOneTime": { + "description": "Label für TOTP Einmalcode Eingabefeld" + }, + "samlPostFormMessage": "Weiterleitung zum Identitätsanbieter...", + "@samlPostFormMessage": { + "description": "SAML Post-Formular Nachricht" + }, + "selectAuthenticatorTitle": "Authentifikator auswählen", + "@selectAuthenticatorTitle": { + "description": "Authentifikator auswählen Titel" + }, + "selectOrganizationTitle": "Organisation auswählen", + "@selectOrganizationTitle": { + "description": "Organisation auswählen Titel" + }, + "x509InfoTitle": "X.509 Zertifikatsinformationen", + "@x509InfoTitle": { + "description": "X.509 Info Titel" + }, + "x509InfoMessage": "Bitte geben Sie Ihre X.509 Zertifikatsinformationen an", + "@x509InfoMessage": { + "description": "X.509 Info Nachricht" + }, + "webauthnAuthenticateMessage": "Authentifizieren Sie sich mit Ihrem Sicherheitsschlüssel", + "@webauthnAuthenticateMessage": { + "description": "WebAuthn Authentifizierungsnachricht" + }, + "webauthnErrorMessage": "Ein Fehler ist bei der WebAuthn-Authentifizierung aufgetreten", + "@webauthnErrorMessage": { + "description": "WebAuthn Fehlernachricht" + }, + "webauthnRegisterMessage": "Registrieren Sie Ihren Sicherheitsschlüssel", + "@webauthnRegisterMessage": { + "description": "WebAuthn Registrierungsnachricht" + }, + "oauth2DeviceVerifyUserCodeMessage": "Geben Sie den auf Ihrem Gerät angezeigten Benutzercode ein", + "@oauth2DeviceVerifyUserCodeMessage": { + "description": "OAuth2 Gerät Benutzercode-Verifizierungsnachricht" + }, + "userCode": "Benutzercode", + "@userCode": { + "description": "Label für Benutzercode Eingabefeld" } } diff --git a/locales/en.arb b/locales/en.arb index 8925f73..a0cc7be 100644 --- a/locales/en.arb +++ b/locales/en.arb @@ -11,5 +11,257 @@ "type": "number" } } + }, + "imprint": "Imprint", + "@imprint": { + "description": "Link text for imprint" + }, + "privacy": "Privacy", + "@privacy": { + "description": "Link text for privacy policy" + }, + "forgotPassword": "Forgot Password?", + "@forgotPassword": { + "description": "Link text for forgot password" + }, + "noAccount": "No account?", + "@noAccount": { + "description": "Text before register link" + }, + "register": "Register", + "@register": { + "description": "Register button text" + }, + "backToLogin": "Back to Login", + "@backToLogin": { + "description": "Back to login link text" + }, + "usernameOrEmail": "Username or Email", + "@usernameOrEmail": { + "description": "Label for username or email input field" + }, + "username": "Username", + "@username": { + "description": "Label for username input field" + }, + "password": "Password", + "@password": { + "description": "Label for password input field" + }, + "rememberMe": "Remember me", + "@rememberMe": { + "description": "Label for remember me checkbox" + }, + "doLogIn": "Log In", + "@doLogIn": { + "description": "Log in button text" + }, + "doForgotPassword": "Forgot Password?", + "@doForgotPassword": { + "description": "Forgot password button text" + }, + "doRegister": "Register", + "@doRegister": { + "description": "Register button text" + }, + "identity-provider-redirector": "Or sign in with", + "@identity-provider-redirector": { + "description": "Text before social login providers" + }, + "acceptTerms": "I accept the terms and conditions", + "@acceptTerms": { + "description": "Text for terms acceptance checkbox" + }, + "passwordNew": "New Password", + "@passwordNew": { + "description": "Label for new password input field" + }, + "passwordConfirm": "Password Confirmation", + "@passwordConfirm": { + "description": "Label for password confirmation input field" + }, + "doSubmit": "Submit", + "@doSubmit": { + "description": "Submit button text" + }, + "otp": "One-time password", + "@otp": { + "description": "Label for OTP input field" + }, + "loginOtp": "Verification Code", + "@loginOtp": { + "description": "Label for login OTP/verification code input field" + }, + "termsText": "Terms and conditions text", + "@termsText": { + "description": "Default terms and conditions text" + }, + "doAccept": "Accept", + "@doAccept": { + "description": "Accept button text" + }, + "doDecline": "Decline", + "@doDecline": { + "description": "Decline button text" + }, + "logoutConfirmHeader": "Are you sure you want to logout?", + "@logoutConfirmHeader": { + "description": "Logout confirmation message" + }, + "doLogout": "Logout", + "@doLogout": { + "description": "Logout button text" + }, + "doCancel": "Cancel", + "@doCancel": { + "description": "Cancel button text" + }, + "backToApplication": "Back to Application", + "@backToApplication": { + "description": "Back to application button text" + }, + "doContinue": "Continue", + "@doContinue": { + "description": "Continue button text" + }, + "emailVerificationBody1": "Please check your email for a verification link.", + "@emailVerificationBody1": { + "description": "Email verification instruction text" + }, + "emailVerificationBody": "Please check your email for a verification link.", + "@emailVerificationBody": { + "description": "Email verification instruction text (alternative key)" + }, + "doClickHere": "Click here", + "@doClickHere": { + "description": "Click here button/link text" + }, + "doRestart": "Restart", + "@doRestart": { + "description": "Restart button text" + }, + "deleteAccountConfirm": "Are you sure you want to delete your account?", + "@deleteAccountConfirm": { + "description": "Delete account confirmation message" + }, + "doDeleteAccount": "Delete Account", + "@doDeleteAccount": { + "description": "Delete account button text" + }, + "deleteCredentialConfirm": "Are you sure you want to delete this credential?", + "@deleteCredentialConfirm": { + "description": "Delete credential confirmation message" + }, + "doDelete": "Delete", + "@doDelete": { + "description": "Delete button text" + }, + "frontchannelLogoutMessage": "Logging out...", + "@frontchannelLogoutMessage": { + "description": "Frontchannel logout message" + }, + "linkIdpMessage": "Linking identity provider...", + "@linkIdpMessage": { + "description": "Link identity provider message" + }, + "idpLinkConfirmMessage": "Do you want to link this identity provider to your account?", + "@idpLinkConfirmMessage": { + "description": "IDP link confirmation message" + }, + "doLink": "Link", + "@doLink": { + "description": "Link button text" + }, + "idpLinkConfirmOverrideMessage": "This identity provider is already linked to another account. Do you want to override it?", + "@idpLinkConfirmOverrideMessage": { + "description": "IDP link override confirmation message" + }, + "doOverride": "Override", + "@doOverride": { + "description": "Override button text" + }, + "email": "Email", + "@email": { + "description": "Label for email input field" + }, + "oauthGrantTitle": "Grant Access", + "@oauthGrantTitle": { + "description": "OAuth grant title" + }, + "oauthGrantMessage": "The application requests access to your account", + "@oauthGrantMessage": { + "description": "OAuth grant message" + }, + "oauthGrantScopes": "Requested Scopes", + "@oauthGrantScopes": { + "description": "OAuth grant scopes label" + }, + "pageExpiredMessage": "This page has expired. Please restart the login process.", + "@pageExpiredMessage": { + "description": "Page expired message" + }, + "passkeysConditionalAuthenticateMessage": "Authenticating with passkey...", + "@passkeysConditionalAuthenticateMessage": { + "description": "Passkeys conditional authenticate message" + }, + "recoveryAuthnCodeConfigMessage": "Configure your recovery authentication code", + "@recoveryAuthnCodeConfigMessage": { + "description": "Recovery authentication code config message" + }, + "recoveryCode": "Recovery Code", + "@recoveryCode": { + "description": "Label for recovery code input field" + }, + "resetOtpMessage": "Your OTP has been reset. Please configure a new one.", + "@resetOtpMessage": { + "description": "Reset OTP message" + }, + "loginTotpScanBarcode": "Scan this QR code with your authenticator app", + "@loginTotpScanBarcode": { + "description": "TOTP scan barcode instruction" + }, + "loginTotpOneTime": "One-time code", + "@loginTotpOneTime": { + "description": "Label for TOTP one-time code input field" + }, + "samlPostFormMessage": "Redirecting to identity provider...", + "@samlPostFormMessage": { + "description": "SAML post form message" + }, + "selectAuthenticatorTitle": "Select Authenticator", + "@selectAuthenticatorTitle": { + "description": "Select authenticator title" + }, + "selectOrganizationTitle": "Select Organization", + "@selectOrganizationTitle": { + "description": "Select organization title" + }, + "x509InfoTitle": "X.509 Certificate Information", + "@x509InfoTitle": { + "description": "X.509 info title" + }, + "x509InfoMessage": "Please provide your X.509 certificate information", + "@x509InfoMessage": { + "description": "X.509 info message" + }, + "webauthnAuthenticateMessage": "Authenticate with your security key", + "@webauthnAuthenticateMessage": { + "description": "WebAuthn authenticate message" + }, + "webauthnErrorMessage": "An error occurred during WebAuthn authentication", + "@webauthnErrorMessage": { + "description": "WebAuthn error message" + }, + "webauthnRegisterMessage": "Register your security key", + "@webauthnRegisterMessage": { + "description": "WebAuthn register message" + }, + "oauth2DeviceVerifyUserCodeMessage": "Enter the user code displayed on your device", + "@oauth2DeviceVerifyUserCodeMessage": { + "description": "OAuth2 device verify user code message" + }, + "userCode": "User Code", + "@userCode": { + "description": "Label for user code input field" } } diff --git a/package-lock.json b/package-lock.json index eb728ca..58cb200 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,19 @@ { "name": "id.helpwave.de", - "version": "0.1.0", + "version": "0.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "id.helpwave.de", - "version": "0.1.0", + "version": "0.1.2", + "hasInstallScript": true, "license": "MPL-2", "dependencies": { "@helpwave/hightide": "0.6.16", + "@keycloakify/email-native": "~260007.0.0", "keycloakify": "^11.14.2", + "lucide-react": "^0.563.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -18,20 +21,20 @@ "@eslint/js": "^9.15.0", "@helpwave/eslint-config": "^0.0.11", "@storybook/react-vite": "^10.2.1", + "@tailwindcss/vite": "^4.1.18", "@types/react": "^18.2.43", "@types/react-dom": "^18.2.17", "@typescript-eslint/eslint-plugin": "^8.15.0", "@typescript-eslint/parser": "^8.15.0", "@vitejs/plugin-react": "^4.2.1", "eslint": "^9.15.0", - "eslint-config-prettier": "^9.1.0", "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.14", "eslint-plugin-storybook": "^10.2.1", "globals": "^15.12.0", - "prettier": "3.3.1", "storybook": "^10.2.1", + "tailwindcss": "^4.1.18", "typescript": "^5.2.2", "typescript-eslint": "^8.15.0", "vite": "^5.0.8" @@ -361,9 +364,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", "cpu": [ "ppc64" ], @@ -378,9 +381,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", "cpu": [ "arm" ], @@ -395,9 +398,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", "cpu": [ "arm64" ], @@ -412,9 +415,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", "cpu": [ "x64" ], @@ -429,9 +432,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", "cpu": [ "arm64" ], @@ -446,9 +449,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", "cpu": [ "x64" ], @@ -463,9 +466,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", "cpu": [ "arm64" ], @@ -480,9 +483,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", "cpu": [ "x64" ], @@ -497,9 +500,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", "cpu": [ "arm" ], @@ -514,9 +517,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", "cpu": [ "arm64" ], @@ -531,9 +534,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", "cpu": [ "ia32" ], @@ -548,9 +551,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", "cpu": [ "loong64" ], @@ -565,9 +568,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", "cpu": [ "mips64el" ], @@ -582,9 +585,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", "cpu": [ "ppc64" ], @@ -599,9 +602,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", "cpu": [ "riscv64" ], @@ -616,9 +619,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", "cpu": [ "s390x" ], @@ -633,9 +636,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", "cpu": [ "x64" ], @@ -650,9 +653,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", "cpu": [ "x64" ], @@ -667,9 +670,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", "cpu": [ "x64" ], @@ -684,9 +687,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", "cpu": [ "x64" ], @@ -701,9 +704,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", "cpu": [ "arm64" ], @@ -718,9 +721,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", "cpu": [ "ia32" ], @@ -735,9 +738,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", "cpu": [ "x64" ], @@ -781,13 +784,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", - "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.4", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -796,9 +799,9 @@ } }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -819,20 +822,36 @@ "node": "*" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", - "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/eslintrc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -842,7 +861,7 @@ "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", + "js-yaml": "^4.1.1", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, @@ -854,9 +873,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -891,19 +910,22 @@ } }, "node_modules/@eslint/js": { - "version": "9.15.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", - "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -911,12 +933,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", - "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { @@ -956,6 +979,15 @@ "tailwindcss": "4.1.18" } }, + "node_modules/@helpwave/hightide/node_modules/lucide-react": { + "version": "0.561.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.561.0.tgz", + "integrity": "sha512-Y59gMY38tl4/i0qewcqohPdEbieBy7SovpBL9IFebhc2mDd8x4PZSOsiFRkpPcOq6bj1r/mjH/Rk73gSlIJP2A==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/@helpwave/hightide/node_modules/react": { "version": "19.2.3", "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", @@ -1046,9 +1078,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", - "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1165,6 +1197,12 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@keycloakify/email-native": { + "version": "260007.0.0", + "resolved": "https://registry.npmjs.org/@keycloakify/email-native/-/email-native-260007.0.0.tgz", + "integrity": "sha512-hFUiOwwpc84eXPAct44G/pTBkYnDQF1jIObME+ZUrb7XidmFJ/TdH9q49LKpd9sIivSyOEJa1qLtrggP+c+BJw==", + "license": "Apache-2.0" + }, "node_modules/@next/eslint-plugin-next": { "version": "15.5.10", "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.10.tgz", @@ -1573,17 +1611,10 @@ } } }, - "node_modules/@rollup/pluginutils/node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "license": "MIT" - }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", - "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.0.tgz", + "integrity": "sha512-tPgXB6cDTndIe1ah7u6amCI1T0SsnlOuKgg10Xh3uizJk4e5M1JGaUMk7J4ciuAUcFpbOiNhm2XIjP9ON0dUqA==", "cpu": [ "arm" ], @@ -1595,9 +1626,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", - "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.0.tgz", + "integrity": "sha512-sa4LyseLLXr1onr97StkU1Nb7fWcg6niokTwEVNOO7awaKaoRObQ54+V/hrF/BP1noMEaaAW6Fg2d/CfLiq3Mg==", "cpu": [ "arm64" ], @@ -1609,9 +1640,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", - "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.0.tgz", + "integrity": "sha512-/NNIj9A7yLjKdmkx5dC2XQ9DmjIECpGpwHoGmA5E1AhU0fuICSqSWScPhN1yLCkEdkCwJIDu2xIeLPs60MNIVg==", "cpu": [ "arm64" ], @@ -1623,9 +1654,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", - "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.0.tgz", + "integrity": "sha512-xoh8abqgPrPYPr7pTYipqnUi1V3em56JzE/HgDgitTqZBZ3yKCWI+7KUkceM6tNweyUKYru1UMi7FC060RyKwA==", "cpu": [ "x64" ], @@ -1636,10 +1667,38 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.0.tgz", + "integrity": "sha512-PCkMh7fNahWSbA0OTUQ2OpYHpjZZr0hPr8lId8twD7a7SeWrvT3xJVyza+dQwXSSq4yEQTMoXgNOfMCsn8584g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.0.tgz", + "integrity": "sha512-1j3stGx+qbhXql4OCDZhnK7b01s6rBKNybfsX+TNrEe9JNq4DLi1yGiR1xW+nL+FNVvI4D02PUnl6gJ/2y6WJA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", - "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.0.tgz", + "integrity": "sha512-eyrr5W08Ms9uM0mLcKfM/Uzx7hjhz2bcjv8P2uynfj0yU8GGPdz8iYrBPhiLOZqahoAMB8ZiolRZPbbU2MAi6Q==", "cpu": [ "arm" ], @@ -1651,9 +1710,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", - "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.0.tgz", + "integrity": "sha512-Xds90ITXJCNyX9pDhqf85MKWUI4lqjiPAipJ8OLp8xqI2Ehk+TCVhF9rvOoN8xTbcafow3QOThkNnrM33uCFQA==", "cpu": [ "arm" ], @@ -1665,9 +1724,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", - "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.0.tgz", + "integrity": "sha512-Xws2KA4CLvZmXjy46SQaXSejuKPhwVdaNinldoYfqruZBaJHqVo6hnRa8SDo9z7PBW5x84SH64+izmldCgbezw==", "cpu": [ "arm64" ], @@ -1679,9 +1738,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", - "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.0.tgz", + "integrity": "sha512-hrKXKbX5FdaRJj7lTMusmvKbhMJSGWJ+w++4KmjiDhpTgNlhYobMvKfDoIWecy4O60K6yA4SnztGuNTQF+Lplw==", "cpu": [ "arm64" ], @@ -1692,10 +1751,52 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", - "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.0.tgz", + "integrity": "sha512-6A+nccfSDGKsPm00d3xKcrsBcbqzCTAukjwWK6rbuAnB2bHaL3r9720HBVZ/no7+FhZLz/U3GwwZZEh6tOSI8Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.0.tgz", + "integrity": "sha512-4P1VyYUe6XAJtQH1Hh99THxr0GKMMwIXsRNOceLrJnaHTDgk1FTcTimDgneRJPvB3LqDQxUmroBclQ1S0cIJwQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.0.tgz", + "integrity": "sha512-8Vv6pLuIZCMcgXre6c3nOPhE0gjz1+nZP6T+hwWjr7sVH8k0jRkH+XnfjjOTglyMBdSKBPPz54/y1gToSKwrSQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.0.tgz", + "integrity": "sha512-r1te1M0Sm2TBVD/RxBPC6RZVwNqUTwJTA7w+C/IW5v9Ssu6xmxWEi+iJQlpBhtUiT1raJ5b48pI8tBvEjEFnFA==", "cpu": [ "ppc64" ], @@ -1707,9 +1808,23 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", - "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.0.tgz", + "integrity": "sha512-say0uMU/RaPm3CDQLxUUTF2oNWL8ysvHkAjcCzV2znxBr23kFfaxocS9qJm+NdkRhF8wtdEEAJuYcLPhSPbjuQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.0.tgz", + "integrity": "sha512-/MU7/HizQGsnBREtRpcSbSV1zfkoxSTR7wLsRmBPQ8FwUj5sykrP1MyJTvsxP5KBq9SyE6kH8UQQQwa0ASeoQQ==", "cpu": [ "riscv64" ], @@ -1721,9 +1836,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", - "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.0.tgz", + "integrity": "sha512-Q9eh+gUGILIHEaJf66aF6a414jQbDnn29zeu0eX3dHMuysnhTvsUvZTCAyZ6tJhUjnvzBKE4FtuaYxutxRZpOg==", "cpu": [ "s390x" ], @@ -1735,9 +1850,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", - "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.0.tgz", + "integrity": "sha512-OR5p5yG5OKSxHReWmwvM0P+VTPMwoBS45PXTMYaskKQqybkS3Kmugq1W+YbNWArF8/s7jQScgzXUhArzEQ7x0A==", "cpu": [ "x64" ], @@ -1749,9 +1864,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", - "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.0.tgz", + "integrity": "sha512-XeatKzo4lHDsVEbm1XDHZlhYZZSQYym6dg2X/Ko0kSFgio+KXLsxwJQprnR48GvdIKDOpqWqssC3iBCjoMcMpw==", "cpu": [ "x64" ], @@ -1762,10 +1877,38 @@ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.0.tgz", + "integrity": "sha512-Lu71y78F5qOfYmubYLHPcJm74GZLU6UJ4THkf/a1K7Tz2ycwC2VUbsqbJAXaR6Bx70SRdlVrt2+n5l7F0agTUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.0.tgz", + "integrity": "sha512-v5xwKDWcu7qhAEcsUubiav7r+48Uk/ENWdr82MBZZRIm7zThSxCIVDfb3ZeRRq9yqk+oIzMdDo6fCcA5DHfMyA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", - "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.0.tgz", + "integrity": "sha512-XnaaaSMGSI6Wk8F4KK3QP7GfuuhjGchElsVerCplUuxRIzdvZ7hRBpLR0omCmw+kI2RFJB80nenhOoGXlJ5TfQ==", "cpu": [ "arm64" ], @@ -1777,9 +1920,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", - "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.0.tgz", + "integrity": "sha512-3K1lP+3BXY4t4VihLw5MEg6IZD3ojSYzqzBG571W3kNQe4G4CcFpSUQVgurYgib5d+YaCjeFow8QivWp8vuSvA==", "cpu": [ "ia32" ], @@ -1790,10 +1933,24 @@ "win32" ] }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.0.tgz", + "integrity": "sha512-MDk610P/vJGc5L5ImE4k5s+GZT3en0KoK1MKPXCRgzmksAMk79j4h3k1IerxTNqwDLxsGxStEZVBqG0gIqZqoA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", - "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.0.tgz", + "integrity": "sha512-Zv7v6q6aV+VslnpwzqKAmrk5JdVkLUzok2208ZXGipjb+msxBr/fJPZyeEXiFgH7k62Ak0SLIfxQRZQvTuf7rQ==", "cpu": [ "x64" ], @@ -2254,6 +2411,21 @@ "node": ">= 10" } }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz", + "integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", + "tailwindcss": "4.1.18" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" + } + }, "node_modules/@tanstack/react-table": { "version": "8.21.3", "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", @@ -2426,6 +2598,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -3727,9 +3906,9 @@ } }, "node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -3741,29 +3920,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, "node_modules/escalade": { @@ -3790,33 +3969,33 @@ } }, "node_modules/eslint": { - "version": "9.15.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.15.0.tgz", - "integrity": "sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.9.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.15.0", - "@eslint/plugin-kit": "^0.2.3", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", + "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.5", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -3850,19 +4029,6 @@ } } }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, "node_modules/eslint-plugin-react": { "version": "7.37.2", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", @@ -3920,9 +4086,9 @@ } }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -3999,9 +4165,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4028,17 +4194,10 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, - "license": "MIT" - }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -4047,9 +4206,9 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4073,15 +4232,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4091,9 +4250,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4595,9 +4754,9 @@ } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4611,16 +4770,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -5143,9 +5292,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -5556,9 +5705,9 @@ } }, "node_modules/lucide-react": { - "version": "0.561.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.561.0.tgz", - "integrity": "sha512-Y59gMY38tl4/i0qewcqohPdEbieBy7SovpBL9IFebhc2mDd8x4PZSOsiFRkpPcOq6bj1r/mjH/Rk73gSlIJP2A==", + "version": "0.563.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.563.0.tgz", + "integrity": "sha512-8dXPB2GI4dI8jV4MgUDGBeLdGk8ekfqVZ0BdLcrRzocGgG75ltNEmWS+gE7uokKF/0oSUuczNDT+g9hFJ23FkA==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -5594,9 +5743,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -5670,9 +5819,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -5995,9 +6144,9 @@ } }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -6015,9 +6164,9 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -6033,23 +6182,6 @@ "node": ">= 0.8.0" } }, - "node_modules/prettier": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz", - "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", @@ -6310,6 +6442,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -6322,14 +6464,14 @@ } }, "node_modules/rollup": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", - "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.0.tgz", + "integrity": "sha512-e5lPJi/aui4TO1LpAXIRLySmwXSE8k3b9zoGfd42p67wzxog4WHjiZF3M2uheQih4DGyc25QEV4yRBbpueNiUA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -6339,32 +6481,34 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.0", - "@rollup/rollup-android-arm64": "4.18.0", - "@rollup/rollup-darwin-arm64": "4.18.0", - "@rollup/rollup-darwin-x64": "4.18.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", - "@rollup/rollup-linux-arm-musleabihf": "4.18.0", - "@rollup/rollup-linux-arm64-gnu": "4.18.0", - "@rollup/rollup-linux-arm64-musl": "4.18.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", - "@rollup/rollup-linux-riscv64-gnu": "4.18.0", - "@rollup/rollup-linux-s390x-gnu": "4.18.0", - "@rollup/rollup-linux-x64-gnu": "4.18.0", - "@rollup/rollup-linux-x64-musl": "4.18.0", - "@rollup/rollup-win32-arm64-msvc": "4.18.0", - "@rollup/rollup-win32-ia32-msvc": "4.18.0", - "@rollup/rollup-win32-x64-msvc": "4.18.0", + "@rollup/rollup-android-arm-eabi": "4.57.0", + "@rollup/rollup-android-arm64": "4.57.0", + "@rollup/rollup-darwin-arm64": "4.57.0", + "@rollup/rollup-darwin-x64": "4.57.0", + "@rollup/rollup-freebsd-arm64": "4.57.0", + "@rollup/rollup-freebsd-x64": "4.57.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.0", + "@rollup/rollup-linux-arm-musleabihf": "4.57.0", + "@rollup/rollup-linux-arm64-gnu": "4.57.0", + "@rollup/rollup-linux-arm64-musl": "4.57.0", + "@rollup/rollup-linux-loong64-gnu": "4.57.0", + "@rollup/rollup-linux-loong64-musl": "4.57.0", + "@rollup/rollup-linux-ppc64-gnu": "4.57.0", + "@rollup/rollup-linux-ppc64-musl": "4.57.0", + "@rollup/rollup-linux-riscv64-gnu": "4.57.0", + "@rollup/rollup-linux-riscv64-musl": "4.57.0", + "@rollup/rollup-linux-s390x-gnu": "4.57.0", + "@rollup/rollup-linux-x64-gnu": "4.57.0", + "@rollup/rollup-linux-x64-musl": "4.57.0", + "@rollup/rollup-openbsd-x64": "4.57.0", + "@rollup/rollup-openharmony-arm64": "4.57.0", + "@rollup/rollup-win32-arm64-msvc": "4.57.0", + "@rollup/rollup-win32-ia32-msvc": "4.57.0", + "@rollup/rollup-win32-x64-gnu": "4.57.0", + "@rollup/rollup-win32-x64-msvc": "4.57.0", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "license": "MIT" - }, "node_modules/run-applescript": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", @@ -7240,16 +7384,16 @@ } }, "node_modules/vite": { - "version": "5.2.13", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.13.tgz", - "integrity": "sha512-SSq1noJfY9pR3I1TUENL3rQYDQCFqgD+lM6fTRAM8Nv6Lsg5hDLaXkjETVeBt+7vZBCMoibD+6IWnT2mJ+Zb/A==", + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "esbuild": "^0.20.1", - "postcss": "^8.4.38", - "rollup": "^4.13.0" + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" }, "bin": { "vite": "bin/vite.js" @@ -7268,6 +7412,7 @@ "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -7285,6 +7430,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, diff --git a/package.json b/package.json index cd30079..27269d9 100755 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "id.helpwave.de", - "version": "0.1.1", + "version": "0.1.2", "repository": { "type": "git", "url": "git://github.com/helpwave/id.helpwave.de.git" }, "type": "module", "scripts": { + "postinstall": "keycloakify sync-extensions", "dev": "vite", "storybook": "storybook dev -p 6006", "build-intl": "npx --package=@helpwave/internationalization build-intl --force -i ./locales -o ./src/i18n/translations.ts -n helpwaveIdTranslation", @@ -20,7 +21,9 @@ "keywords": [], "dependencies": { "@helpwave/hightide": "0.6.16", + "@keycloakify/email-native": "~260007.0.0", "keycloakify": "^11.14.2", + "lucide-react": "^0.563.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -28,6 +31,7 @@ "@eslint/js": "^9.15.0", "@helpwave/eslint-config": "^0.0.11", "@storybook/react-vite": "^10.2.1", + "@tailwindcss/vite": "^4.1.18", "@types/react": "^18.2.43", "@types/react-dom": "^18.2.17", "@typescript-eslint/eslint-plugin": "^8.15.0", @@ -40,6 +44,7 @@ "eslint-plugin-storybook": "^10.2.1", "globals": "^15.12.0", "storybook": "^10.2.1", + "tailwindcss": "^4.1.18", "typescript": "^5.2.2", "typescript-eslint": "^8.15.0", "vite": "^5.0.8" diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c0e760e807cec6b518f422e9af5d3630be841749 GIT binary patch literal 2922 zcmbtW`8N~_8%CsW#MI4_-A#7tS_>i4W{iCu#@N>)%UDOGvfeRN_9$U2W5zm$5z0Oc zgE4mTg(;1R5ynM)b-q90KF@j2`@HXSo^#$GUk(n=U;GVD4jB$RJ`N7yUpmdo;x0cx z4Dd_x-@j*S^V|JhXSjd0y*PK~?#t&tFUe48(NsGJ+LnS`aFoIt7j&H z6;oXHkXIE~1eGAq@A)kG@U0hl$|$vMk{1e!$Q|s%f*#oFX#D13r{<62PY*BuI^th} zrF`4o{#HRv<>{KbLhpMT_Z(%Rm``F@rC5jIW;4bPFun@d3_)RDRtw&{CmLAs_@GT` zdt|QirLr=6rXq!G!1siA{Mk4Vuv^_b zhR?1ZEru6$)=3AJCo4JbDynK z_CWKeBcQC%+7PXsQ{;GdML}qf&xU4xN_+kpHl>zbUNBVNI$TpD&B(|XOvskEAG}(H zbc+FGue8e&}C=0UZPc&fb>dd-}Wnk-aBUIAWfc>>NGBKWhL3Wa8E}alG ze9HUjw|+&Yw$?qyJH?~VD=2ycFSPoafzP~-0ea&E`ol+CgUK9Zr#q7his=nvQF1#!;GR^z&+QLPsY9=eC4Hnz;f^hLQ#*Z;9bcRc4fM9s z58t6!q^1D~^z{a~3o*SC6Fxb`LR?VwJEJ4;)%P>v+GjWV6D?YKfv zyxPm&V_~NOP+{`vNmv7o8+Bg=ifSJ!UnvaeVC79Yw9A(G5$1Sbd=I1>hF^aBy}DRE zu(1F6IF1+(&?4XBh7C+)Bkr)dv%Z}LXI?)wdl>38tq{aw*SliAprR&csm``LwQCQ4 zAnMLn;goQ`m-32p5EI)8KVLTO*Nw@GI1?6*iXF>p|19rP2)18~Q9fRYwX|edjIT(WU{sE;Q z-Z{Nh4!O%M5PMcNga47bQQOTZm)y4kctlt`Dd%!_je3M&6nE9$dK zL{cLx*4?tFT3~6V^KL!HYl~fi3lA-UIgLJ2)D_0 zO86>-SVwfPO+Oj&n}qs_y4X?nvkkt+J* zDmSB27$p61Hgh-IF&ThYvh0m(?(*Kwd)Px87U7oz#pZieCN{?l^;qo{5?w_7gqHxk>_;dObNYT<5Kj= zbI?H1FtesT1>tp|b?^5A0nN8j^55?0^k5mj!g)=-vKM!o`#o@@PtP08o6TdfC*tqS z#-Re(bXwZ=`&vC>AZg_6F08hzM=&$~eAGD!=D9m}LC-FoTPofSw zxy@dG_cK9_ApOxHfW4nOcc@z{ZHP@v6Fz5Ae`g}9Z-2h48Y*D#?xRasjGT%&;X_0? z`}t?Dc(T>gw7|7!pANTdoqr?_qr6_MxQ{0B9dJMPUJTuEfUT24UG2hVZY2JJ2F&o9 zsCX`A-ie)W0Nk*r8^7``ZYEAey*C{1GiiMzH$-nK!-DHAgkB_tuoJ#$U97eu%nQbJcU{3v310#F ztGmb%&0W-t9wDArto+eI_vE3}*5TT$r+9Dv1v1|Z$M<>{CHF=-$G;n~|kRUVI@S`*EwKpsoMc~Zg4v9>ZHw_}#=Hq0nw&;}kCTW)D;uv&aSu*A+5A&zi( zQvKg*j+T!0rJ7~858E`_j^edg!-sR97`rdf{^bYX=D)qgz;hs{$3SD|mit7Y>KRLv zN6T7{66n@Mjy0G~oWqT}iDniYb_d%o@->g&xO{YF+sqb--FYtxC9zzi`}v8^^4_ET z)?WA`xQo)}fQT5QJ=QNUHNaTt4vPs)R`5E6_^w&<*|&=A#0_N@9i}JnYncb#=rr}~ z3hRD}eX8mKo^i{uS#%9`IaSNWL)6KNpiMobSGz4A#3hKJt&{%DeP(#BJClJS$1nT4 z+q;{&uh)3m=$L_;7gk-&rsb=}AjP%G zOr?nyfBfgqB9q#s8+>!3_BphI0#Lr}9;+!BIFd&rdgNhoFievx) literal 0 HcmV?d00001 diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..4dd285c --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,69 @@ +# This file is managed by Keycloakify, do not edit it manually. + +# === Owned files start === +# === Owned files end ===== + +# === @keycloakify/email-native v260007.0.0 === +/email/theme.properties +/email/html/email-test.ftl +/email/html/email-update-confirmation.ftl +/email/html/email-verification-with-code.ftl +/email/html/email-verification.ftl +/email/html/event-login_error.ftl +/email/html/event-remove_credential.ftl +/email/html/event-remove_totp.ftl +/email/html/event-update_credential.ftl +/email/html/event-update_password.ftl +/email/html/event-update_totp.ftl +/email/html/event-user_disabled_by_permanent_lockout.ftl +/email/html/event-user_disabled_by_temporary_lockout.ftl +/email/html/executeActions.ftl +/email/html/identity-provider-link.ftl +/email/html/org-invite.ftl +/email/html/password-reset.ftl +/email/html/template.ftl +/email/messages/messages_ar.properties +/email/messages/messages_ca.properties +/email/messages/messages_cs.properties +/email/messages/messages_da.properties +/email/messages/messages_de.properties +/email/messages/messages_el.properties +/email/messages/messages_en.properties +/email/messages/messages_es.properties +/email/messages/messages_fa.properties +/email/messages/messages_fi.properties +/email/messages/messages_fr.properties +/email/messages/messages_hu.properties +/email/messages/messages_it.properties +/email/messages/messages_ja.properties +/email/messages/messages_ka.properties +/email/messages/messages_lt.properties +/email/messages/messages_nl.properties +/email/messages/messages_no.properties +/email/messages/messages_pl.properties +/email/messages/messages_pt_BR.properties +/email/messages/messages_pt.properties +/email/messages/messages_ru.properties +/email/messages/messages_sk.properties +/email/messages/messages_sv.properties +/email/messages/messages_th.properties +/email/messages/messages_tr.properties +/email/messages/messages_uk.properties +/email/messages/messages_zh_CN.properties +/email/messages/messages_zh_TW.properties +/email/text/email-test.ftl +/email/text/email-update-confirmation.ftl +/email/text/email-verification-with-code.ftl +/email/text/email-verification.ftl +/email/text/event-login_error.ftl +/email/text/event-remove_credential.ftl +/email/text/event-remove_totp.ftl +/email/text/event-update_credential.ftl +/email/text/event-update_password.ftl +/email/text/event-update_totp.ftl +/email/text/event-user_disabled_by_permanent_lockout.ftl +/email/text/event-user_disabled_by_temporary_lockout.ftl +/email/text/executeActions.ftl +/email/text/identity-provider-link.ftl +/email/text/org-invite.ftl +/email/text/password-reset.ftl diff --git a/src/i18n/translations.ts b/src/i18n/translations.ts index c4efbac..fb986d8 100644 --- a/src/i18n/translations.ts +++ b/src/i18n/translations.ts @@ -10,28 +10,217 @@ export const helpwaveIdTranslationLocales = ['de', 'en'] as const export type HelpwaveIdTranslationLocales = typeof helpwaveIdTranslationLocales[number] export type HelpwaveIdTranslationEntries = { + 'acceptTerms': string, + 'backToApplication': string, + 'backToLogin': string, + 'deleteAccountConfirm': string, + 'deleteCredentialConfirm': string, + 'doAccept': string, + 'doCancel': string, + 'doClickHere': string, + 'doContinue': string, + 'doDecline': string, + 'doDelete': string, + 'doDeleteAccount': string, + 'doForgotPassword': string, + 'doLink': string, + 'doLogIn': string, + 'doLogout': string, + 'doOverride': string, + 'doRegister': string, + 'doRestart': string, + 'doSubmit': string, + 'email': string, + 'emailVerificationBody': string, + 'emailVerificationBody1': string, + 'forgotPassword': string, + 'frontchannelLogoutMessage': string, 'helpwaveId': string, + 'identity-provider-redirector': string, + 'idpLinkConfirmMessage': string, + 'idpLinkConfirmOverrideMessage': string, + 'imprint': string, + 'linkIdpMessage': string, + 'loginOtp': string, + 'loginTotpOneTime': string, + 'loginTotpScanBarcode': string, + 'logoutConfirmHeader': string, + 'noAccount': string, 'nOrganization': (values: { count: number }) => string, + 'oauth2DeviceVerifyUserCodeMessage': string, + 'oauthGrantMessage': string, + 'oauthGrantScopes': string, + 'oauthGrantTitle': string, + 'otp': string, + 'pageExpiredMessage': string, + 'passkeysConditionalAuthenticateMessage': string, + 'password': string, + 'passwordConfirm': string, + 'passwordNew': string, + 'privacy': string, + 'recoveryAuthnCodeConfigMessage': string, + 'recoveryCode': string, + 'register': string, + 'rememberMe': string, + 'resetOtpMessage': string, + 'samlPostFormMessage': string, + 'selectAuthenticatorTitle': string, + 'selectOrganizationTitle': string, + 'termsText': string, + 'userCode': string, + 'username': string, + 'usernameOrEmail': string, + 'webauthnAuthenticateMessage': string, + 'webauthnErrorMessage': string, + 'webauthnRegisterMessage': string, + 'x509InfoMessage': string, + 'x509InfoTitle': string, } export const helpwaveIdTranslation: Translation> = { 'de': { + 'acceptTerms': `Ich akzeptiere die Allgemeinen Geschäftsbedingungen`, + 'backToApplication': `Zurück zur Anwendung`, + 'backToLogin': `Zurück zur Anmeldung`, + 'deleteAccountConfirm': `Möchten Sie Ihr Konto wirklich löschen?`, + 'deleteCredentialConfirm': `Möchten Sie diese Anmeldedaten wirklich löschen?`, + 'doAccept': `Akzeptieren`, + 'doCancel': `Abbrechen`, + 'doClickHere': `Hier klicken`, + 'doContinue': `Weiter`, + 'doDecline': `Ablehnen`, + 'doDelete': `Löschen`, + 'doDeleteAccount': `Konto löschen`, + 'doForgotPassword': `Passwort vergessen?`, + 'doLink': `Verknüpfen`, + 'doLogIn': `Anmelden`, + 'doLogout': `Abmelden`, + 'doOverride': `Überschreiben`, + 'doRegister': `Registrieren`, + 'doRestart': `Neu starten`, + 'doSubmit': `Absenden`, + 'email': `E-Mail`, + 'emailVerificationBody': `Bitte überprüfen Sie Ihre E-Mail für einen Bestätigungslink.`, + 'emailVerificationBody1': `Bitte überprüfen Sie Ihre E-Mail für einen Bestätigungslink.`, + 'forgotPassword': `Passwort vergessen?`, + 'frontchannelLogoutMessage': `Abmelden...`, 'helpwaveId': `helpwave id`, + 'identity-provider-redirector': `Oder anmelden mit`, + 'idpLinkConfirmMessage': `Möchten Sie diesen Identitätsanbieter mit Ihrem Konto verknüpfen?`, + 'idpLinkConfirmOverrideMessage': `Dieser Identitätsanbieter ist bereits mit einem anderen Konto verknüpft. Möchten Sie dies überschreiben?`, + 'imprint': `Impressum`, + 'linkIdpMessage': `Identitätsanbieter verknüpfen...`, + 'loginOtp': `Bestätigungscode`, + 'loginTotpOneTime': `Einmalcode`, + 'loginTotpScanBarcode': `Scannen Sie diesen QR-Code mit Ihrer Authenticator-App`, + 'logoutConfirmHeader': `Möchten Sie sich wirklich abmelden?`, + 'noAccount': `Kein Konto?`, 'nOrganization': ({ count }): string => { return TranslationGen.resolvePlural(count, { '=1': `${count} Organisation`, 'other': `${count} Organisationen`, }) - } + }, + 'oauth2DeviceVerifyUserCodeMessage': `Geben Sie den auf Ihrem Gerät angezeigten Benutzercode ein`, + 'oauthGrantMessage': `Die Anwendung fordert Zugriff auf Ihr Konto an`, + 'oauthGrantScopes': `Angeforderte Berechtigungen`, + 'oauthGrantTitle': `Zugriff gewähren`, + 'otp': `Einmalpasswort`, + 'pageExpiredMessage': `Diese Seite ist abgelaufen. Bitte starten Sie den Anmeldevorgang neu.`, + 'passkeysConditionalAuthenticateMessage': `Authentifizierung mit Passkey...`, + 'password': `Passwort`, + 'passwordConfirm': `Passwort bestätigen`, + 'passwordNew': `Neues Passwort`, + 'privacy': `Datenschutz`, + 'recoveryAuthnCodeConfigMessage': `Konfigurieren Sie Ihren Wiederherstellungsauthentifizierungscode`, + 'recoveryCode': `Wiederherstellungscode`, + 'register': `Registrieren`, + 'rememberMe': `Angemeldet bleiben`, + 'resetOtpMessage': `Ihr OTP wurde zurückgesetzt. Bitte konfigurieren Sie ein neues.`, + 'samlPostFormMessage': `Weiterleitung zum Identitätsanbieter...`, + 'selectAuthenticatorTitle': `Authentifikator auswählen`, + 'selectOrganizationTitle': `Organisation auswählen`, + 'termsText': `Allgemeine Geschäftsbedingungen Text`, + 'userCode': `Benutzercode`, + 'username': `Benutzername`, + 'usernameOrEmail': `Benutzername oder E-Mail`, + 'webauthnAuthenticateMessage': `Authentifizieren Sie sich mit Ihrem Sicherheitsschlüssel`, + 'webauthnErrorMessage': `Ein Fehler ist bei der WebAuthn-Authentifizierung aufgetreten`, + 'webauthnRegisterMessage': `Registrieren Sie Ihren Sicherheitsschlüssel`, + 'x509InfoMessage': `Bitte geben Sie Ihre X.509 Zertifikatsinformationen an`, + 'x509InfoTitle': `X.509 Zertifikatsinformationen` }, 'en': { + 'acceptTerms': `I accept the terms and conditions`, + 'backToApplication': `Back to Application`, + 'backToLogin': `Back to Login`, + 'deleteAccountConfirm': `Are you sure you want to delete your account?`, + 'deleteCredentialConfirm': `Are you sure you want to delete this credential?`, + 'doAccept': `Accept`, + 'doCancel': `Cancel`, + 'doClickHere': `Click here`, + 'doContinue': `Continue`, + 'doDecline': `Decline`, + 'doDelete': `Delete`, + 'doDeleteAccount': `Delete Account`, + 'doForgotPassword': `Forgot Password?`, + 'doLink': `Link`, + 'doLogIn': `Log In`, + 'doLogout': `Logout`, + 'doOverride': `Override`, + 'doRegister': `Register`, + 'doRestart': `Restart`, + 'doSubmit': `Submit`, + 'email': `Email`, + 'emailVerificationBody': `Please check your email for a verification link.`, + 'emailVerificationBody1': `Please check your email for a verification link.`, + 'forgotPassword': `Forgot Password?`, + 'frontchannelLogoutMessage': `Logging out...`, 'helpwaveId': `helpwave id`, + 'identity-provider-redirector': `Or sign in with`, + 'idpLinkConfirmMessage': `Do you want to link this identity provider to your account?`, + 'idpLinkConfirmOverrideMessage': `This identity provider is already linked to another account. Do you want to override it?`, + 'imprint': `Imprint`, + 'linkIdpMessage': `Linking identity provider...`, + 'loginOtp': `Verification Code`, + 'loginTotpOneTime': `One-time code`, + 'loginTotpScanBarcode': `Scan this QR code with your authenticator app`, + 'logoutConfirmHeader': `Are you sure you want to logout?`, + 'noAccount': `No account?`, 'nOrganization': ({ count }): string => { return TranslationGen.resolvePlural(count, { '=1': `${count} Organization`, 'other': `${count} Organizations`, }) - } + }, + 'oauth2DeviceVerifyUserCodeMessage': `Enter the user code displayed on your device`, + 'oauthGrantMessage': `The application requests access to your account`, + 'oauthGrantScopes': `Requested Scopes`, + 'oauthGrantTitle': `Grant Access`, + 'otp': `One-time password`, + 'pageExpiredMessage': `This page has expired. Please restart the login process.`, + 'passkeysConditionalAuthenticateMessage': `Authenticating with passkey...`, + 'password': `Password`, + 'passwordConfirm': `Password Confirmation`, + 'passwordNew': `New Password`, + 'privacy': `Privacy`, + 'recoveryAuthnCodeConfigMessage': `Configure your recovery authentication code`, + 'recoveryCode': `Recovery Code`, + 'register': `Register`, + 'rememberMe': `Remember me`, + 'resetOtpMessage': `Your OTP has been reset. Please configure a new one.`, + 'samlPostFormMessage': `Redirecting to identity provider...`, + 'selectAuthenticatorTitle': `Select Authenticator`, + 'selectOrganizationTitle': `Select Organization`, + 'termsText': `Terms and conditions text`, + 'userCode': `User Code`, + 'username': `Username`, + 'usernameOrEmail': `Username or Email`, + 'webauthnAuthenticateMessage': `Authenticate with your security key`, + 'webauthnErrorMessage': `An error occurred during WebAuthn authentication`, + 'webauthnRegisterMessage': `Register your security key`, + 'x509InfoMessage': `Please provide your X.509 certificate information`, + 'x509InfoTitle': `X.509 Certificate Information` } } diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..57d4fa7 --- /dev/null +++ b/src/index.css @@ -0,0 +1,14 @@ +@import "tailwindcss"; + +:root { + --hw-color-secondary-50: #f9fafb; + --hw-color-secondary-100: #f3f4f6; + --hw-color-secondary-200: #e5e7eb; + --hw-color-secondary-300: #d1d5db; + --hw-color-secondary-400: #9ca3af; + --hw-color-secondary-500: #6b7280; + --hw-color-secondary-600: #4b5563; + --hw-color-secondary-700: #374151; + --hw-color-secondary-800: #1f2937; + --hw-color-secondary-900: #111827; +} diff --git a/src/login/KcPage.tsx b/src/login/KcPage.tsx index c7ebf36..aad93e5 100644 --- a/src/login/KcPage.tsx +++ b/src/login/KcPage.tsx @@ -3,6 +3,41 @@ import type { KcContext } from './KcContext' import Login from './pages/Login' import Register from './pages/Register' import ForgotPassword from './pages/ForgotPassword' +import Info from './pages/Info' +import Error from './pages/Error' +import Code from './pages/Code' +import LogoutConfirm from './pages/LogoutConfirm' +import Terms from './pages/Terms' +import LoginOtp from './pages/LoginOtp' +import LoginUpdatePassword from './pages/LoginUpdatePassword' +import LoginVerifyEmail from './pages/LoginVerifyEmail' +import DeleteAccountConfirm from './pages/DeleteAccountConfirm' +import DeleteCredential from './pages/DeleteCredential' +import FrontchannelLogout from './pages/FrontchannelLogout' +import IdpReviewUserProfile from './pages/IdpReviewUserProfile' +import LinkIdpAction from './pages/LinkIdpAction' +import LoginConfigTotp from './pages/LoginConfigTotp' +import LoginIdpLinkConfirm from './pages/LoginIdpLinkConfirm' +import LoginIdpLinkConfirmOverride from './pages/LoginIdpLinkConfirmOverride' +import LoginIdpLinkEmail from './pages/LoginIdpLinkEmail' +import LoginOauth2DeviceVerifyUserCode from './pages/LoginOauth2DeviceVerifyUserCode' +import LoginOauthGrant from './pages/LoginOauthGrant' +import LoginPageExpired from './pages/LoginPageExpired' +import LoginPasskeysConditionalAuthenticate from './pages/LoginPasskeysConditionalAuthenticate' +import LoginPassword from './pages/LoginPassword' +import LoginRecoveryAuthnCodeConfig from './pages/LoginRecoveryAuthnCodeConfig' +import LoginRecoveryAuthnCodeInput from './pages/LoginRecoveryAuthnCodeInput' +import LoginResetOtp from './pages/LoginResetOtp' +import LoginUpdateProfile from './pages/LoginUpdateProfile' +import LoginUsername from './pages/LoginUsername' +import LoginX509Info from './pages/LoginX509Info' +import SamlPostForm from './pages/SamlPostForm' +import SelectAuthenticator from './pages/SelectAuthenticator' +import SelectOrganization from './pages/SelectOrganization' +import UpdateEmail from './pages/UpdateEmail' +import WebauthnAuthenticate from './pages/WebauthnAuthenticate' +import WebauthnError from './pages/WebauthnError' +import WebauthnRegister from './pages/WebauthnRegister' import { HelpwaveLogo } from '@helpwave/hightide' export default function KcPage(props: { kcContext: KcContext }) { @@ -24,6 +59,76 @@ export default function KcPage(props: { kcContext: KcContext }) { return case 'login-reset-password.ftl': return + case 'info.ftl': + return + case 'error.ftl': + return + case 'code.ftl': + return + case 'logout-confirm.ftl': + return + case 'terms.ftl': + return + case 'login-otp.ftl': + return + case 'login-update-password.ftl': + return + case 'login-verify-email.ftl': + return + case 'delete-account-confirm.ftl': + return + case 'delete-credential.ftl': + return + case 'frontchannel-logout.ftl': + return + case 'idp-review-user-profile.ftl': + return + case 'link-idp-action.ftl': + return + case 'login-config-totp.ftl': + return + case 'login-idp-link-confirm.ftl': + return + case 'login-idp-link-confirm-override.ftl': + return + case 'login-idp-link-email.ftl': + return + case 'login-oauth2-device-verify-user-code.ftl': + return + case 'login-oauth-grant.ftl': + return + case 'login-page-expired.ftl': + return + case 'login-passkeys-conditional-authenticate.ftl': + return + case 'login-password.ftl': + return + case 'login-recovery-authn-code-config.ftl': + return + case 'login-recovery-authn-code-input.ftl': + return + case 'login-reset-otp.ftl': + return + case 'login-update-profile.ftl': + return + case 'login-username.ftl': + return + case 'login-x509-info.ftl': + return + case 'saml-post-form.ftl': + return + case 'select-authenticator.ftl': + return + case 'select-organization.ftl': + return + case 'update-email.ftl': + return + case 'webauthn-authenticate.ftl': + return + case 'webauthn-error.ftl': + return + case 'webauthn-register.ftl': + return default: return (
diff --git a/src/login/components/Branding.tsx b/src/login/components/Branding.tsx new file mode 100644 index 0000000..6b0e11e --- /dev/null +++ b/src/login/components/Branding.tsx @@ -0,0 +1,12 @@ +import { HelpwaveLogo } from '@helpwave/hightide' + +export function Branding() { + return ( +
+ +
+ helpwave id +
+
+ ) +} \ No newline at end of file diff --git a/src/login/components/Footer.tsx b/src/login/components/Footer.tsx new file mode 100644 index 0000000..3a849af --- /dev/null +++ b/src/login/components/Footer.tsx @@ -0,0 +1,40 @@ +import type { KcContext } from '../KcContext' +import { useTranslation } from '../../i18n/useTranslation' + +type FooterProps = { + kcContext: KcContext, +} + +export function Footer({ kcContext }: FooterProps) { + const locale = kcContext.locale?.currentLanguageTag ?? 'en' + const t = useTranslation(locale) + + return ( + + ) +} \ No newline at end of file diff --git a/src/login/components/LanguageSwitcher.tsx b/src/login/components/LanguageSwitcher.tsx new file mode 100644 index 0000000..521b523 --- /dev/null +++ b/src/login/components/LanguageSwitcher.tsx @@ -0,0 +1,50 @@ +import { useState } from 'react' +import { Button, LanguageDialog } from '@helpwave/hightide' +import type { KcContext } from '../KcContext' +import { Languages } from 'lucide-react' + +type LanguageSwitcherProps = { + kcContext: KcContext, +} + +export function LanguageSwitcher({ kcContext }: LanguageSwitcherProps) { + const [isOpen, setIsOpen] = useState(false) + + const handleLanguageChange = (locale: string) => { + const url = new URL(window.location.href) + url.searchParams.set('kc_locale', locale) + window.location.href = url.toString() + } + + return ( + <> + + setIsOpen(false)} + > + {kcContext.locale?.supported?.map((lang: { languageTag: string, label: string, url: string }) => ( + + ))} + + + ) +} \ No newline at end of file diff --git a/src/login/components/PageLayout.tsx b/src/login/components/PageLayout.tsx new file mode 100644 index 0000000..13f7b63 --- /dev/null +++ b/src/login/components/PageLayout.tsx @@ -0,0 +1,44 @@ +import type { ReactNode } from 'react' +import type { KcContext } from '../KcContext' +import { Branding } from './Branding' +import { RealmChip } from './RealmChip' +import { ThemeSwitcher } from './ThemeSwitcher' +import { LanguageSwitcher } from './LanguageSwitcher' +import { Footer } from './Footer' +import { hideKeycloakStyles } from '../utils/hideKeycloakStyles' + +type PageLayoutProps = { + kcContext: KcContext, + children: ReactNode, +} + +export function PageLayout({ kcContext, children }: PageLayoutProps) { + return ( + <> + +
+
+ + +
+ +
+ + + +
+ {children} +
+
+ +
+
+ + ) +} \ No newline at end of file diff --git a/src/login/components/RealmChip.tsx b/src/login/components/RealmChip.tsx index ff39456..afac73d 100644 --- a/src/login/components/RealmChip.tsx +++ b/src/login/components/RealmChip.tsx @@ -1,12 +1,20 @@ -import { HelpwaveBadge } from '@helpwave/hightide' +import { Chip } from '@helpwave/hightide' import type { KcContext } from '../KcContext' +import { getRealmColor } from '../utils/realmColor' type RealmChipProps = { kcContext: KcContext, }; -export function RealmChip(_props: RealmChipProps) { +export function RealmChip({ kcContext }: RealmChipProps) { + const realmName = (kcContext.realm as { name?: string, realm?: string })?.realm ?? + (kcContext.realm as { name?: string })?.name ?? + 'unknown' + const color = getRealmColor(realmName) + return ( - + + {realmName} + ) } \ No newline at end of file diff --git a/src/login/components/ThemeSwitcher.tsx b/src/login/components/ThemeSwitcher.tsx new file mode 100644 index 0000000..a3e3557 --- /dev/null +++ b/src/login/components/ThemeSwitcher.tsx @@ -0,0 +1,22 @@ +import { useState } from 'react' +import { Button, ThemeDialog } from '@helpwave/hightide' +import { Palette } from 'lucide-react' + +export function ThemeSwitcher() { + const [isOpen, setIsOpen] = useState(false) + + return ( + <> + + setIsOpen(false)} /> + + ) +} \ No newline at end of file diff --git a/src/login/pages/Code.tsx b/src/login/pages/Code.tsx new file mode 100644 index 0000000..cb593ae --- /dev/null +++ b/src/login/pages/Code.tsx @@ -0,0 +1,85 @@ +import { useState } from 'react' +import { Button, Input, FormFieldLayout } from '@helpwave/hightide' +import type { KcContext } from '../KcContext' +import { useI18n } from '../i18n' +import Template from 'keycloakify/login/Template' +import { PageLayout } from '../components/PageLayout' +import { useTranslation } from '../../i18n/useTranslation' + +type CodeProps = { + kcContext: Extract, +}; + +export default function Code({ kcContext }: CodeProps) { + const { i18n } = useI18n({ kcContext }) + const locale = kcContext.locale?.currentLanguageTag ?? 'en' + const t = useTranslation(locale) + const [code, setCode] = useState('') + + const codeError = kcContext.messagesPerField?.existsError('code') + ? kcContext.messagesPerField.get('code') + : undefined + + return ( + + ) +} \ No newline at end of file diff --git a/src/login/pages/DeleteAccountConfirm.tsx b/src/login/pages/DeleteAccountConfirm.tsx new file mode 100644 index 0000000..b83500f --- /dev/null +++ b/src/login/pages/DeleteAccountConfirm.tsx @@ -0,0 +1,41 @@ +import { Button } from '@helpwave/hightide' +import type { KcContext } from '../KcContext' +import { useI18n } from '../i18n' +import Template from 'keycloakify/login/Template' +import { PageLayout } from '../components/PageLayout' +import { useTranslation } from '../../i18n/useTranslation' + +type DeleteAccountConfirmProps = { + kcContext: Extract, +}; + +export default function DeleteAccountConfirm({ kcContext }: DeleteAccountConfirmProps) { + const { i18n } = useI18n({ kcContext }) + const locale = kcContext.locale?.currentLanguageTag ?? 'en' + const t = useTranslation(locale) + + return ( + + ) +} diff --git a/src/login/pages/DeleteCredential.tsx b/src/login/pages/DeleteCredential.tsx new file mode 100644 index 0000000..666eed0 --- /dev/null +++ b/src/login/pages/DeleteCredential.tsx @@ -0,0 +1,41 @@ +import { Button } from '@helpwave/hightide' +import type { KcContext } from '../KcContext' +import { useI18n } from '../i18n' +import Template from 'keycloakify/login/Template' +import { PageLayout } from '../components/PageLayout' +import { useTranslation } from '../../i18n/useTranslation' + +type DeleteCredentialProps = { + kcContext: Extract, +}; + +export default function DeleteCredential({ kcContext }: DeleteCredentialProps) { + const { i18n } = useI18n({ kcContext }) + const locale = kcContext.locale?.currentLanguageTag ?? 'en' + const t = useTranslation(locale) + + return ( + + ) +} diff --git a/src/login/pages/Error.tsx b/src/login/pages/Error.tsx new file mode 100644 index 0000000..49429c9 --- /dev/null +++ b/src/login/pages/Error.tsx @@ -0,0 +1,69 @@ +import { Button } from '@helpwave/hightide' +import type { KcContext } from '../KcContext' +import { useI18n } from '../i18n' +import Template from 'keycloakify/login/Template' +import { PageLayout } from '../components/PageLayout' +import { ArrowLeft } from 'lucide-react' +import { useTranslation } from '../../i18n/useTranslation' + +type ErrorProps = { + kcContext: Extract, +}; + +export default function Error({ kcContext }: ErrorProps) { + const { i18n } = useI18n({ kcContext }) + const locale = kcContext.locale?.currentLanguageTag ?? 'en' + const t = useTranslation(locale) + + return ( + + ) +} \ No newline at end of file diff --git a/src/login/pages/ForgotPassword.tsx b/src/login/pages/ForgotPassword.tsx index 332f0d8..5116ce0 100644 --- a/src/login/pages/ForgotPassword.tsx +++ b/src/login/pages/ForgotPassword.tsx @@ -3,7 +3,9 @@ import { Button, Input, FormFieldLayout } from '@helpwave/hightide' import type { KcContext } from '../KcContext' import { useI18n } from '../i18n' import Template from 'keycloakify/login/Template' -import { RealmChip } from '../components/RealmChip' +import { PageLayout } from '../components/PageLayout' +import { ArrowLeft } from 'lucide-react' +import { useTranslation } from '../../i18n/useTranslation' type ForgotPasswordProps = { kcContext: Extract, @@ -11,6 +13,8 @@ type ForgotPasswordProps = { export default function ForgotPassword({ kcContext }: ForgotPasswordProps) { const { i18n } = useI18n({ kcContext }) + const locale = kcContext.locale?.currentLanguageTag ?? 'en' + const t = useTranslation(locale) const [username, setUsername] = useState(kcContext.auth?.attemptedUsername ?? '') const usernameError = kcContext.messagesPerField?.existsError('username') @@ -20,43 +24,14 @@ export default function ForgotPassword({ kcContext }: ForgotPasswordProps) { const message = kcContext.message return ( - <> - -