#754: PasswordWrapper fix for React 19
This commit is contained in:
parent
e788c46601
commit
cb358bd745
@ -1,6 +1,7 @@
|
|||||||
import type { JSX } from "keycloakify/tools/JSX";
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useEffect, useReducer, Fragment } from "react";
|
import { useEffect, Fragment } from "react";
|
||||||
import { assert } from "keycloakify/tools/assert";
|
import { assert } from "keycloakify/tools/assert";
|
||||||
|
import { useIsPasswordRevealed } from "keycloakify/tools/useIsPasswordRevealed";
|
||||||
import type { KcClsx } from "keycloakify/login/lib/kcClsx";
|
import type { KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import {
|
import {
|
||||||
useUserProfileForm,
|
useUserProfileForm,
|
||||||
@ -249,15 +250,7 @@ function PasswordWrapper(props: { kcClsx: KcClsx; i18n: I18n; passwordInputId: s
|
|||||||
|
|
||||||
const { msgStr } = i18n;
|
const { msgStr } = i18n;
|
||||||
|
|
||||||
const [isPasswordRevealed, toggleIsPasswordRevealed] = useReducer((isPasswordRevealed: boolean) => !isPasswordRevealed, false);
|
const { isPasswordRevealed, toggleIsPasswordRevealed } = useIsPasswordRevealed({ passwordInputId });
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const passwordInputElement = document.getElementById(passwordInputId);
|
|
||||||
|
|
||||||
assert(passwordInputElement instanceof HTMLInputElement);
|
|
||||||
|
|
||||||
passwordInputElement.type = isPasswordRevealed ? "text" : "password";
|
|
||||||
}, [isPasswordRevealed]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={kcClsx("kcInputGroup")}>
|
<div className={kcClsx("kcInputGroup")}>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import type { JSX } from "keycloakify/tools/JSX";
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useState, useEffect, useReducer } from "react";
|
import { useState } from "react";
|
||||||
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
||||||
import { assert } from "keycloakify/tools/assert";
|
import { useIsPasswordRevealed } from "keycloakify/tools/useIsPasswordRevealed";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
import type { PageProps } from "keycloakify/login/pages/PageProps";
|
import type { PageProps } from "keycloakify/login/pages/PageProps";
|
||||||
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
@ -200,15 +200,7 @@ function PasswordWrapper(props: { kcClsx: KcClsx; i18n: I18n; passwordInputId: s
|
|||||||
|
|
||||||
const { msgStr } = i18n;
|
const { msgStr } = i18n;
|
||||||
|
|
||||||
const [isPasswordRevealed, toggleIsPasswordRevealed] = useReducer((isPasswordRevealed: boolean) => !isPasswordRevealed, false);
|
const { isPasswordRevealed, toggleIsPasswordRevealed } = useIsPasswordRevealed({ passwordInputId });
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const passwordInputElement = document.getElementById(passwordInputId);
|
|
||||||
|
|
||||||
assert(passwordInputElement instanceof HTMLInputElement);
|
|
||||||
|
|
||||||
passwordInputElement.type = isPasswordRevealed ? "text" : "password";
|
|
||||||
}, [isPasswordRevealed]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={kcClsx("kcInputGroup")}>
|
<div className={kcClsx("kcInputGroup")}>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import type { JSX } from "keycloakify/tools/JSX";
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useState, useEffect, useReducer } from "react";
|
import { useState } from "react";
|
||||||
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
import { assert } from "keycloakify/tools/assert";
|
import { useIsPasswordRevealed } from "keycloakify/tools/useIsPasswordRevealed";
|
||||||
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import type { PageProps } from "keycloakify/login/pages/PageProps";
|
import type { PageProps } from "keycloakify/login/pages/PageProps";
|
||||||
import type { KcContext } from "../KcContext";
|
import type { KcContext } from "../KcContext";
|
||||||
@ -107,15 +107,7 @@ function PasswordWrapper(props: { kcClsx: KcClsx; i18n: I18n; passwordInputId: s
|
|||||||
|
|
||||||
const { msgStr } = i18n;
|
const { msgStr } = i18n;
|
||||||
|
|
||||||
const [isPasswordRevealed, toggleIsPasswordRevealed] = useReducer((isPasswordRevealed: boolean) => !isPasswordRevealed, false);
|
const { isPasswordRevealed, toggleIsPasswordRevealed } = useIsPasswordRevealed({ passwordInputId });
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const passwordInputElement = document.getElementById(passwordInputId);
|
|
||||||
|
|
||||||
assert(passwordInputElement instanceof HTMLInputElement);
|
|
||||||
|
|
||||||
passwordInputElement.type = isPasswordRevealed ? "text" : "password";
|
|
||||||
}, [isPasswordRevealed]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={kcClsx("kcInputGroup")}>
|
<div className={kcClsx("kcInputGroup")}>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import type { JSX } from "keycloakify/tools/JSX";
|
import type { JSX } from "keycloakify/tools/JSX";
|
||||||
import { useEffect, useReducer } from "react";
|
import { useIsPasswordRevealed } from "keycloakify/tools/useIsPasswordRevealed";
|
||||||
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
import { kcSanitize } from "keycloakify/lib/kcSanitize";
|
||||||
import { assert } from "keycloakify/tools/assert";
|
|
||||||
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import type { PageProps } from "keycloakify/login/pages/PageProps";
|
import type { PageProps } from "keycloakify/login/pages/PageProps";
|
||||||
import type { KcContext } from "../KcContext";
|
import type { KcContext } from "../KcContext";
|
||||||
@ -146,15 +145,7 @@ function PasswordWrapper(props: { kcClsx: KcClsx; i18n: I18n; passwordInputId: s
|
|||||||
|
|
||||||
const { msgStr } = i18n;
|
const { msgStr } = i18n;
|
||||||
|
|
||||||
const [isPasswordRevealed, toggleIsPasswordRevealed] = useReducer((isPasswordRevealed: boolean) => !isPasswordRevealed, false);
|
const { isPasswordRevealed, toggleIsPasswordRevealed } = useIsPasswordRevealed({ passwordInputId });
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const passwordInputElement = document.getElementById(passwordInputId);
|
|
||||||
|
|
||||||
assert(passwordInputElement instanceof HTMLInputElement);
|
|
||||||
|
|
||||||
passwordInputElement.type = isPasswordRevealed ? "text" : "password";
|
|
||||||
}, [isPasswordRevealed]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={kcClsx("kcInputGroup")}>
|
<div className={kcClsx("kcInputGroup")}>
|
||||||
|
45
src/tools/useIsPasswordRevealed.ts
Normal file
45
src/tools/useIsPasswordRevealed.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { useEffect, useReducer } from "react";
|
||||||
|
import { assert } from "keycloakify/tools/assert";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initially false, state that enables to dynamically control if
|
||||||
|
* the type of a password input is "password" (false) or "text" (true).
|
||||||
|
*/
|
||||||
|
export function useIsPasswordRevealed(params: { passwordInputId: string }) {
|
||||||
|
const { passwordInputId } = params;
|
||||||
|
|
||||||
|
const [isPasswordRevealed, toggleIsPasswordRevealed] = useReducer(
|
||||||
|
(isPasswordRevealed: boolean) => !isPasswordRevealed,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const passwordInputElement = document.getElementById(passwordInputId);
|
||||||
|
|
||||||
|
assert(passwordInputElement instanceof HTMLInputElement);
|
||||||
|
|
||||||
|
const type = isPasswordRevealed ? "text" : "password";
|
||||||
|
|
||||||
|
passwordInputElement.type = type;
|
||||||
|
|
||||||
|
const observer = new MutationObserver(mutations => {
|
||||||
|
mutations.forEach(mutation => {
|
||||||
|
if (mutation.attributeName !== "type") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (passwordInputElement.type === type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
passwordInputElement.type = type;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(passwordInputElement, { attributes: true });
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
observer.disconnect();
|
||||||
|
};
|
||||||
|
}, [isPasswordRevealed]);
|
||||||
|
|
||||||
|
return { isPasswordRevealed, toggleIsPasswordRevealed };
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user