getClassName -> kcClsx
This commit is contained in:
@ -2,7 +2,6 @@ import { lazy, Suspense } from "react";
|
|||||||
import { assert, type Equals } from "tsafe/assert";
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
||||||
import type { KcContext } from "./KcContext";
|
import type { KcContext } from "./KcContext";
|
||||||
import type { I18n } from "./i18n";
|
|
||||||
|
|
||||||
const Password = lazy(() => import("keycloakify/account/pages/Password"));
|
const Password = lazy(() => import("keycloakify/account/pages/Password"));
|
||||||
const Account = lazy(() => import("keycloakify/account/pages/Account"));
|
const Account = lazy(() => import("keycloakify/account/pages/Account"));
|
||||||
@ -12,7 +11,7 @@ const Applications = lazy(() => import("keycloakify/account/pages/Applications")
|
|||||||
const Log = lazy(() => import("keycloakify/account/pages/Log"));
|
const Log = lazy(() => import("keycloakify/account/pages/Log"));
|
||||||
const FederatedIdentity = lazy(() => import("keycloakify/account/pages/FederatedIdentity"));
|
const FederatedIdentity = lazy(() => import("keycloakify/account/pages/FederatedIdentity"));
|
||||||
|
|
||||||
export default function Fallback(props: PageProps<KcContext, I18n>) {
|
export default function Fallback(props: PageProps<KcContext>) {
|
||||||
const { kcContext, ...rest } = props;
|
const { kcContext, ...rest } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { assert } from "keycloakify/tools/assert";
|
import { assert } from "keycloakify/tools/assert";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
import { useGetClassName } from "keycloakify/account/lib/useGetClassName";
|
import { getKcClsx } from "keycloakify/account/lib/kcClsx";
|
||||||
import { useInsertLinkTags } from "keycloakify/tools/useInsertLinkTags";
|
import { useInsertLinkTags } from "keycloakify/tools/useInsertLinkTags";
|
||||||
import { useSetClassName } from "keycloakify/tools/useSetClassName";
|
import { useSetClassName } from "keycloakify/tools/useSetClassName";
|
||||||
import type { TemplateProps } from "keycloakify/account/TemplateProps";
|
import type { TemplateProps } from "keycloakify/account/TemplateProps";
|
||||||
@ -11,7 +11,7 @@ import { useI18n } from "./i18n";
|
|||||||
export default function Template(props: TemplateProps<KcContext>) {
|
export default function Template(props: TemplateProps<KcContext>) {
|
||||||
const { kcContext, doUseDefaultCss, active, classes, children } = props;
|
const { kcContext, doUseDefaultCss, active, classes, children } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({ doUseDefaultCss, classes });
|
const { kcClsx } = getKcClsx({ doUseDefaultCss, classes });
|
||||||
|
|
||||||
const { msg, msgStr, getChangeLocalUrl, labelBySupportedLanguageTag, currentLanguageTag } = useI18n({ kcContext });
|
const { msg, msgStr, getChangeLocalUrl, labelBySupportedLanguageTag, currentLanguageTag } = useI18n({ kcContext });
|
||||||
|
|
||||||
@ -23,12 +23,12 @@ export default function Template(props: TemplateProps<KcContext>) {
|
|||||||
|
|
||||||
useSetClassName({
|
useSetClassName({
|
||||||
qualifiedName: "html",
|
qualifiedName: "html",
|
||||||
className: getClassName("kcHtmlClass")
|
className: kcClsx("kcHtmlClass")
|
||||||
});
|
});
|
||||||
|
|
||||||
useSetClassName({
|
useSetClassName({
|
||||||
qualifiedName: "body",
|
qualifiedName: "body",
|
||||||
className: clsx("admin-console", "user", getClassName("kcBodyClass"))
|
className: clsx("admin-console", "user", kcClsx("kcBodyClass"))
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createUseClassName } from "keycloakify/lib/useGetClassName";
|
import { createGetKcClsx } from "keycloakify/lib/getKcClsx";
|
||||||
import type { ClassKey } from "keycloakify/account/TemplateProps";
|
import type { ClassKey } from "keycloakify/account/TemplateProps";
|
||||||
|
|
||||||
export const { useGetClassName } = createUseClassName<ClassKey>({
|
export const { getKcClsx } = createGetKcClsx<ClassKey>({
|
||||||
defaultClasses: {
|
defaultClasses: {
|
||||||
kcHtmlClass: undefined,
|
kcHtmlClass: undefined,
|
||||||
kcBodyClass: undefined,
|
kcBodyClass: undefined,
|
||||||
@ -19,3 +19,7 @@ export const { useGetClassName } = createUseClassName<ClassKey>({
|
|||||||
"pf-c-form__helper-text pf-m-error required kc-feedback-text"
|
"pf-c-form__helper-text pf-m-error required kc-feedback-text"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export type { ClassKey };
|
||||||
|
|
||||||
|
export type KcClsx = ReturnType<typeof getKcClsx>["kcClsx"];
|
@ -1,18 +1,20 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
||||||
import { useGetClassName } from "keycloakify/account/lib/useGetClassName";
|
import { getKcClsx } from "keycloakify/account/lib/kcClsx";
|
||||||
import type { KcContext } from "../KcContext";
|
import type { KcContext } from "../KcContext";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
|
|
||||||
export default function Account(props: PageProps<Extract<KcContext, { pageId: "account.ftl" }>>) {
|
export default function Account(props: PageProps<Extract<KcContext, { pageId: "account.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const classes = {
|
||||||
|
...props.classes,
|
||||||
|
kcBodyClass: clsx(props.classes?.kcBodyClass, "user")
|
||||||
|
};
|
||||||
|
|
||||||
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes: {
|
classes
|
||||||
...classes,
|
|
||||||
kcBodyClass: clsx(classes?.kcBodyClass, "user")
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { url, realm, messagesPerField, stateChecker, account, referrer } = kcContext;
|
const { url, realm, messagesPerField, stateChecker, account, referrer } = kcContext;
|
||||||
@ -102,11 +104,7 @@ export default function Account(props: PageProps<Extract<KcContext, { pageId: "a
|
|||||||
{referrer !== undefined && <a href={referrer?.url}>{msg("backToApplication")}</a>}
|
{referrer !== undefined && <a href={referrer?.url}>{msg("backToApplication")}</a>}
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="submitAction"
|
name="submitAction"
|
||||||
value="Save"
|
value="Save"
|
||||||
>
|
>
|
||||||
@ -114,11 +112,7 @@ export default function Account(props: PageProps<Extract<KcContext, { pageId: "a
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="submitAction"
|
name="submitAction"
|
||||||
value="Cancel"
|
value="Cancel"
|
||||||
>
|
>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/account/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/account/lib/useGetClassName";
|
|
||||||
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
||||||
import type { KcContext } from "../KcContext";
|
import type { KcContext } from "../KcContext";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -7,7 +6,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function Applications(props: PageProps<Extract<KcContext, { pageId: "applications.ftl" }>>) {
|
export default function Applications(props: PageProps<Extract<KcContext, { pageId: "applications.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, classes, Template } = props;
|
const { kcContext, doUseDefaultCss, classes, Template } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -114,7 +113,7 @@ export default function Applications(props: PageProps<Extract<KcContext, { pageI
|
|||||||
application.additionalGrants.length > 0 ? (
|
application.additionalGrants.length > 0 ? (
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(getClassName("kcButtonPrimaryClass"), getClassName("kcButtonClass"))}
|
className={kcClsx("kcButtonPrimaryClass", "kcButtonClass")}
|
||||||
id={`revoke-${application.client.clientId}`}
|
id={`revoke-${application.client.clientId}`}
|
||||||
name="clientId"
|
name="clientId"
|
||||||
value={application.client.id}
|
value={application.client.id}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { Key } from "react";
|
import type { Key } from "react";
|
||||||
import { useGetClassName } from "keycloakify/account/lib/useGetClassName";
|
import { getKcClsx } from "keycloakify/account/lib/kcClsx";
|
||||||
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
||||||
import type { KcContext } from "../KcContext";
|
import type { KcContext } from "../KcContext";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -7,7 +7,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function Log(props: PageProps<Extract<KcContext, { pageId: "log.ftl" }>>) {
|
export default function Log(props: PageProps<Extract<KcContext, { pageId: "log.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, classes, Template } = props;
|
const { kcContext, doUseDefaultCss, classes, Template } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -18,7 +18,7 @@ export default function Log(props: PageProps<Extract<KcContext, { pageId: "log.f
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} active="log">
|
<Template {...{ kcContext, doUseDefaultCss, classes }} active="log">
|
||||||
<div className={getClassName("kcContentWrapperClass")}>
|
<div className={kcClsx("kcContentWrapperClass")}>
|
||||||
<div className="col-md-10">
|
<div className="col-md-10">
|
||||||
<h2>{msg("accountLogHtmlTitle")}</h2>
|
<h2>{msg("accountLogHtmlTitle")}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
import { useGetClassName } from "keycloakify/account/lib/useGetClassName";
|
import { getKcClsx } from "keycloakify/account/lib/kcClsx";
|
||||||
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
||||||
import type { KcContext } from "../KcContext";
|
import type { KcContext } from "../KcContext";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
|
|
||||||
export default function Password(props: PageProps<Extract<KcContext, { pageId: "password.ftl" }>>) {
|
export default function Password(props: PageProps<Extract<KcContext, { pageId: "password.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const classes = {
|
||||||
|
...props.classes,
|
||||||
|
kcBodyClass: clsx(props.classes?.kcBodyClass, "password")
|
||||||
|
};
|
||||||
|
|
||||||
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes: {
|
classes
|
||||||
...classes,
|
|
||||||
kcBodyClass: clsx(classes?.kcBodyClass, "password")
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { url, password, account, stateChecker } = kcContext;
|
const { url, password, account, stateChecker } = kcContext;
|
||||||
@ -191,11 +193,7 @@ export default function Password(props: PageProps<Extract<KcContext, { pageId: "
|
|||||||
<button
|
<button
|
||||||
disabled={newPasswordError !== "" || newPasswordConfirmError !== ""}
|
disabled={newPasswordError !== "" || newPasswordConfirmError !== ""}
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="submitAction"
|
name="submitAction"
|
||||||
value="Save"
|
value="Save"
|
||||||
>
|
>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/account/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/account/lib/useGetClassName";
|
|
||||||
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
||||||
import type { KcContext } from "../KcContext";
|
import type { KcContext } from "../KcContext";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -7,7 +6,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function Sessions(props: PageProps<Extract<KcContext, { pageId: "sessions.ftl" }>>) {
|
export default function Sessions(props: PageProps<Extract<KcContext, { pageId: "sessions.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -17,7 +16,7 @@ export default function Sessions(props: PageProps<Extract<KcContext, { pageId: "
|
|||||||
const { msg } = useI18n({ kcContext });
|
const { msg } = useI18n({ kcContext });
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} active="sessions">
|
<Template {...{ kcContext, doUseDefaultCss, classes }} active="sessions">
|
||||||
<div className={getClassName("kcContentWrapperClass")}>
|
<div className={kcClsx("kcContentWrapperClass")}>
|
||||||
<div className="col-md-10">
|
<div className="col-md-10">
|
||||||
<h2>{msg("sessionsHtmlTitle")}</h2>
|
<h2>{msg("sessionsHtmlTitle")}</h2>
|
||||||
</div>
|
</div>
|
||||||
@ -56,7 +55,7 @@ export default function Sessions(props: PageProps<Extract<KcContext, { pageId: "
|
|||||||
|
|
||||||
<form action={url.sessionsUrl} method="post">
|
<form action={url.sessionsUrl} method="post">
|
||||||
<input type="hidden" id="stateChecker" name="stateChecker" value={stateChecker} />
|
<input type="hidden" id="stateChecker" name="stateChecker" value={stateChecker} />
|
||||||
<button id="logout-all-sessions" type="submit" className={clsx(getClassName("kcButtonDefaultClass"), getClassName("kcButtonClass"))}>
|
<button id="logout-all-sessions" type="submit" className={kcClsx("kcButtonDefaultClass", "kcButtonClass")}>
|
||||||
{msg("doLogOutAllSessions")}
|
{msg("doLogOutAllSessions")}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
import { useGetClassName } from "keycloakify/account/lib/useGetClassName";
|
import { getKcClsx } from "keycloakify/account/lib/kcClsx";
|
||||||
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
import type { PageProps } from "keycloakify/account/pages/PageProps";
|
||||||
import type { KcContext } from "../KcContext";
|
import type { KcContext } from "../KcContext";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -7,7 +7,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function Totp(props: PageProps<Extract<KcContext, { pageId: "totp.ftl" }>>) {
|
export default function Totp(props: PageProps<Extract<KcContext, { pageId: "totp.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -140,9 +140,9 @@ export default function Totp(props: PageProps<Extract<KcContext, { pageId: "totp
|
|||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
<hr />
|
<hr />
|
||||||
<form action={url.totpUrl} className={getClassName("kcFormClass")} id="kc-totp-settings-form" method="post">
|
<form action={url.totpUrl} className={kcClsx("kcFormClass")} id="kc-totp-settings-form" method="post">
|
||||||
<input type="hidden" id="stateChecker" name="stateChecker" value={stateChecker} />
|
<input type="hidden" id="stateChecker" name="stateChecker" value={stateChecker} />
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className="col-sm-2 col-md-2">
|
<div className="col-sm-2 col-md-2">
|
||||||
<label htmlFor="totp" className="control-label">
|
<label htmlFor="totp" className="control-label">
|
||||||
{msg("authenticatorCode")}
|
{msg("authenticatorCode")}
|
||||||
@ -155,12 +155,12 @@ export default function Totp(props: PageProps<Extract<KcContext, { pageId: "totp
|
|||||||
id="totp"
|
id="totp"
|
||||||
name="totp"
|
name="totp"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
aria-invalid={messagesPerField.existsError("totp")}
|
aria-invalid={messagesPerField.existsError("totp")}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{messagesPerField.existsError("totp") && (
|
{messagesPerField.existsError("totp") && (
|
||||||
<span id="input-error-otp-code" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error-otp-code" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.get("totp")}
|
{messagesPerField.get("totp")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@ -169,9 +169,9 @@ export default function Totp(props: PageProps<Extract<KcContext, { pageId: "totp
|
|||||||
{mode && <input type="hidden" id="mode" value={mode} />}
|
{mode && <input type="hidden" id="mode" value={mode} />}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className="col-sm-2 col-md-2">
|
<div className="col-sm-2 col-md-2">
|
||||||
<label htmlFor="userLabel" className={getClassName("kcLabelClass")}>
|
<label htmlFor="userLabel" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("totpDeviceName")}
|
{msg("totpDeviceName")}
|
||||||
</label>
|
</label>
|
||||||
{totp.otpCredentials.length >= 1 && <span className="required">*</span>}
|
{totp.otpCredentials.length >= 1 && <span className="required">*</span>}
|
||||||
@ -182,37 +182,28 @@ export default function Totp(props: PageProps<Extract<KcContext, { pageId: "totp
|
|||||||
id="userLabel"
|
id="userLabel"
|
||||||
name="userLabel"
|
name="userLabel"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
aria-invalid={messagesPerField.existsError("userLabel")}
|
aria-invalid={messagesPerField.existsError("userLabel")}
|
||||||
/>
|
/>
|
||||||
{messagesPerField.existsError("userLabel") && (
|
{messagesPerField.existsError("userLabel") && (
|
||||||
<span id="input-error-otp-label" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error-otp-label" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.get("userLabel")}
|
{messagesPerField.get("userLabel")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="kc-form-buttons" className={clsx(getClassName("kcFormGroupClass"), "text-right")}>
|
<div id="kc-form-buttons" className={clsx(kcClsx("kcFormGroupClass"), "text-right")}>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
id="saveTOTPBtn"
|
id="saveTOTPBtn"
|
||||||
value={msgStr("doSave")}
|
value={msgStr("doSave")}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonLargeClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
id="cancelTOTPBtn"
|
id="cancelTOTPBtn"
|
||||||
name="submitAction"
|
name="submitAction"
|
||||||
value="Cancel"
|
value="Cancel"
|
||||||
|
75
src/lib/getKcClsx.ts
Normal file
75
src/lib/getKcClsx.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import type { Param0 } from "tsafe";
|
||||||
|
import { type CxArg, clsx_withTransform } from "../tools/clsx_withTransform";
|
||||||
|
import { clsx } from "../tools/clsx";
|
||||||
|
import { assert } from "tsafe/assert";
|
||||||
|
import { is } from "tsafe/is";
|
||||||
|
|
||||||
|
export function createGetKcClsx<ClassKey extends string>(params: {
|
||||||
|
defaultClasses: Record<ClassKey, string | undefined>;
|
||||||
|
}) {
|
||||||
|
const { defaultClasses } = params;
|
||||||
|
|
||||||
|
function areSameParams(
|
||||||
|
params1: Param0<typeof getKcClsx>,
|
||||||
|
params2: Param0<typeof getKcClsx>
|
||||||
|
): boolean {
|
||||||
|
if (params1.doUseDefaultCss !== params2.doUseDefaultCss) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params1.classes === params2.classes) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.stringify(params1.classes) === JSON.stringify(params2.classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
let cache:
|
||||||
|
| {
|
||||||
|
params: Param0<typeof getKcClsx>;
|
||||||
|
result: ReturnType<typeof getKcClsx>;
|
||||||
|
}
|
||||||
|
| undefined = undefined;
|
||||||
|
|
||||||
|
function getKcClsx(params: {
|
||||||
|
doUseDefaultCss: boolean;
|
||||||
|
classes: Partial<Record<ClassKey, string>> | undefined;
|
||||||
|
}): { kcClsx: (...args: CxArg<ClassKey>[]) => string } {
|
||||||
|
// NOTE: We implement a cache here only so that getClassName can be stable across renders.
|
||||||
|
// We don't want to use useConstCallback because we want this to be useable outside of React.
|
||||||
|
use_cache: {
|
||||||
|
if (cache === undefined) {
|
||||||
|
break use_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!areSameParams(cache.params, params)) {
|
||||||
|
break use_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cache.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { classes, doUseDefaultCss } = params;
|
||||||
|
|
||||||
|
function kcClsx(...args: CxArg<ClassKey>[]): string {
|
||||||
|
return clsx_withTransform({
|
||||||
|
args,
|
||||||
|
transform: classKey => {
|
||||||
|
assert(is<ClassKey>(classKey));
|
||||||
|
|
||||||
|
return clsx(
|
||||||
|
classKey,
|
||||||
|
doUseDefaultCss ? defaultClasses[classKey] : undefined,
|
||||||
|
classes?.[classKey]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cache = { params, result: { kcClsx } };
|
||||||
|
|
||||||
|
return { kcClsx };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { getKcClsx };
|
||||||
|
}
|
@ -1,66 +0,0 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
|
||||||
import type { Param0 } from "tsafe";
|
|
||||||
|
|
||||||
// NOTE: Note for people trying to implement Keycloakify in other frontend
|
|
||||||
// frameworks. This can be used outside of React, useGetClassName isn't actually a hook.
|
|
||||||
|
|
||||||
export function createUseClassName<ClassKey extends string>(params: {
|
|
||||||
defaultClasses: Record<ClassKey, string | undefined>;
|
|
||||||
}) {
|
|
||||||
const { defaultClasses } = params;
|
|
||||||
|
|
||||||
function areSameParams(
|
|
||||||
params1: Param0<typeof useGetClassName>,
|
|
||||||
params2: Param0<typeof useGetClassName>
|
|
||||||
): boolean {
|
|
||||||
if (params1.doUseDefaultCss !== params2.doUseDefaultCss) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params1.classes === params2.classes) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return JSON.stringify(params1.classes) === JSON.stringify(params2.classes);
|
|
||||||
}
|
|
||||||
|
|
||||||
let cache:
|
|
||||||
| {
|
|
||||||
params: Param0<typeof useGetClassName>;
|
|
||||||
result: ReturnType<typeof useGetClassName>;
|
|
||||||
}
|
|
||||||
| undefined = undefined;
|
|
||||||
|
|
||||||
function useGetClassName(params: {
|
|
||||||
doUseDefaultCss: boolean;
|
|
||||||
classes: Partial<Record<ClassKey, string>> | undefined;
|
|
||||||
}): { getClassName: (classKey: ClassKey) => string } {
|
|
||||||
// NOTE: We implement a cache here only so that getClassName can be stable across renders.
|
|
||||||
// We don't want to use useConstCallback because we want this to be useable outside of React.
|
|
||||||
use_cache: {
|
|
||||||
if (cache === undefined) {
|
|
||||||
break use_cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!areSameParams(cache.params, params)) {
|
|
||||||
break use_cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cache.result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getClassName(classKey: ClassKey): string {
|
|
||||||
return clsx(
|
|
||||||
classKey,
|
|
||||||
params.doUseDefaultCss ? defaultClasses[classKey] : undefined,
|
|
||||||
params.classes?.[classKey]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
cache = { params, result: { getClassName } };
|
|
||||||
|
|
||||||
return { getClassName };
|
|
||||||
}
|
|
||||||
|
|
||||||
return { useGetClassName };
|
|
||||||
}
|
|
@ -2,7 +2,7 @@ import { useEffect } from "react";
|
|||||||
import { assert } from "keycloakify/tools/assert";
|
import { assert } from "keycloakify/tools/assert";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
import type { TemplateProps } from "keycloakify/login/TemplateProps";
|
import type { TemplateProps } from "keycloakify/login/TemplateProps";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
||||||
import { useInsertLinkTags } from "keycloakify/tools/useInsertLinkTags";
|
import { useInsertLinkTags } from "keycloakify/tools/useInsertLinkTags";
|
||||||
import { useSetClassName } from "keycloakify/tools/useSetClassName";
|
import { useSetClassName } from "keycloakify/tools/useSetClassName";
|
||||||
@ -26,7 +26,7 @@ export default function Template(props: TemplateProps<KcContext>) {
|
|||||||
children
|
children
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({ doUseDefaultCss, classes });
|
const { kcClsx } = getKcClsx({ doUseDefaultCss, classes });
|
||||||
|
|
||||||
const { msg, msgStr, getChangeLocalUrl, labelBySupportedLanguageTag, currentLanguageTag } = useI18n({ kcContext });
|
const { msg, msgStr, getChangeLocalUrl, labelBySupportedLanguageTag, currentLanguageTag } = useI18n({ kcContext });
|
||||||
|
|
||||||
@ -38,12 +38,12 @@ export default function Template(props: TemplateProps<KcContext>) {
|
|||||||
|
|
||||||
useSetClassName({
|
useSetClassName({
|
||||||
qualifiedName: "html",
|
qualifiedName: "html",
|
||||||
className: getClassName("kcHtmlClass")
|
className: kcClsx("kcHtmlClass")
|
||||||
});
|
});
|
||||||
|
|
||||||
useSetClassName({
|
useSetClassName({
|
||||||
qualifiedName: "body",
|
qualifiedName: "body",
|
||||||
className: bodyClassName ?? getClassName("kcBodyClass")
|
className: bodyClassName ?? kcClsx("kcBodyClass")
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -115,19 +115,19 @@ export default function Template(props: TemplateProps<KcContext>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={getClassName("kcLoginClass")}>
|
<div className={kcClsx("kcLoginClass")}>
|
||||||
<div id="kc-header" className={getClassName("kcHeaderClass")}>
|
<div id="kc-header" className={kcClsx("kcHeaderClass")}>
|
||||||
<div id="kc-header-wrapper" className={getClassName("kcHeaderWrapperClass")}>
|
<div id="kc-header-wrapper" className={kcClsx("kcHeaderWrapperClass")}>
|
||||||
{msg("loginTitleHtml", realm.displayNameHtml)}
|
{msg("loginTitleHtml", realm.displayNameHtml)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={getClassName("kcFormCardClass")}>
|
<div className={kcClsx("kcFormCardClass")}>
|
||||||
<header className={getClassName("kcFormHeaderClass")}>
|
<header className={kcClsx("kcFormHeaderClass")}>
|
||||||
{realm.internationalizationEnabled && (assert(locale !== undefined), locale.supported.length > 1) && (
|
{realm.internationalizationEnabled && (assert(locale !== undefined), locale.supported.length > 1) && (
|
||||||
<div className={getClassName("kcLocaleMainClass")} id="kc-locale">
|
<div className={kcClsx("kcLocaleMainClass")} id="kc-locale">
|
||||||
<div id="kc-locale-wrapper" className={getClassName("kcLocaleWrapperClass")}>
|
<div id="kc-locale-wrapper" className={kcClsx("kcLocaleWrapperClass")}>
|
||||||
<div id="kc-locale-dropdown" className={clsx("menu-button-links", getClassName("kcLocaleDropDownClass"))}>
|
<div id="kc-locale-dropdown" className={clsx("menu-button-links", kcClsx("kcLocaleDropDownClass"))}>
|
||||||
<button
|
<button
|
||||||
tabIndex={1}
|
tabIndex={1}
|
||||||
id="kc-current-locale-link"
|
id="kc-current-locale-link"
|
||||||
@ -144,14 +144,14 @@ export default function Template(props: TemplateProps<KcContext>) {
|
|||||||
aria-labelledby="kc-current-locale-link"
|
aria-labelledby="kc-current-locale-link"
|
||||||
aria-activedescendant=""
|
aria-activedescendant=""
|
||||||
id="language-switch1"
|
id="language-switch1"
|
||||||
className={getClassName("kcLocaleListClass")}
|
className={kcClsx("kcLocaleListClass")}
|
||||||
>
|
>
|
||||||
{locale.supported.map(({ languageTag }, i) => (
|
{locale.supported.map(({ languageTag }, i) => (
|
||||||
<li key={languageTag} className={getClassName("kcLocaleListItemClass")} role="none">
|
<li key={languageTag} className={kcClsx("kcLocaleListItemClass")} role="none">
|
||||||
<a
|
<a
|
||||||
role="menuitem"
|
role="menuitem"
|
||||||
id={`language-${i + 1}`}
|
id={`language-${i + 1}`}
|
||||||
className={getClassName("kcLocaleItemClass")}
|
className={kcClsx("kcLocaleItemClass")}
|
||||||
href={getChangeLocalUrl(languageTag)}
|
href={getChangeLocalUrl(languageTag)}
|
||||||
>
|
>
|
||||||
{labelBySupportedLanguageTag[languageTag]}
|
{labelBySupportedLanguageTag[languageTag]}
|
||||||
@ -165,8 +165,8 @@ export default function Template(props: TemplateProps<KcContext>) {
|
|||||||
)}
|
)}
|
||||||
{!(auth !== undefined && auth.showUsername && !auth.showResetCredentials) ? (
|
{!(auth !== undefined && auth.showUsername && !auth.showResetCredentials) ? (
|
||||||
displayRequiredFields ? (
|
displayRequiredFields ? (
|
||||||
<div className={getClassName("kcContentWrapperClass")}>
|
<div className={kcClsx("kcContentWrapperClass")}>
|
||||||
<div className={clsx(getClassName("kcLabelWrapperClass"), "subtitle")}>
|
<div className={clsx(kcClsx("kcLabelWrapperClass"), "subtitle")}>
|
||||||
<span className="subtitle">
|
<span className="subtitle">
|
||||||
<span className="required">*</span>
|
<span className="required">*</span>
|
||||||
{msg("requiredFields")}
|
{msg("requiredFields")}
|
||||||
@ -180,19 +180,19 @@ export default function Template(props: TemplateProps<KcContext>) {
|
|||||||
<h1 id="kc-page-title">{headerNode}</h1>
|
<h1 id="kc-page-title">{headerNode}</h1>
|
||||||
)
|
)
|
||||||
) : displayRequiredFields ? (
|
) : displayRequiredFields ? (
|
||||||
<div className={getClassName("kcContentWrapperClass")}>
|
<div className={kcClsx("kcContentWrapperClass")}>
|
||||||
<div className={clsx(getClassName("kcLabelWrapperClass"), "subtitle")}>
|
<div className={clsx(kcClsx("kcLabelWrapperClass"), "subtitle")}>
|
||||||
<span className="subtitle">
|
<span className="subtitle">
|
||||||
<span className="required">*</span> {msg("requiredFields")}
|
<span className="required">*</span> {msg("requiredFields")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-10">
|
<div className="col-md-10">
|
||||||
{showUsernameNode}
|
{showUsernameNode}
|
||||||
<div id="kc-username" className={getClassName("kcFormGroupClass")}>
|
<div id="kc-username" className={kcClsx("kcFormGroupClass")}>
|
||||||
<label id="kc-attempted-username">{auth.attemptedUsername}</label>
|
<label id="kc-attempted-username">{auth.attemptedUsername}</label>
|
||||||
<a id="reset-login" href={url.loginRestartFlowUrl} aria-label={msgStr("restartLoginTooltip")}>
|
<a id="reset-login" href={url.loginRestartFlowUrl} aria-label={msgStr("restartLoginTooltip")}>
|
||||||
<div className="kc-login-tooltip">
|
<div className="kc-login-tooltip">
|
||||||
<i className={getClassName("kcResetFlowIcon")}></i>
|
<i className={kcClsx("kcResetFlowIcon")}></i>
|
||||||
<span className="kc-tooltip-text">{msg("restartLoginTooltip")}</span>
|
<span className="kc-tooltip-text">{msg("restartLoginTooltip")}</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
@ -202,11 +202,11 @@ export default function Template(props: TemplateProps<KcContext>) {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{showUsernameNode}
|
{showUsernameNode}
|
||||||
<div id="kc-username" className={getClassName("kcFormGroupClass")}>
|
<div id="kc-username" className={kcClsx("kcFormGroupClass")}>
|
||||||
<label id="kc-attempted-username">{auth.attemptedUsername}</label>
|
<label id="kc-attempted-username">{auth.attemptedUsername}</label>
|
||||||
<a id="reset-login" href={url.loginRestartFlowUrl} aria-label={msgStr("restartLoginTooltip")}>
|
<a id="reset-login" href={url.loginRestartFlowUrl} aria-label={msgStr("restartLoginTooltip")}>
|
||||||
<div className="kc-login-tooltip">
|
<div className="kc-login-tooltip">
|
||||||
<i className={getClassName("kcResetFlowIcon")}></i>
|
<i className={kcClsx("kcResetFlowIcon")}></i>
|
||||||
<span className="kc-tooltip-text">{msg("restartLoginTooltip")}</span>
|
<span className="kc-tooltip-text">{msg("restartLoginTooltip")}</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
@ -221,18 +221,18 @@ export default function Template(props: TemplateProps<KcContext>) {
|
|||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
`alert-${message.type}`,
|
`alert-${message.type}`,
|
||||||
getClassName("kcAlertClass"),
|
kcClsx("kcAlertClass"),
|
||||||
`pf-m-${message?.type === "error" ? "danger" : message.type}`
|
`pf-m-${message?.type === "error" ? "danger" : message.type}`
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="pf-c-alert__icon">
|
<div className="pf-c-alert__icon">
|
||||||
{message.type === "success" && <span className={getClassName("kcFeedbackSuccessIcon")}></span>}
|
{message.type === "success" && <span className={kcClsx("kcFeedbackSuccessIcon")}></span>}
|
||||||
{message.type === "warning" && <span className={getClassName("kcFeedbackWarningIcon")}></span>}
|
{message.type === "warning" && <span className={kcClsx("kcFeedbackWarningIcon")}></span>}
|
||||||
{message.type === "error" && <span className={getClassName("kcFeedbackErrorIcon")}></span>}
|
{message.type === "error" && <span className={kcClsx("kcFeedbackErrorIcon")}></span>}
|
||||||
{message.type === "info" && <span className={getClassName("kcFeedbackInfoIcon")}></span>}
|
{message.type === "info" && <span className={kcClsx("kcFeedbackInfoIcon")}></span>}
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
className={getClassName("kcAlertTitleClass")}
|
className={kcClsx("kcAlertTitleClass")}
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: message.summary
|
__html: message.summary
|
||||||
}}
|
}}
|
||||||
@ -242,8 +242,8 @@ export default function Template(props: TemplateProps<KcContext>) {
|
|||||||
{children}
|
{children}
|
||||||
{auth !== undefined && auth.showTryAnotherWayLink && (
|
{auth !== undefined && auth.showTryAnotherWayLink && (
|
||||||
<form id="kc-select-try-another-way-form" action={url.loginAction} method="post">
|
<form id="kc-select-try-another-way-form" action={url.loginAction} method="post">
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<input type="hidden" name="tryAnotherWay" value="on" />
|
<input type="hidden" name="tryAnotherWay" value="on" />
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
@ -261,8 +261,8 @@ export default function Template(props: TemplateProps<KcContext>) {
|
|||||||
)}
|
)}
|
||||||
{socialProvidersNode}
|
{socialProvidersNode}
|
||||||
{displayInfo && (
|
{displayInfo && (
|
||||||
<div id="kc-info" className={getClassName("kcSignUpClass")}>
|
<div id="kc-info" className={kcClsx("kcSignUpClass")}>
|
||||||
<div id="kc-info-wrapper" className={getClassName("kcInfoAreaWrapperClass")}>
|
<div id="kc-info-wrapper" className={kcClsx("kcInfoAreaWrapperClass")}>
|
||||||
{infoNode}
|
{infoNode}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useReducer, Fragment } from "react";
|
import { useEffect, useReducer, Fragment } from "react";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import type { ClassKey } from "keycloakify/login/TemplateProps";
|
import type { KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import {
|
import {
|
||||||
useUserProfileForm,
|
useUserProfileForm,
|
||||||
getButtonToDisplayForMultivaluedAttributeField,
|
getButtonToDisplayForMultivaluedAttributeField,
|
||||||
@ -9,11 +9,11 @@ import {
|
|||||||
type FormFieldError
|
type FormFieldError
|
||||||
} from "keycloakify/login/lib/useUserProfileForm";
|
} from "keycloakify/login/lib/useUserProfileForm";
|
||||||
import type { Attribute } from "keycloakify/login/KcContext";
|
import type { Attribute } from "keycloakify/login/KcContext";
|
||||||
import { useI18n } from "./i18n";
|
import { useI18n, type I18n } from "./i18n";
|
||||||
|
|
||||||
export type UserProfileFormFieldsProps = {
|
export type UserProfileFormFieldsProps = {
|
||||||
kcContext: KcContextLike;
|
kcContext: KcContextLike;
|
||||||
getClassName: (classKey: ClassKey) => string;
|
kcClsx: KcClsx;
|
||||||
onIsFormSubmittableValueChange: (isFormSubmittable: boolean) => void;
|
onIsFormSubmittableValueChange: (isFormSubmittable: boolean) => void;
|
||||||
BeforeField?: (props: BeforeAfterFieldProps) => JSX.Element | null;
|
BeforeField?: (props: BeforeAfterFieldProps) => JSX.Element | null;
|
||||||
AfterField?: (props: BeforeAfterFieldProps) => JSX.Element | null;
|
AfterField?: (props: BeforeAfterFieldProps) => JSX.Element | null;
|
||||||
@ -23,24 +23,24 @@ type BeforeAfterFieldProps = {
|
|||||||
attribute: Attribute;
|
attribute: Attribute;
|
||||||
dispatchFormAction: React.Dispatch<FormAction>;
|
dispatchFormAction: React.Dispatch<FormAction>;
|
||||||
displayableErrors: FormFieldError[];
|
displayableErrors: FormFieldError[];
|
||||||
i18n: I18n;
|
|
||||||
valueOrValues: string | string[];
|
valueOrValues: string | string[];
|
||||||
|
kcClsx: KcClsx;
|
||||||
|
i18n: I18n;
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE: Enabled by default but it's a UX best practice to set it to false.
|
// NOTE: Enabled by default but it's a UX best practice to set it to false.
|
||||||
const doMakeUserConfirmPassword = true;
|
const doMakeUserConfirmPassword = true;
|
||||||
|
|
||||||
export default function UserProfileFormFields(props: UserProfileFormFieldsProps) {
|
export default function UserProfileFormFields(props: UserProfileFormFieldsProps) {
|
||||||
const { kcContext, onIsFormSubmittableValueChange, i18n, getClassName, BeforeField, AfterField } = props;
|
const { kcContext, kcClsx, onIsFormSubmittableValueChange, BeforeField, AfterField } = props;
|
||||||
|
|
||||||
const { advancedMsg } = i18n;
|
const { advancedMsg } = useI18n({ kcContext });
|
||||||
|
|
||||||
const {
|
const {
|
||||||
formState: { formFieldStates, isFormSubmittable },
|
formState: { formFieldStates, isFormSubmittable },
|
||||||
dispatchFormAction
|
dispatchFormAction
|
||||||
} = useUserProfileForm({
|
} = useUserProfileForm({
|
||||||
kcContext,
|
kcContext,
|
||||||
i18n,
|
|
||||||
doMakeUserConfirmPassword
|
doMakeUserConfirmPassword
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -48,6 +48,8 @@ export default function UserProfileFormFields(props: UserProfileFormFieldsProps)
|
|||||||
onIsFormSubmittableValueChange(isFormSubmittable);
|
onIsFormSubmittableValueChange(isFormSubmittable);
|
||||||
}, [isFormSubmittable]);
|
}, [isFormSubmittable]);
|
||||||
|
|
||||||
|
const i18n = useI18n({ kcContext });
|
||||||
|
|
||||||
const groupNameRef = { current: "" };
|
const groupNameRef = { current: "" };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -55,32 +57,33 @@ export default function UserProfileFormFields(props: UserProfileFormFieldsProps)
|
|||||||
{formFieldStates.map(({ attribute, displayableErrors, valueOrValues }) => {
|
{formFieldStates.map(({ attribute, displayableErrors, valueOrValues }) => {
|
||||||
return (
|
return (
|
||||||
<Fragment key={attribute.name}>
|
<Fragment key={attribute.name}>
|
||||||
<GroupLabel attribute={attribute} getClassName={getClassName} i18n={i18n} groupNameRef={groupNameRef} />
|
<GroupLabel attribute={attribute} groupNameRef={groupNameRef} i18n={i18n} kcClsx={kcClsx} />
|
||||||
{BeforeField !== undefined && (
|
{BeforeField !== undefined && (
|
||||||
<BeforeField
|
<BeforeField
|
||||||
attribute={attribute}
|
attribute={attribute}
|
||||||
dispatchFormAction={dispatchFormAction}
|
dispatchFormAction={dispatchFormAction}
|
||||||
displayableErrors={displayableErrors}
|
displayableErrors={displayableErrors}
|
||||||
i18n={i18n}
|
|
||||||
valueOrValues={valueOrValues}
|
valueOrValues={valueOrValues}
|
||||||
|
kcClsx={kcClsx}
|
||||||
|
i18n={i18n}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={getClassName("kcFormGroupClass")}
|
className={kcClsx("kcFormGroupClass")}
|
||||||
style={{
|
style={{
|
||||||
display: attribute.name === "password-confirm" && !doMakeUserConfirmPassword ? "none" : undefined
|
display: attribute.name === "password-confirm" && !doMakeUserConfirmPassword ? "none" : undefined
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label htmlFor={attribute.name} className={getClassName("kcLabelClass")}>
|
<label htmlFor={attribute.name} className={kcClsx("kcLabelClass")}>
|
||||||
{advancedMsg(attribute.displayName ?? "")}
|
{advancedMsg(attribute.displayName ?? "")}
|
||||||
</label>
|
</label>
|
||||||
{attribute.required && <>*</>}
|
{attribute.required && <>*</>}
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
{attribute.annotations.inputHelperTextBefore !== undefined && (
|
{attribute.annotations.inputHelperTextBefore !== undefined && (
|
||||||
<div
|
<div
|
||||||
className={getClassName("kcInputHelperTextBeforeClass")}
|
className={kcClsx("kcInputHelperTextBeforeClass")}
|
||||||
id={`form-help-text-before-${attribute.name}`}
|
id={`form-help-text-before-${attribute.name}`}
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
>
|
>
|
||||||
@ -91,19 +94,14 @@ export default function UserProfileFormFields(props: UserProfileFormFieldsProps)
|
|||||||
attribute={attribute}
|
attribute={attribute}
|
||||||
valueOrValues={valueOrValues}
|
valueOrValues={valueOrValues}
|
||||||
displayableErrors={displayableErrors}
|
displayableErrors={displayableErrors}
|
||||||
formValidationDispatch={dispatchFormAction}
|
dispatchFormAction={dispatchFormAction}
|
||||||
getClassName={getClassName}
|
kcClsx={kcClsx}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
/>
|
/>
|
||||||
<FieldErrors
|
<FieldErrors attribute={attribute} displayableErrors={displayableErrors} kcClsx={kcClsx} fieldIndex={undefined} />
|
||||||
attribute={attribute}
|
|
||||||
getClassName={getClassName}
|
|
||||||
displayableErrors={displayableErrors}
|
|
||||||
fieldIndex={undefined}
|
|
||||||
/>
|
|
||||||
{attribute.annotations.inputHelperTextAfter !== undefined && (
|
{attribute.annotations.inputHelperTextAfter !== undefined && (
|
||||||
<div
|
<div
|
||||||
className={getClassName("kcInputHelperTextAfterClass")}
|
className={kcClsx("kcInputHelperTextAfterClass")}
|
||||||
id={`form-help-text-after-${attribute.name}`}
|
id={`form-help-text-after-${attribute.name}`}
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
>
|
>
|
||||||
@ -116,8 +114,9 @@ export default function UserProfileFormFields(props: UserProfileFormFieldsProps)
|
|||||||
attribute={attribute}
|
attribute={attribute}
|
||||||
dispatchFormAction={dispatchFormAction}
|
dispatchFormAction={dispatchFormAction}
|
||||||
displayableErrors={displayableErrors}
|
displayableErrors={displayableErrors}
|
||||||
i18n={i18n}
|
|
||||||
valueOrValues={valueOrValues}
|
valueOrValues={valueOrValues}
|
||||||
|
kcClsx={kcClsx}
|
||||||
|
i18n={i18n}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{/* NOTE: Downloading of html5DataAnnotations scripts is done in the useUserProfileForm hook */}
|
{/* NOTE: Downloading of html5DataAnnotations scripts is done in the useUserProfileForm hook */}
|
||||||
@ -132,13 +131,13 @@ export default function UserProfileFormFields(props: UserProfileFormFieldsProps)
|
|||||||
|
|
||||||
function GroupLabel(props: {
|
function GroupLabel(props: {
|
||||||
attribute: Attribute;
|
attribute: Attribute;
|
||||||
getClassName: UserProfileFormFieldsProps["getClassName"];
|
|
||||||
i18n: I18n;
|
|
||||||
groupNameRef: {
|
groupNameRef: {
|
||||||
current: string;
|
current: string;
|
||||||
};
|
};
|
||||||
|
i18n: I18n;
|
||||||
|
kcClsx: KcClsx;
|
||||||
}) {
|
}) {
|
||||||
const { attribute, getClassName, i18n, groupNameRef } = props;
|
const { attribute, groupNameRef, i18n, kcClsx } = props;
|
||||||
|
|
||||||
const { advancedMsg } = i18n;
|
const { advancedMsg } = i18n;
|
||||||
|
|
||||||
@ -150,7 +149,7 @@ function GroupLabel(props: {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={getClassName("kcFormGroupClass")}
|
className={kcClsx("kcFormGroupClass")}
|
||||||
{...Object.fromEntries(Object.entries(attribute.group.html5DataAnnotations).map(([key, value]) => [`data-${key}`, value]))}
|
{...Object.fromEntries(Object.entries(attribute.group.html5DataAnnotations).map(([key, value]) => [`data-${key}`, value]))}
|
||||||
>
|
>
|
||||||
{(() => {
|
{(() => {
|
||||||
@ -158,8 +157,8 @@ function GroupLabel(props: {
|
|||||||
const groupHeaderText = groupDisplayHeader !== "" ? advancedMsg(groupDisplayHeader) : attribute.group.name;
|
const groupHeaderText = groupDisplayHeader !== "" ? advancedMsg(groupDisplayHeader) : attribute.group.name;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={getClassName("kcContentWrapperClass")}>
|
<div className={kcClsx("kcContentWrapperClass")}>
|
||||||
<label id={`header-${attribute.group.name}`} className={getClassName("kcFormGroupHeader")}>
|
<label id={`header-${attribute.group.name}`} className={kcClsx("kcFormGroupHeader")}>
|
||||||
{groupHeaderText}
|
{groupHeaderText}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@ -172,8 +171,8 @@ function GroupLabel(props: {
|
|||||||
const groupDescriptionText = advancedMsg(groupDisplayDescription);
|
const groupDescriptionText = advancedMsg(groupDisplayDescription);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label id={`description-${attribute.group.name}`} className={getClassName("kcLabelClass")}>
|
<label id={`description-${attribute.group.name}`} className={kcClsx("kcLabelClass")}>
|
||||||
{groupDescriptionText}
|
{groupDescriptionText}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@ -190,13 +189,8 @@ function GroupLabel(props: {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function FieldErrors(props: {
|
function FieldErrors(props: { attribute: Attribute; displayableErrors: FormFieldError[]; fieldIndex: number | undefined; kcClsx: KcClsx }) {
|
||||||
attribute: Attribute;
|
const { attribute, fieldIndex, kcClsx } = props;
|
||||||
getClassName: UserProfileFormFieldsProps["getClassName"];
|
|
||||||
displayableErrors: FormFieldError[];
|
|
||||||
fieldIndex: number | undefined;
|
|
||||||
}) {
|
|
||||||
const { attribute, getClassName, fieldIndex } = props;
|
|
||||||
|
|
||||||
const displayableErrors = props.displayableErrors.filter(error => error.fieldIndex === fieldIndex);
|
const displayableErrors = props.displayableErrors.filter(error => error.fieldIndex === fieldIndex);
|
||||||
|
|
||||||
@ -207,7 +201,7 @@ function FieldErrors(props: {
|
|||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
id={`input-error-${attribute.name}${fieldIndex === undefined ? "" : `-${fieldIndex}`}`}
|
id={`input-error-${attribute.name}${fieldIndex === undefined ? "" : `-${fieldIndex}`}`}
|
||||||
className={getClassName("kcInputErrorMessageClass")}
|
className={kcClsx("kcInputErrorMessageClass")}
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
>
|
>
|
||||||
{displayableErrors
|
{displayableErrors
|
||||||
@ -226,9 +220,9 @@ type InputFiledByTypeProps = {
|
|||||||
attribute: Attribute;
|
attribute: Attribute;
|
||||||
valueOrValues: string | string[];
|
valueOrValues: string | string[];
|
||||||
displayableErrors: FormFieldError[];
|
displayableErrors: FormFieldError[];
|
||||||
formValidationDispatch: React.Dispatch<FormAction>;
|
dispatchFormAction: React.Dispatch<FormAction>;
|
||||||
getClassName: UserProfileFormFieldsProps["getClassName"];
|
|
||||||
i18n: I18n;
|
i18n: I18n;
|
||||||
|
kcClsx: KcClsx;
|
||||||
};
|
};
|
||||||
|
|
||||||
function InputFiledByType(props: InputFiledByTypeProps) {
|
function InputFiledByType(props: InputFiledByTypeProps) {
|
||||||
@ -258,7 +252,7 @@ function InputFiledByType(props: InputFiledByTypeProps) {
|
|||||||
|
|
||||||
if (attribute.name === "password" || attribute.name === "password-confirm") {
|
if (attribute.name === "password" || attribute.name === "password-confirm") {
|
||||||
return (
|
return (
|
||||||
<PasswordWrapper getClassName={props.getClassName} i18n={props.i18n} passwordInputId={attribute.name}>
|
<PasswordWrapper kcClsx={props.kcClsx} i18n={props.i18n} passwordInputId={attribute.name}>
|
||||||
{inputNode}
|
{inputNode}
|
||||||
</PasswordWrapper>
|
</PasswordWrapper>
|
||||||
);
|
);
|
||||||
@ -269,8 +263,8 @@ function InputFiledByType(props: InputFiledByTypeProps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function PasswordWrapper(props: { getClassName: (classKey: ClassKey) => string; i18n: I18n; passwordInputId: string; children: JSX.Element }) {
|
function PasswordWrapper(props: { kcClsx: KcClsx; i18n: I18n; passwordInputId: string; children: JSX.Element }) {
|
||||||
const { getClassName, i18n, passwordInputId, children } = props;
|
const { kcClsx, i18n, passwordInputId, children } = props;
|
||||||
|
|
||||||
const { msgStr } = i18n;
|
const { msgStr } = i18n;
|
||||||
|
|
||||||
@ -285,26 +279,23 @@ function PasswordWrapper(props: { getClassName: (classKey: ClassKey) => string;
|
|||||||
}, [isPasswordRevealed]);
|
}, [isPasswordRevealed]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={getClassName("kcInputGroup")}>
|
<div className={kcClsx("kcInputGroup")}>
|
||||||
{children}
|
{children}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={getClassName("kcFormPasswordVisibilityButtonClass")}
|
className={kcClsx("kcFormPasswordVisibilityButtonClass")}
|
||||||
aria-label={msgStr(isPasswordRevealed ? "hidePassword" : "showPassword")}
|
aria-label={msgStr(isPasswordRevealed ? "hidePassword" : "showPassword")}
|
||||||
aria-controls={passwordInputId}
|
aria-controls={passwordInputId}
|
||||||
onClick={toggleIsPasswordRevealed}
|
onClick={toggleIsPasswordRevealed}
|
||||||
>
|
>
|
||||||
<i
|
<i className={kcClsx(isPasswordRevealed ? "kcFormPasswordVisibilityIconHide" : "kcFormPasswordVisibilityIconShow")} aria-hidden />
|
||||||
className={getClassName(isPasswordRevealed ? "kcFormPasswordVisibilityIconHide" : "kcFormPasswordVisibilityIconShow")}
|
|
||||||
aria-hidden
|
|
||||||
/>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function InputTag(props: InputFiledByTypeProps & { fieldIndex: number | undefined }) {
|
function InputTag(props: InputFiledByTypeProps & { fieldIndex: number | undefined }) {
|
||||||
const { attribute, fieldIndex, getClassName, formValidationDispatch, valueOrValues, i18n, displayableErrors } = props;
|
const { attribute, fieldIndex, kcClsx, dispatchFormAction, valueOrValues, i18n, displayableErrors } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -330,7 +321,7 @@ function InputTag(props: InputFiledByTypeProps & { fieldIndex: number | undefine
|
|||||||
|
|
||||||
return valueOrValues;
|
return valueOrValues;
|
||||||
})()}
|
})()}
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
aria-invalid={displayableErrors.find(error => error.fieldIndex === fieldIndex) !== undefined}
|
aria-invalid={displayableErrors.find(error => error.fieldIndex === fieldIndex) !== undefined}
|
||||||
disabled={attribute.readOnly}
|
disabled={attribute.readOnly}
|
||||||
autoComplete={attribute.autocomplete}
|
autoComplete={attribute.autocomplete}
|
||||||
@ -348,7 +339,7 @@ function InputTag(props: InputFiledByTypeProps & { fieldIndex: number | undefine
|
|||||||
step={attribute.annotations.inputTypeStep}
|
step={attribute.annotations.inputTypeStep}
|
||||||
{...Object.fromEntries(Object.entries(attribute.html5DataAnnotations ?? {}).map(([key, value]) => [`data-${key}`, value]))}
|
{...Object.fromEntries(Object.entries(attribute.html5DataAnnotations ?? {}).map(([key, value]) => [`data-${key}`, value]))}
|
||||||
onChange={event =>
|
onChange={event =>
|
||||||
formValidationDispatch({
|
dispatchFormAction({
|
||||||
action: "update",
|
action: "update",
|
||||||
name: attribute.name,
|
name: attribute.name,
|
||||||
valueOrValues: (() => {
|
valueOrValues: (() => {
|
||||||
@ -369,7 +360,7 @@ function InputTag(props: InputFiledByTypeProps & { fieldIndex: number | undefine
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
onBlur={() =>
|
onBlur={() =>
|
||||||
formValidationDispatch({
|
dispatchFormAction({
|
||||||
action: "focus lost",
|
action: "focus lost",
|
||||||
name: attribute.name,
|
name: attribute.name,
|
||||||
fieldIndex: fieldIndex
|
fieldIndex: fieldIndex
|
||||||
@ -387,17 +378,12 @@ function InputTag(props: InputFiledByTypeProps & { fieldIndex: number | undefine
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FieldErrors
|
<FieldErrors attribute={attribute} kcClsx={kcClsx} displayableErrors={displayableErrors} fieldIndex={fieldIndex} />
|
||||||
attribute={attribute}
|
|
||||||
getClassName={getClassName}
|
|
||||||
displayableErrors={displayableErrors}
|
|
||||||
fieldIndex={fieldIndex}
|
|
||||||
/>
|
|
||||||
<AddRemoveButtonsMultiValuedAttribute
|
<AddRemoveButtonsMultiValuedAttribute
|
||||||
attribute={attribute}
|
attribute={attribute}
|
||||||
values={values}
|
values={values}
|
||||||
fieldIndex={fieldIndex}
|
fieldIndex={fieldIndex}
|
||||||
dispatchFormAction={formValidationDispatch}
|
dispatchFormAction={dispatchFormAction}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
@ -464,7 +450,7 @@ function AddRemoveButtonsMultiValuedAttribute(props: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function InputTagSelects(props: InputFiledByTypeProps) {
|
function InputTagSelects(props: InputFiledByTypeProps) {
|
||||||
const { attribute, formValidationDispatch, getClassName, valueOrValues } = props;
|
const { attribute, dispatchFormAction, kcClsx, valueOrValues } = props;
|
||||||
|
|
||||||
const { advancedMsg } = props.i18n;
|
const { advancedMsg } = props.i18n;
|
||||||
|
|
||||||
@ -477,16 +463,16 @@ function InputTagSelects(props: InputFiledByTypeProps) {
|
|||||||
case "select-radiobuttons":
|
case "select-radiobuttons":
|
||||||
return {
|
return {
|
||||||
inputType: "radio",
|
inputType: "radio",
|
||||||
classDiv: getClassName("kcInputClassRadio"),
|
classDiv: kcClsx("kcInputClassRadio"),
|
||||||
classInput: getClassName("kcInputClassRadioInput"),
|
classInput: kcClsx("kcInputClassRadioInput"),
|
||||||
classLabel: getClassName("kcInputClassRadioLabel")
|
classLabel: kcClsx("kcInputClassRadioLabel")
|
||||||
};
|
};
|
||||||
case "multiselect-checkboxes":
|
case "multiselect-checkboxes":
|
||||||
return {
|
return {
|
||||||
inputType: "checkbox",
|
inputType: "checkbox",
|
||||||
classDiv: getClassName("kcInputClassCheckbox"),
|
classDiv: kcClsx("kcInputClassCheckbox"),
|
||||||
classInput: getClassName("kcInputClassCheckboxInput"),
|
classInput: kcClsx("kcInputClassCheckboxInput"),
|
||||||
classLabel: getClassName("kcInputClassCheckboxLabel")
|
classLabel: kcClsx("kcInputClassCheckboxLabel")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
@ -529,7 +515,7 @@ function InputTagSelects(props: InputFiledByTypeProps) {
|
|||||||
disabled={attribute.readOnly}
|
disabled={attribute.readOnly}
|
||||||
checked={valueOrValues instanceof Array ? valueOrValues.includes(option) : valueOrValues === option}
|
checked={valueOrValues instanceof Array ? valueOrValues.includes(option) : valueOrValues === option}
|
||||||
onChange={event =>
|
onChange={event =>
|
||||||
formValidationDispatch({
|
dispatchFormAction({
|
||||||
action: "update",
|
action: "update",
|
||||||
name: attribute.name,
|
name: attribute.name,
|
||||||
valueOrValues: (() => {
|
valueOrValues: (() => {
|
||||||
@ -552,7 +538,7 @@ function InputTagSelects(props: InputFiledByTypeProps) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
onBlur={() =>
|
onBlur={() =>
|
||||||
formValidationDispatch({
|
dispatchFormAction({
|
||||||
action: "focus lost",
|
action: "focus lost",
|
||||||
name: attribute.name,
|
name: attribute.name,
|
||||||
fieldIndex: undefined
|
fieldIndex: undefined
|
||||||
@ -561,7 +547,7 @@ function InputTagSelects(props: InputFiledByTypeProps) {
|
|||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
htmlFor={`${attribute.name}-${option}`}
|
htmlFor={`${attribute.name}-${option}`}
|
||||||
className={`${classLabel}${attribute.readOnly ? ` ${getClassName("kcInputClassRadioCheckboxLabelDisabled")}` : ""}`}
|
className={`${classLabel}${attribute.readOnly ? ` ${kcClsx("kcInputClassRadioCheckboxLabelDisabled")}` : ""}`}
|
||||||
>
|
>
|
||||||
{advancedMsg(option)}
|
{advancedMsg(option)}
|
||||||
</label>
|
</label>
|
||||||
@ -572,7 +558,7 @@ function InputTagSelects(props: InputFiledByTypeProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function TextareaTag(props: InputFiledByTypeProps) {
|
function TextareaTag(props: InputFiledByTypeProps) {
|
||||||
const { attribute, formValidationDispatch, getClassName, displayableErrors, valueOrValues } = props;
|
const { attribute, dispatchFormAction, kcClsx, displayableErrors, valueOrValues } = props;
|
||||||
|
|
||||||
assert(typeof valueOrValues === "string");
|
assert(typeof valueOrValues === "string");
|
||||||
|
|
||||||
@ -582,7 +568,7 @@ function TextareaTag(props: InputFiledByTypeProps) {
|
|||||||
<textarea
|
<textarea
|
||||||
id={attribute.name}
|
id={attribute.name}
|
||||||
name={attribute.name}
|
name={attribute.name}
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
aria-invalid={displayableErrors.length !== 0}
|
aria-invalid={displayableErrors.length !== 0}
|
||||||
disabled={attribute.readOnly}
|
disabled={attribute.readOnly}
|
||||||
cols={attribute.annotations.inputTypeCols === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeCols}`)}
|
cols={attribute.annotations.inputTypeCols === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeCols}`)}
|
||||||
@ -590,14 +576,14 @@ function TextareaTag(props: InputFiledByTypeProps) {
|
|||||||
maxLength={attribute.annotations.inputTypeMaxlength === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeMaxlength}`)}
|
maxLength={attribute.annotations.inputTypeMaxlength === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeMaxlength}`)}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={event =>
|
onChange={event =>
|
||||||
formValidationDispatch({
|
dispatchFormAction({
|
||||||
action: "update",
|
action: "update",
|
||||||
name: attribute.name,
|
name: attribute.name,
|
||||||
valueOrValues: event.target.value
|
valueOrValues: event.target.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
onBlur={() =>
|
onBlur={() =>
|
||||||
formValidationDispatch({
|
dispatchFormAction({
|
||||||
action: "focus lost",
|
action: "focus lost",
|
||||||
name: attribute.name,
|
name: attribute.name,
|
||||||
fieldIndex: undefined
|
fieldIndex: undefined
|
||||||
@ -608,7 +594,7 @@ function TextareaTag(props: InputFiledByTypeProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function SelectTag(props: InputFiledByTypeProps) {
|
function SelectTag(props: InputFiledByTypeProps) {
|
||||||
const { attribute, formValidationDispatch, getClassName, displayableErrors, i18n, valueOrValues } = props;
|
const { attribute, dispatchFormAction, kcClsx, displayableErrors, i18n, valueOrValues } = props;
|
||||||
|
|
||||||
const { advancedMsg } = i18n;
|
const { advancedMsg } = i18n;
|
||||||
|
|
||||||
@ -618,14 +604,14 @@ function SelectTag(props: InputFiledByTypeProps) {
|
|||||||
<select
|
<select
|
||||||
id={attribute.name}
|
id={attribute.name}
|
||||||
name={attribute.name}
|
name={attribute.name}
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
aria-invalid={displayableErrors.length !== 0}
|
aria-invalid={displayableErrors.length !== 0}
|
||||||
disabled={attribute.readOnly}
|
disabled={attribute.readOnly}
|
||||||
multiple={isMultiple}
|
multiple={isMultiple}
|
||||||
size={attribute.annotations.inputTypeSize === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeSize}`)}
|
size={attribute.annotations.inputTypeSize === undefined ? undefined : parseInt(`${attribute.annotations.inputTypeSize}`)}
|
||||||
value={valueOrValues}
|
value={valueOrValues}
|
||||||
onChange={event =>
|
onChange={event =>
|
||||||
formValidationDispatch({
|
dispatchFormAction({
|
||||||
action: "update",
|
action: "update",
|
||||||
name: attribute.name,
|
name: attribute.name,
|
||||||
valueOrValues: (() => {
|
valueOrValues: (() => {
|
||||||
@ -638,7 +624,7 @@ function SelectTag(props: InputFiledByTypeProps) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
onBlur={() =>
|
onBlur={() =>
|
||||||
formValidationDispatch({
|
dispatchFormAction({
|
||||||
action: "focus lost",
|
action: "focus lost",
|
||||||
name: attribute.name,
|
name: attribute.name,
|
||||||
fieldIndex: undefined
|
fieldIndex: undefined
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export type { MessageKey } from "./i18n";
|
export type { MessageKey, KcContextLike } from "./i18n";
|
||||||
import { createUseI18n } from "./i18n";
|
import { createUseI18n } from "./i18n";
|
||||||
export { createUseI18n };
|
export { createUseI18n };
|
||||||
export { fallbackLanguageTag } from "./i18n";
|
export { fallbackLanguageTag } from "./i18n";
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createUseClassName } from "keycloakify/lib/useGetClassName";
|
import { createGetKcClsx } from "keycloakify/lib/getKcClsx";
|
||||||
import type { ClassKey } from "keycloakify/login/TemplateProps";
|
import type { ClassKey } from "keycloakify/login/TemplateProps";
|
||||||
|
|
||||||
export const { useGetClassName } = createUseClassName<ClassKey>({
|
export const { getKcClsx } = createGetKcClsx<ClassKey>({
|
||||||
defaultClasses: {
|
defaultClasses: {
|
||||||
kcHtmlClass: "login-pf",
|
kcHtmlClass: "login-pf",
|
||||||
kcBodyClass: undefined,
|
kcBodyClass: undefined,
|
||||||
@ -137,3 +137,7 @@ export const { useGetClassName } = createUseClassName<ClassKey>({
|
|||||||
kcLabelClass: "pf-c-form__label pf-c-form__label-text"
|
kcLabelClass: "pf-c-form__label pf-c-form__label-text"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export type { ClassKey };
|
||||||
|
|
||||||
|
export type KcClsx = ReturnType<typeof getKcClsx>["kcClsx"];
|
@ -7,9 +7,11 @@ import { useConstCallback } from "keycloakify/tools/useConstCallback";
|
|||||||
import { emailRegexp } from "keycloakify/tools/emailRegExp";
|
import { emailRegexp } from "keycloakify/tools/emailRegExp";
|
||||||
import { formatNumber } from "keycloakify/tools/formatNumber";
|
import { formatNumber } from "keycloakify/tools/formatNumber";
|
||||||
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
||||||
import type { KcContext, PasswordPolicies, Attribute, Validators } from "keycloakify/login/KcContext";
|
import type { PasswordPolicies, Attribute, Validators } from "keycloakify/login/KcContext";
|
||||||
|
import type { KcContext } from "../KcContext";
|
||||||
import type { MessageKey } from "keycloakify/login/i18n";
|
import type { MessageKey } from "keycloakify/login/i18n";
|
||||||
import type { I18n } from "../i18n";
|
import { KcContextLike as KcContextLike_i18n } from "keycloakify/login/i18n";
|
||||||
|
import { useI18n } from "../i18n";
|
||||||
|
|
||||||
export type FormFieldError = {
|
export type FormFieldError = {
|
||||||
errorMessage: JSX.Element;
|
errorMessage: JSX.Element;
|
||||||
@ -64,23 +66,23 @@ export type FormAction =
|
|||||||
fieldIndex: number | undefined;
|
fieldIndex: number | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type KcContextLike = {
|
export type KcContextLike = KcContextLike_i18n &
|
||||||
messagesPerField: Pick<KcContext.Common["messagesPerField"], "existsError" | "get">;
|
KcContextLike_useGetErrors & {
|
||||||
profile: {
|
profile: {
|
||||||
attributesByName: Record<string, Attribute>;
|
attributesByName: Record<string, Attribute>;
|
||||||
html5DataAnnotations?: Record<string, string>;
|
html5DataAnnotations?: Record<string, string>;
|
||||||
};
|
};
|
||||||
passwordRequired?: boolean;
|
passwordRequired?: boolean;
|
||||||
realm: { registrationEmailAsUsername: boolean };
|
realm: { registrationEmailAsUsername: boolean };
|
||||||
passwordPolicies?: PasswordPolicies;
|
|
||||||
url: {
|
url: {
|
||||||
resourcesPath: string;
|
resourcesPath: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
assert<Extract<KcContext.Register, { pageId: "register.ftl" }> extends KcContextLike ? true : false>();
|
||||||
|
|
||||||
export type ParamsOfUseUserProfileForm = {
|
export type ParamsOfUseUserProfileForm = {
|
||||||
kcContext: KcContextLike;
|
kcContext: KcContextLike;
|
||||||
i18n: I18n;
|
|
||||||
doMakeUserConfirmPassword: boolean;
|
doMakeUserConfirmPassword: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -103,7 +105,7 @@ namespace internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTypeOfUseUserProfileForm {
|
export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTypeOfUseUserProfileForm {
|
||||||
const { kcContext, i18n, doMakeUserConfirmPassword } = params;
|
const { kcContext, doMakeUserConfirmPassword } = params;
|
||||||
|
|
||||||
const { insertScriptTags } = useInsertScriptTags({
|
const { insertScriptTags } = useInsertScriptTags({
|
||||||
componentOrHookName: "useUserProfileForm",
|
componentOrHookName: "useUserProfileForm",
|
||||||
@ -120,8 +122,7 @@ export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTy
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const { getErrors } = useGetErrors({
|
const { getErrors } = useGetErrors({
|
||||||
kcContext,
|
kcContext
|
||||||
i18n
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialState = useMemo((): internal.State => {
|
const initialState = useMemo((): internal.State => {
|
||||||
@ -515,12 +516,19 @@ export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTy
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField" | "passwordPolicies">; i18n: I18n }) {
|
type KcContextLike_useGetErrors = KcContextLike_i18n & {
|
||||||
const { kcContext, i18n } = params;
|
messagesPerField: Pick<KcContext["messagesPerField"], "existsError" | "get">;
|
||||||
|
passwordPolicies?: PasswordPolicies;
|
||||||
|
};
|
||||||
|
|
||||||
|
assert<KcContextLike extends KcContextLike_useGetErrors ? true : false>();
|
||||||
|
|
||||||
|
function useGetErrors(params: { kcContext: KcContextLike_useGetErrors }) {
|
||||||
|
const { kcContext } = params;
|
||||||
|
|
||||||
const { messagesPerField, passwordPolicies } = kcContext;
|
const { messagesPerField, passwordPolicies } = kcContext;
|
||||||
|
|
||||||
const { msg, msgStr, advancedMsg, advancedMsgStr } = i18n;
|
const { msg, msgStr, advancedMsg, advancedMsgStr } = useI18n({ kcContext });
|
||||||
|
|
||||||
const getErrors = useConstCallback(
|
const getErrors = useConstCallback(
|
||||||
(params: {
|
(params: {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
import { getKcClsx } 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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -6,7 +6,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function Code(props: PageProps<Extract<KcContext, { pageId: "code.ftl" }>>) {
|
export default function Code(props: PageProps<Extract<KcContext, { pageId: "code.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -17,14 +17,16 @@ export default function Code(props: PageProps<Extract<KcContext, { pageId: "code
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
headerNode={code.success ? msg("codeSuccessTitle") : msg("codeErrorTitle", code.error)}
|
headerNode={code.success ? msg("codeSuccessTitle") : msg("codeErrorTitle", code.error)}
|
||||||
>
|
>
|
||||||
<div id="kc-code">
|
<div id="kc-code">
|
||||||
{code.success ? (
|
{code.success ? (
|
||||||
<>
|
<>
|
||||||
<p>{msg("copyCodeInstruction")}</p>
|
<p>{msg("copyCodeInstruction")}</p>
|
||||||
<input id="code" className={getClassName("kcTextareaClass")} defaultValue={code.code} />
|
<input id="code" className={kcClsx("kcTextareaClass")} defaultValue={code.code} />
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<p id="error">{code.error}</p>
|
<p id="error">{code.error}</p>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -7,7 +6,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function DeleteAccountConfirm(props: PageProps<Extract<KcContext, { pageId: "delete-account-confirm.ftl" }>>) {
|
export default function DeleteAccountConfirm(props: PageProps<Extract<KcContext, { pageId: "delete-account-confirm.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -17,7 +16,7 @@ export default function DeleteAccountConfirm(props: PageProps<Extract<KcContext,
|
|||||||
const { msg, msgStr } = useI18n({ kcContext });
|
const { msg, msgStr } = useI18n({ kcContext });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("deleteAccountConfirm")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("deleteAccountConfirm")}>
|
||||||
<form action={url.loginAction} className="form-vertical" method="post">
|
<form action={url.loginAction} className="form-vertical" method="post">
|
||||||
<div className="alert alert-warning" style={{ marginTop: "0", marginBottom: "30px" }}>
|
<div className="alert alert-warning" style={{ marginTop: "0", marginBottom: "30px" }}>
|
||||||
<span className="pficon pficon-warning-triangle-o"></span>
|
<span className="pficon pficon-warning-triangle-o"></span>
|
||||||
@ -37,13 +36,13 @@ export default function DeleteAccountConfirm(props: PageProps<Extract<KcContext,
|
|||||||
<p className="delete-account-text">{msg("finalDeletionConfirmation")}</p>
|
<p className="delete-account-text">{msg("finalDeletionConfirmation")}</p>
|
||||||
<div id="kc-form-buttons">
|
<div id="kc-form-buttons">
|
||||||
<input
|
<input
|
||||||
className={clsx(getClassName("kcButtonClass"), getClassName("kcButtonPrimaryClass"), getClassName("kcButtonLargeClass"))}
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doConfirmDelete")}
|
value={msgStr("doConfirmDelete")}
|
||||||
/>
|
/>
|
||||||
{triggered_from_aia && (
|
{triggered_from_aia && (
|
||||||
<button
|
<button
|
||||||
className={clsx(getClassName("kcButtonClass"), getClassName("kcButtonDefaultClass"), getClassName("kcButtonLargeClass"))}
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
|
||||||
style={{ marginLeft: "calc(100% - 220px)" }}
|
style={{ marginLeft: "calc(100% - 220px)" }}
|
||||||
type="submit"
|
type="submit"
|
||||||
name="cancel-aia"
|
name="cancel-aia"
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -9,7 +8,7 @@ export default function DeleteCredential(props: PageProps<Extract<KcContext, { p
|
|||||||
|
|
||||||
const { msgStr, msg } = useI18n({ kcContext });
|
const { msgStr, msg } = useI18n({ kcContext });
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -17,18 +16,24 @@ export default function DeleteCredential(props: PageProps<Extract<KcContext, { p
|
|||||||
const { url, credentialLabel } = kcContext;
|
const { url, credentialLabel } = kcContext;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} displayMessage={false} headerNode={msg("deleteCredentialTitle", credentialLabel)}>
|
<Template
|
||||||
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
|
displayMessage={false}
|
||||||
|
headerNode={msg("deleteCredentialTitle", credentialLabel)}
|
||||||
|
>
|
||||||
<div id="kc-delete-text">{msg("deleteCredentialMessage", credentialLabel)}</div>
|
<div id="kc-delete-text">{msg("deleteCredentialMessage", credentialLabel)}</div>
|
||||||
<form className="form-actions" action={url.loginAction} method="POST">
|
<form className="form-actions" action={url.loginAction} method="POST">
|
||||||
<input
|
<input
|
||||||
className={clsx(getClassName("kcButtonClass"), getClassName("kcButtonPrimaryClass"), getClassName("kcButtonLargeClass"))}
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
name="accept"
|
name="accept"
|
||||||
id="kc-accept"
|
id="kc-accept"
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doConfirmDelete")}
|
value={msgStr("doConfirmDelete")}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
className={clsx(getClassName("kcButtonClass"), getClassName("kcButtonDefaultClass"), getClassName("kcButtonLargeClass"))}
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
|
||||||
name="cancel-aia"
|
name="cancel-aia"
|
||||||
value={msgStr("doCancel")}
|
value={msgStr("doCancel")}
|
||||||
id="kc-decline"
|
id="kc-decline"
|
||||||
|
@ -10,7 +10,7 @@ export default function Error(props: PageProps<Extract<KcContext, { pageId: "err
|
|||||||
const { msg } = useI18n({ kcContext });
|
const { msg } = useI18n({ kcContext });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} displayMessage={false} headerNode={msg("errorTitle")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} displayMessage={false} headerNode={msg("errorTitle")}>
|
||||||
<div id="kc-error-message">
|
<div id="kc-error-message">
|
||||||
<p className="instruction">{message.summary}</p>
|
<p className="instruction">{message.summary}</p>
|
||||||
{!skipLink && client !== undefined && client.baseUrl !== undefined && (
|
{!skipLink && client !== undefined && client.baseUrl !== undefined && (
|
||||||
|
@ -18,7 +18,9 @@ export default function FrontchannelLogout(props: PageProps<Extract<KcContext, {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
documentTitle={msgStr("frontchannel-logout.title")}
|
documentTitle={msgStr("frontchannel-logout.title")}
|
||||||
headerNode={msg("frontchannel-logout.title")}
|
headerNode={msg("frontchannel-logout.title")}
|
||||||
>
|
>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import type { PageProps } from "keycloakify/login/pages/PageProps";
|
import type { PageProps } from "keycloakify/login/pages/PageProps";
|
||||||
import type { UserProfileFormFieldsProps } from "keycloakify/login/UserProfileFormFields";
|
import type { UserProfileFormFieldsProps } from "keycloakify/login/UserProfileFormFields";
|
||||||
import type { KcContext } from "../KcContext";
|
import type { KcContext } from "../KcContext";
|
||||||
@ -14,7 +13,7 @@ type IdpReviewUserProfileProps = PageProps<Extract<KcContext, { pageId: "idp-rev
|
|||||||
export default function IdpReviewUserProfile(props: IdpReviewUserProfileProps) {
|
export default function IdpReviewUserProfile(props: IdpReviewUserProfileProps) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
|
const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -27,25 +26,22 @@ export default function IdpReviewUserProfile(props: IdpReviewUserProfileProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
displayMessage={messagesPerField.exists("global")}
|
displayMessage={messagesPerField.exists("global")}
|
||||||
displayRequiredFields
|
displayRequiredFields
|
||||||
headerNode={msg("loginIdpReviewProfileTitle")}
|
headerNode={msg("loginIdpReviewProfileTitle")}
|
||||||
>
|
>
|
||||||
<form id="kc-idp-review-profile-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
|
<form id="kc-idp-review-profile-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
<UserProfileFormFields kcContext={kcContext} onIsFormSubmittableValueChange={setIsFomSubmittable} getClassName={getClassName} />
|
<UserProfileFormFields kcContext={kcContext} onIsFormSubmittableValueChange={setIsFomSubmittable} kcClsx={kcClsx} />
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")} />
|
<div className={kcClsx("kcFormOptionsWrapperClass")} />
|
||||||
</div>
|
</div>
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<input
|
<input
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doSubmit")}
|
value={msgStr("doSubmit")}
|
||||||
disabled={!isFomSubmittable}
|
disabled={!isFomSubmittable}
|
||||||
|
@ -17,7 +17,9 @@ export default function Info(props: PageProps<Extract<KcContext, { pageId: "info
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
displayMessage={false}
|
displayMessage={false}
|
||||||
headerNode={messageHeader !== undefined ? <>{messageHeader}</> : <>{message.summary}</>}
|
headerNode={messageHeader !== undefined ? <>{messageHeader}</> : <>{message.summary}</>}
|
||||||
>
|
>
|
||||||
|
@ -2,14 +2,14 @@ import { useState, useEffect, useReducer } from "react";
|
|||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
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 { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import type { KcContext } from "../KcContext";
|
import type { KcContext } from "../KcContext";
|
||||||
import { useI18n, type I18n } from "../i18n";
|
import { useI18n, type I18n } from "../i18n";
|
||||||
|
|
||||||
export default function Login(props: PageProps<Extract<KcContext, { pageId: "login.ftl" }>>) {
|
export default function Login(props: PageProps<Extract<KcContext, { pageId: "login.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -23,7 +23,9 @@ export default function Login(props: PageProps<Extract<KcContext, { pageId: "log
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
displayMessage={!messagesPerField.existsError("username", "password")}
|
displayMessage={!messagesPerField.existsError("username", "password")}
|
||||||
headerNode={msg("loginAccountTitle")}
|
headerNode={msg("loginAccountTitle")}
|
||||||
displayInfo={realm.password && realm.registrationAllowed && !registrationDisabled}
|
displayInfo={realm.password && realm.registrationAllowed && !registrationDisabled}
|
||||||
@ -42,32 +44,23 @@ export default function Login(props: PageProps<Extract<KcContext, { pageId: "log
|
|||||||
socialProvidersNode={
|
socialProvidersNode={
|
||||||
<>
|
<>
|
||||||
{realm.password && social.providers?.length && (
|
{realm.password && social.providers?.length && (
|
||||||
<div id="kc-social-providers" className={getClassName("kcFormSocialAccountSectionClass")}>
|
<div id="kc-social-providers" className={kcClsx("kcFormSocialAccountSectionClass")}>
|
||||||
<hr />
|
<hr />
|
||||||
<h2>{msg("identity-provider-login-label")}</h2>
|
<h2>{msg("identity-provider-login-label")}</h2>
|
||||||
<ul
|
<ul className={kcClsx("kcFormSocialAccountListClass", social.providers.length > 3 && "kcFormSocialAccountListGridClass")}>
|
||||||
className={clsx(
|
|
||||||
getClassName("kcFormSocialAccountListClass"),
|
|
||||||
social.providers.length > 3 && getClassName("kcFormSocialAccountListGridClass")
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{social.providers.map((...[p, , providers]) => (
|
{social.providers.map((...[p, , providers]) => (
|
||||||
<li key={p.alias}>
|
<li key={p.alias}>
|
||||||
<a
|
<a
|
||||||
id={`social-${p.alias}`}
|
id={`social-${p.alias}`}
|
||||||
className={clsx(
|
className={kcClsx(
|
||||||
getClassName("kcFormSocialAccountListButtonClass"),
|
"kcFormSocialAccountListButtonClass",
|
||||||
providers.length > 3 && getClassName("kcFormSocialAccountGridItem")
|
providers.length > 3 && "kcFormSocialAccountGridItem"
|
||||||
)}
|
)}
|
||||||
type="button"
|
type="button"
|
||||||
href={p.loginUrl}
|
href={p.loginUrl}
|
||||||
>
|
>
|
||||||
{p.iconClasses && (
|
{p.iconClasses && <i className={clsx(kcClsx("kcCommonLogoIdP"), p.iconClasses)} aria-hidden="true"></i>}
|
||||||
<i className={clsx(getClassName("kcCommonLogoIdP"), p.iconClasses)} aria-hidden="true"></i>
|
<span className={clsx(kcClsx("kcFormSocialAccountNameClass"), p.iconClasses && "kc-social-icon-text")}>
|
||||||
)}
|
|
||||||
<span
|
|
||||||
className={clsx(getClassName("kcFormSocialAccountNameClass"), p.iconClasses && "kc-social-icon-text")}
|
|
||||||
>
|
|
||||||
{p.displayName}
|
{p.displayName}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
@ -92,8 +85,8 @@ export default function Login(props: PageProps<Extract<KcContext, { pageId: "log
|
|||||||
method="post"
|
method="post"
|
||||||
>
|
>
|
||||||
{!usernameHidden && (
|
{!usernameHidden && (
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<label htmlFor="username" className={getClassName("kcLabelClass")}>
|
<label htmlFor="username" className={kcClsx("kcLabelClass")}>
|
||||||
{!realm.loginWithEmailAllowed
|
{!realm.loginWithEmailAllowed
|
||||||
? msg("username")
|
? msg("username")
|
||||||
: !realm.registrationEmailAsUsername
|
: !realm.registrationEmailAsUsername
|
||||||
@ -103,7 +96,7 @@ export default function Login(props: PageProps<Extract<KcContext, { pageId: "log
|
|||||||
<input
|
<input
|
||||||
tabIndex={2}
|
tabIndex={2}
|
||||||
id="username"
|
id="username"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
name="username"
|
name="username"
|
||||||
defaultValue={login.username ?? ""}
|
defaultValue={login.username ?? ""}
|
||||||
type="text"
|
type="text"
|
||||||
@ -112,22 +105,22 @@ export default function Login(props: PageProps<Extract<KcContext, { pageId: "log
|
|||||||
aria-invalid={messagesPerField.existsError("username", "password")}
|
aria-invalid={messagesPerField.existsError("username", "password")}
|
||||||
/>
|
/>
|
||||||
{messagesPerField.existsError("username", "password") && (
|
{messagesPerField.existsError("username", "password") && (
|
||||||
<span id="input-error" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.getFirstError("username", "password")}
|
{messagesPerField.getFirstError("username", "password")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<label htmlFor="password" className={getClassName("kcLabelClass")}>
|
<label htmlFor="password" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("password")}
|
{msg("password")}
|
||||||
</label>
|
</label>
|
||||||
<PasswordWrapper getClassName={getClassName} i18n={i18n} passwordInputId="password">
|
<PasswordWrapper kcClsx={kcClsx} i18n={i18n} passwordInputId="password">
|
||||||
<input
|
<input
|
||||||
tabIndex={3}
|
tabIndex={3}
|
||||||
id="password"
|
id="password"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
name="password"
|
name="password"
|
||||||
type="password"
|
type="password"
|
||||||
autoComplete="current-password"
|
autoComplete="current-password"
|
||||||
@ -135,13 +128,13 @@ export default function Login(props: PageProps<Extract<KcContext, { pageId: "log
|
|||||||
/>
|
/>
|
||||||
</PasswordWrapper>
|
</PasswordWrapper>
|
||||||
{usernameHidden && messagesPerField.existsError("username", "password") && (
|
{usernameHidden && messagesPerField.existsError("username", "password") && (
|
||||||
<span id="input-error" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.getFirstError("username", "password")}
|
{messagesPerField.getFirstError("username", "password")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={clsx(getClassName("kcFormGroupClass"), getClassName("kcFormSettingClass"))}>
|
<div className={kcClsx("kcFormGroupClass", "kcFormSettingClass")}>
|
||||||
<div id="kc-form-options">
|
<div id="kc-form-options">
|
||||||
{realm.rememberMe && !usernameHidden && (
|
{realm.rememberMe && !usernameHidden && (
|
||||||
<div className="checkbox">
|
<div className="checkbox">
|
||||||
@ -158,7 +151,7 @@ export default function Login(props: PageProps<Extract<KcContext, { pageId: "log
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}>
|
||||||
{realm.resetPasswordAllowed && (
|
{realm.resetPasswordAllowed && (
|
||||||
<span>
|
<span>
|
||||||
<a tabIndex={6} href={url.loginResetCredentialsUrl}>
|
<a tabIndex={6} href={url.loginResetCredentialsUrl}>
|
||||||
@ -169,17 +162,12 @@ export default function Login(props: PageProps<Extract<KcContext, { pageId: "log
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormGroupClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormGroupClass")}>
|
||||||
<input type="hidden" id="id-hidden-input" name="credentialId" value={auth.selectedCredential} />
|
<input type="hidden" id="id-hidden-input" name="credentialId" value={auth.selectedCredential} />
|
||||||
<input
|
<input
|
||||||
tabIndex={7}
|
tabIndex={7}
|
||||||
disabled={isLoginButtonDisabled}
|
disabled={isLoginButtonDisabled}
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="login"
|
name="login"
|
||||||
id="kc-login"
|
id="kc-login"
|
||||||
type="submit"
|
type="submit"
|
||||||
@ -194,13 +182,8 @@ export default function Login(props: PageProps<Extract<KcContext, { pageId: "log
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PasswordWrapper(props: {
|
function PasswordWrapper(props: { kcClsx: KcClsx; i18n: I18n; passwordInputId: string; children: JSX.Element }) {
|
||||||
getClassName: ReturnType<typeof useGetClassName>["getClassName"];
|
const { kcClsx, i18n, passwordInputId, children } = props;
|
||||||
i18n: I18n;
|
|
||||||
passwordInputId: string;
|
|
||||||
children: JSX.Element;
|
|
||||||
}) {
|
|
||||||
const { getClassName, i18n, passwordInputId, children } = props;
|
|
||||||
|
|
||||||
const { msgStr } = i18n;
|
const { msgStr } = i18n;
|
||||||
|
|
||||||
@ -215,19 +198,16 @@ function PasswordWrapper(props: {
|
|||||||
}, [isPasswordRevealed]);
|
}, [isPasswordRevealed]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={getClassName("kcInputGroup")}>
|
<div className={kcClsx("kcInputGroup")}>
|
||||||
{children}
|
{children}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={getClassName("kcFormPasswordVisibilityButtonClass")}
|
className={kcClsx("kcFormPasswordVisibilityButtonClass")}
|
||||||
aria-label={msgStr(isPasswordRevealed ? "hidePassword" : "showPassword")}
|
aria-label={msgStr(isPasswordRevealed ? "hidePassword" : "showPassword")}
|
||||||
aria-controls={passwordInputId}
|
aria-controls={passwordInputId}
|
||||||
onClick={toggleIsPasswordRevealed}
|
onClick={toggleIsPasswordRevealed}
|
||||||
>
|
>
|
||||||
<i
|
<i className={kcClsx(isPasswordRevealed ? "kcFormPasswordVisibilityIconHide" : "kcFormPasswordVisibilityIconShow")} aria-hidden />
|
||||||
className={getClassName(isPasswordRevealed ? "kcFormPasswordVisibilityIconHide" : "kcFormPasswordVisibilityIconShow")}
|
|
||||||
aria-hidden
|
|
||||||
/>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx, KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName, type ClassKey } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n, type I18n } from "../i18n";
|
import { useI18n, type I18n } from "../i18n";
|
||||||
@ -7,7 +6,7 @@ import { useI18n, type I18n } from "../i18n";
|
|||||||
export default function LoginConfigTotp(props: PageProps<Extract<KcContext, { pageId: "login-config-totp.ftl" }>>) {
|
export default function LoginConfigTotp(props: PageProps<Extract<KcContext, { pageId: "login-config-totp.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -19,7 +18,7 @@ export default function LoginConfigTotp(props: PageProps<Extract<KcContext, { pa
|
|||||||
const { msg, msgStr, advancedMsg } = i18n;
|
const { msg, msgStr, advancedMsg } = i18n;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("loginTotpTitle")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("loginTotpTitle")}>
|
||||||
<>
|
<>
|
||||||
<ol id="kc-totp-settings">
|
<ol id="kc-totp-settings">
|
||||||
<li>
|
<li>
|
||||||
@ -89,26 +88,26 @@ export default function LoginConfigTotp(props: PageProps<Extract<KcContext, { pa
|
|||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<form action={url.loginAction} className={getClassName("kcFormClass")} id="kc-totp-settings-form" method="post">
|
<form action={url.loginAction} className={kcClsx("kcFormClass")} id="kc-totp-settings-form" method="post">
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<label htmlFor="totp" className={getClassName("kcLabelClass")}>
|
<label htmlFor="totp" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("authenticatorCode")}
|
{msg("authenticatorCode")}
|
||||||
</label>{" "}
|
</label>{" "}
|
||||||
<span className="required">*</span>
|
<span className="required">*</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="totp"
|
id="totp"
|
||||||
name="totp"
|
name="totp"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
aria-invalid={messagesPerField.existsError("totp")}
|
aria-invalid={messagesPerField.existsError("totp")}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{messagesPerField.existsError("totp") && (
|
{messagesPerField.existsError("totp") && (
|
||||||
<span id="input-error-otp-code" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error-otp-code" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.get("totp")}
|
{messagesPerField.get("totp")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@ -117,54 +116,45 @@ export default function LoginConfigTotp(props: PageProps<Extract<KcContext, { pa
|
|||||||
{mode && <input type="hidden" id="mode" value={mode} />}
|
{mode && <input type="hidden" id="mode" value={mode} />}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<label htmlFor="userLabel" className={getClassName("kcLabelClass")}>
|
<label htmlFor="userLabel" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("loginTotpDeviceName")}
|
{msg("loginTotpDeviceName")}
|
||||||
</label>{" "}
|
</label>{" "}
|
||||||
{totp.otpCredentials.length >= 1 && <span className="required">*</span>}
|
{totp.otpCredentials.length >= 1 && <span className="required">*</span>}
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="userLabel"
|
id="userLabel"
|
||||||
name="userLabel"
|
name="userLabel"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
aria-invalid={messagesPerField.existsError("userLabel")}
|
aria-invalid={messagesPerField.existsError("userLabel")}
|
||||||
/>
|
/>
|
||||||
{messagesPerField.existsError("userLabel") && (
|
{messagesPerField.existsError("userLabel") && (
|
||||||
<span id="input-error-otp-label" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error-otp-label" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.get("userLabel")}
|
{messagesPerField.get("userLabel")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<LogoutOtherSessions {...{ getClassName, i18n }} />
|
<LogoutOtherSessions kcClsx={kcClsx} i18n={i18n} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isAppInitiatedAction ? (
|
{isAppInitiatedAction ? (
|
||||||
<>
|
<>
|
||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
id="saveTOTPBtn"
|
id="saveTOTPBtn"
|
||||||
value={msgStr("doSubmit")}
|
value={msgStr("doSubmit")}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonLargeClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
id="cancelTOTPBtn"
|
id="cancelTOTPBtn"
|
||||||
name="cancel-aia"
|
name="cancel-aia"
|
||||||
value="true"
|
value="true"
|
||||||
@ -175,7 +165,7 @@ export default function LoginConfigTotp(props: PageProps<Extract<KcContext, { pa
|
|||||||
) : (
|
) : (
|
||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(getClassName("kcButtonClass"), getClassName("kcButtonPrimaryClass"), getClassName("kcButtonLargeClass"))}
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
id="saveTOTPBtn"
|
id="saveTOTPBtn"
|
||||||
value={msgStr("doSubmit")}
|
value={msgStr("doSubmit")}
|
||||||
/>
|
/>
|
||||||
@ -186,14 +176,14 @@ export default function LoginConfigTotp(props: PageProps<Extract<KcContext, { pa
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function LogoutOtherSessions(props: { getClassName: (key: ClassKey) => string; i18n: I18n }) {
|
function LogoutOtherSessions(props: { kcClsx: KcClsx; i18n: I18n }) {
|
||||||
const { getClassName, i18n } = props;
|
const { kcClsx, i18n } = props;
|
||||||
|
|
||||||
const { msg } = i18n;
|
const { msg } = i18n;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}>
|
||||||
<div className="checkbox">
|
<div className="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
|
<input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -7,7 +6,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function LoginIdpLinkConfirm(props: PageProps<Extract<KcContext, { pageId: "login-idp-link-confirm.ftl" }>>) {
|
export default function LoginIdpLinkConfirm(props: PageProps<Extract<KcContext, { pageId: "login-idp-link-confirm.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -17,17 +16,12 @@ export default function LoginIdpLinkConfirm(props: PageProps<Extract<KcContext,
|
|||||||
const { msg } = useI18n({ kcContext });
|
const { msg } = useI18n({ kcContext });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("confirmLinkIdpTitle")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("confirmLinkIdpTitle")}>
|
||||||
<form id="kc-register-form" action={url.loginAction} method="post">
|
<form id="kc-register-form" action={url.loginAction} method="post">
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="submitAction"
|
name="submitAction"
|
||||||
id="updateProfile"
|
id="updateProfile"
|
||||||
value="updateProfile"
|
value="updateProfile"
|
||||||
@ -36,12 +30,7 @@ export default function LoginIdpLinkConfirm(props: PageProps<Extract<KcContext,
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="submitAction"
|
name="submitAction"
|
||||||
id="linkAccount"
|
id="linkAccount"
|
||||||
value="linkAccount"
|
value="linkAccount"
|
||||||
|
@ -10,7 +10,7 @@ export default function LoginIdpLinkEmail(props: PageProps<Extract<KcContext, {
|
|||||||
const { msg } = useI18n({ kcContext });
|
const { msg } = useI18n({ kcContext });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("emailLinkIdpTitle", idpAlias)}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("emailLinkIdpTitle", idpAlias)}>
|
||||||
<p id="instruction1" className="instruction">
|
<p id="instruction1" className="instruction">
|
||||||
{msg("emailLinkIdp1", idpAlias, brokerContext.username, realm.displayName)}
|
{msg("emailLinkIdp1", idpAlias, brokerContext.username, realm.displayName)}
|
||||||
</p>
|
</p>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
import { PageProps } from "keycloakify/login/pages/PageProps";
|
import { PageProps } from "keycloakify/login/pages/PageProps";
|
||||||
import { KcContext } from "../KcContext";
|
import { KcContext } from "../KcContext";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -12,51 +11,47 @@ export default function LoginOauth2DeviceVerifyUserCode(
|
|||||||
|
|
||||||
const { msg, msgStr } = useI18n({ kcContext });
|
const { msg, msgStr } = useI18n({ kcContext });
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("oauth2DeviceVerificationTitle")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("oauth2DeviceVerificationTitle")}>
|
||||||
<form
|
<form
|
||||||
id="kc-user-verify-device-user-code-form"
|
id="kc-user-verify-device-user-code-form"
|
||||||
className={getClassName("kcFormClass")}
|
className={kcClsx("kcFormClass")}
|
||||||
action={url.oauth2DeviceVerificationAction}
|
action={url.oauth2DeviceVerificationAction}
|
||||||
method="post"
|
method="post"
|
||||||
>
|
>
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label htmlFor="device-user-code" className={getClassName("kcLabelClass")}>
|
<label htmlFor="device-user-code" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("verifyOAuth2DeviceUserCode")}
|
{msg("verifyOAuth2DeviceUserCode")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<input
|
<input
|
||||||
id="device-user-code"
|
id="device-user-code"
|
||||||
name="device_user_code"
|
name="device_user_code"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
type="text"
|
type="text"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}></div>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<div className={getClassName("kcFormButtonsWrapperClass")}>
|
<div className={kcClsx("kcFormButtonsWrapperClass")}>
|
||||||
<input
|
<input
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doSubmit")}
|
value={msgStr("doSubmit")}
|
||||||
/>
|
/>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
import { PageProps } from "keycloakify/login/pages/PageProps";
|
import { PageProps } from "keycloakify/login/pages/PageProps";
|
||||||
import { KcContext } from "../KcContext";
|
import { KcContext } from "../KcContext";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -10,14 +9,16 @@ export default function LoginOauthGrant(props: PageProps<Extract<KcContext, { pa
|
|||||||
|
|
||||||
const { msg, msgStr, advancedMsg, advancedMsgStr } = useI18n({ kcContext });
|
const { msg, msgStr, advancedMsg, advancedMsgStr } = useI18n({ kcContext });
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
bodyClassName="oauth"
|
bodyClassName="oauth"
|
||||||
headerNode={
|
headerNode={
|
||||||
<>
|
<>
|
||||||
@ -68,30 +69,22 @@ export default function LoginOauthGrant(props: PageProps<Extract<KcContext, { pa
|
|||||||
|
|
||||||
<form className="form-actions" action={url.oauthAction} method="POST">
|
<form className="form-actions" action={url.oauthAction} method="POST">
|
||||||
<input type="hidden" name="code" value={oauth.code} />
|
<input type="hidden" name="code" value={oauth.code} />
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div id="kc-form-options">
|
<div id="kc-form-options">
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}></div>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="kc-form-buttons">
|
<div id="kc-form-buttons">
|
||||||
<div className={getClassName("kcFormButtonsWrapperClass")}>
|
<div className={kcClsx("kcFormButtonsWrapperClass")}>
|
||||||
<input
|
<input
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="accept"
|
name="accept"
|
||||||
id="kc-login"
|
id="kc-login"
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doYes")}
|
value={msgStr("doYes")}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="cancel"
|
name="cancel"
|
||||||
id="kc-cancel"
|
id="kc-cancel"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Fragment } from "react";
|
import { Fragment } from "react";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -8,7 +7,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function LoginOtp(props: PageProps<Extract<KcContext, { pageId: "login-otp.ftl" }>>) {
|
export default function LoginOtp(props: PageProps<Extract<KcContext, { pageId: "login-otp.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -18,27 +17,33 @@ export default function LoginOtp(props: PageProps<Extract<KcContext, { pageId: "
|
|||||||
const { msg, msgStr } = useI18n({ kcContext });
|
const { msg, msgStr } = useI18n({ kcContext });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} displayMessage={!messagesPerField.existsError("totp")} headerNode={msg("doLogIn")}>
|
<Template
|
||||||
<form id="kc-otp-login-form" className={clsx(getClassName("kcFormClass"))} action={url.loginAction} method="post">
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
|
displayMessage={!messagesPerField.existsError("totp")}
|
||||||
|
headerNode={msg("doLogIn")}
|
||||||
|
>
|
||||||
|
<form id="kc-otp-login-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
{otpLogin.userOtpCredentials.length > 1 && (
|
{otpLogin.userOtpCredentials.length > 1 && (
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
{otpLogin.userOtpCredentials.map((otpCredential, index) => (
|
{otpLogin.userOtpCredentials.map((otpCredential, index) => (
|
||||||
<Fragment key={index}>
|
<Fragment key={index}>
|
||||||
<input
|
<input
|
||||||
id={`kc-otp-credential-${index}`}
|
id={`kc-otp-credential-${index}`}
|
||||||
className={getClassName("kcLoginOTPListInputClass")}
|
className={kcClsx("kcLoginOTPListInputClass")}
|
||||||
type="radio"
|
type="radio"
|
||||||
name="selectedCredentialId"
|
name="selectedCredentialId"
|
||||||
value={otpCredential.id}
|
value={otpCredential.id}
|
||||||
defaultChecked={otpCredential.id === otpLogin.selectedCredentialId}
|
defaultChecked={otpCredential.id === otpLogin.selectedCredentialId}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={`kc-otp-credential-${index}`} className={getClassName("kcLoginOTPListClass")} tabIndex={index}>
|
<label htmlFor={`kc-otp-credential-${index}`} className={kcClsx("kcLoginOTPListClass")} tabIndex={index}>
|
||||||
<span className={getClassName("kcLoginOTPListItemHeaderClass")}>
|
<span className={kcClsx("kcLoginOTPListItemHeaderClass")}>
|
||||||
<span className={getClassName("kcLoginOTPListItemIconBodyClass")}>
|
<span className={kcClsx("kcLoginOTPListItemIconBodyClass")}>
|
||||||
<i className={getClassName("kcLoginOTPListItemIconClass")} aria-hidden="true"></i>
|
<i className={kcClsx("kcLoginOTPListItemIconClass")} aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
<span className={getClassName("kcLoginOTPListItemTitleClass")}>{otpCredential.userLabel}</span>
|
<span className={kcClsx("kcLoginOTPListItemTitleClass")}>{otpCredential.userLabel}</span>
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
@ -47,42 +52,37 @@ export default function LoginOtp(props: PageProps<Extract<KcContext, { pageId: "
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label htmlFor="otp" className={getClassName("kcLabelClass")}>
|
<label htmlFor="otp" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("loginOtpOneTime")}
|
{msg("loginOtpOneTime")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<input
|
<input
|
||||||
id="otp"
|
id="otp"
|
||||||
name="otp"
|
name="otp"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
type="text"
|
type="text"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
autoFocus
|
autoFocus
|
||||||
aria-invalid={messagesPerField.existsError("totp")}
|
aria-invalid={messagesPerField.existsError("totp")}
|
||||||
/>
|
/>
|
||||||
{messagesPerField.existsError("totp") && (
|
{messagesPerField.existsError("totp") && (
|
||||||
<span id="input-error-otp-code" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error-otp-code" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.get("totp")}
|
{messagesPerField.get("totp")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}></div>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<input
|
<input
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="login"
|
name="login"
|
||||||
id="kc-login"
|
id="kc-login"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -10,7 +10,7 @@ export default function LoginPageExpired(props: PageProps<Extract<KcContext, { p
|
|||||||
const { msg } = useI18n({ kcContext });
|
const { msg } = useI18n({ kcContext });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("pageExpiredTitle")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("pageExpiredTitle")}>
|
||||||
<p id="instruction1" className="instruction">
|
<p id="instruction1" className="instruction">
|
||||||
{msg("pageExpiredMsg1")}
|
{msg("pageExpiredMsg1")}
|
||||||
<a id="loginRestartLink" href={url.loginRestartFlowUrl}>
|
<a id="loginRestartLink" href={url.loginRestartFlowUrl}>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useState, useEffect, useReducer } from "react";
|
import { useState, useEffect, useReducer } from "react";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
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";
|
||||||
import { useI18n, type I18n } from "../i18n";
|
import { useI18n, type I18n } from "../i18n";
|
||||||
@ -9,7 +9,7 @@ import { useI18n, type I18n } from "../i18n";
|
|||||||
export default function LoginPassword(props: PageProps<Extract<KcContext, { pageId: "login-password.ftl" }>>) {
|
export default function LoginPassword(props: PageProps<Extract<KcContext, { pageId: "login-password.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -22,7 +22,13 @@ export default function LoginPassword(props: PageProps<Extract<KcContext, { page
|
|||||||
const [isLoginButtonDisabled, setIsLoginButtonDisabled] = useState(false);
|
const [isLoginButtonDisabled, setIsLoginButtonDisabled] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("doLogIn")} displayMessage={!messagesPerField.existsError("password")}>
|
<Template
|
||||||
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
|
headerNode={msg("doLogIn")}
|
||||||
|
displayMessage={!messagesPerField.existsError("password")}
|
||||||
|
>
|
||||||
<div id="kc-form">
|
<div id="kc-form">
|
||||||
<div id="kc-form-wrapper">
|
<div id="kc-form-wrapper">
|
||||||
<form
|
<form
|
||||||
@ -34,17 +40,17 @@ export default function LoginPassword(props: PageProps<Extract<KcContext, { page
|
|||||||
action={url.loginAction}
|
action={url.loginAction}
|
||||||
method="post"
|
method="post"
|
||||||
>
|
>
|
||||||
<div className={clsx(getClassName("kcFormGroupClass"), "no-bottom-margin")}>
|
<div className={clsx(kcClsx("kcFormGroupClass"), "no-bottom-margin")}>
|
||||||
<hr />
|
<hr />
|
||||||
<label htmlFor="password" className={getClassName("kcLabelClass")}>
|
<label htmlFor="password" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("password")}
|
{msg("password")}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<PasswordWrapper getClassName={getClassName} i18n={i18n} passwordInputId="password">
|
<PasswordWrapper kcClsx={kcClsx} i18n={i18n} passwordInputId="password">
|
||||||
<input
|
<input
|
||||||
tabIndex={2}
|
tabIndex={2}
|
||||||
id="password"
|
id="password"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
name="password"
|
name="password"
|
||||||
type="password"
|
type="password"
|
||||||
autoFocus
|
autoFocus
|
||||||
@ -54,14 +60,14 @@ export default function LoginPassword(props: PageProps<Extract<KcContext, { page
|
|||||||
</PasswordWrapper>
|
</PasswordWrapper>
|
||||||
|
|
||||||
{messagesPerField.existsError("password") && (
|
{messagesPerField.existsError("password") && (
|
||||||
<span id="input-error-password" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error-password" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.get("password")}
|
{messagesPerField.get("password")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={clsx(getClassName("kcFormGroupClass"), getClassName("kcFormSettingClass"))}>
|
<div className={kcClsx("kcFormGroupClass", "kcFormSettingClass")}>
|
||||||
<div id="kc-form-options" />
|
<div id="kc-form-options" />
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}>
|
||||||
{realm.resetPasswordAllowed && (
|
{realm.resetPasswordAllowed && (
|
||||||
<span>
|
<span>
|
||||||
<a tabIndex={5} href={url.loginResetCredentialsUrl}>
|
<a tabIndex={5} href={url.loginResetCredentialsUrl}>
|
||||||
@ -71,15 +77,10 @@ export default function LoginPassword(props: PageProps<Extract<KcContext, { page
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormGroupClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormGroupClass")}>
|
||||||
<input
|
<input
|
||||||
tabIndex={4}
|
tabIndex={4}
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="login"
|
name="login"
|
||||||
id="kc-login"
|
id="kc-login"
|
||||||
type="submit"
|
type="submit"
|
||||||
@ -94,13 +95,8 @@ export default function LoginPassword(props: PageProps<Extract<KcContext, { page
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PasswordWrapper(props: {
|
function PasswordWrapper(props: { kcClsx: KcClsx; i18n: I18n; passwordInputId: string; children: JSX.Element }) {
|
||||||
getClassName: ReturnType<typeof useGetClassName>["getClassName"];
|
const { kcClsx, i18n, passwordInputId, children } = props;
|
||||||
i18n: I18n;
|
|
||||||
passwordInputId: string;
|
|
||||||
children: JSX.Element;
|
|
||||||
}) {
|
|
||||||
const { getClassName, i18n, passwordInputId, children } = props;
|
|
||||||
|
|
||||||
const { msgStr } = i18n;
|
const { msgStr } = i18n;
|
||||||
|
|
||||||
@ -115,19 +111,16 @@ function PasswordWrapper(props: {
|
|||||||
}, [isPasswordRevealed]);
|
}, [isPasswordRevealed]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={getClassName("kcInputGroup")}>
|
<div className={kcClsx("kcInputGroup")}>
|
||||||
{children}
|
{children}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={getClassName("kcFormPasswordVisibilityButtonClass")}
|
className={kcClsx("kcFormPasswordVisibilityButtonClass")}
|
||||||
aria-label={msgStr(isPasswordRevealed ? "hidePassword" : "showPassword")}
|
aria-label={msgStr(isPasswordRevealed ? "hidePassword" : "showPassword")}
|
||||||
aria-controls={passwordInputId}
|
aria-controls={passwordInputId}
|
||||||
onClick={toggleIsPasswordRevealed}
|
onClick={toggleIsPasswordRevealed}
|
||||||
>
|
>
|
||||||
<i
|
<i className={kcClsx(isPasswordRevealed ? "kcFormPasswordVisibilityIconHide" : "kcFormPasswordVisibilityIconShow")} aria-hidden />
|
||||||
className={getClassName(isPasswordRevealed ? "kcFormPasswordVisibilityIconHide" : "kcFormPasswordVisibilityIconShow")}
|
|
||||||
aria-hidden
|
|
||||||
/>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
||||||
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";
|
||||||
@ -9,7 +9,7 @@ import { useI18n, type I18n } from "../i18n";
|
|||||||
export default function LoginRecoveryAuthnCodeConfig(props: PageProps<Extract<KcContext, { pageId: "login-recovery-authn-code-config.ftl" }>>) {
|
export default function LoginRecoveryAuthnCodeConfig(props: PageProps<Extract<KcContext, { pageId: "login-recovery-authn-code-config.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -145,8 +145,8 @@ export default function LoginRecoveryAuthnCodeConfig(props: PageProps<Extract<Kc
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("recovery-code-config-header")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("recovery-code-config-header")}>
|
||||||
<div className={clsx("pf-c-alert", "pf-m-warning", "pf-m-inline", getClassName("kcRecoveryCodesWarning"))} aria-label="Warning alert">
|
<div className={clsx("pf-c-alert", "pf-m-warning", "pf-m-inline", kcClsx("kcRecoveryCodesWarning"))} aria-label="Warning alert">
|
||||||
<div className="pf-c-alert__icon">
|
<div className="pf-c-alert__icon">
|
||||||
<i className="pficon-warning-triangle-o" aria-hidden="true" />
|
<i className="pficon-warning-triangle-o" aria-hidden="true" />
|
||||||
</div>
|
</div>
|
||||||
@ -159,7 +159,7 @@ export default function LoginRecoveryAuthnCodeConfig(props: PageProps<Extract<Kc
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ol id="kc-recovery-codes-list" className={getClassName("kcRecoveryCodesList")}>
|
<ol id="kc-recovery-codes-list" className={kcClsx("kcRecoveryCodesList")}>
|
||||||
{recoveryAuthnCodesConfigBean.generatedRecoveryAuthnCodesList.map((code, index) => (
|
{recoveryAuthnCodesConfigBean.generatedRecoveryAuthnCodesList.map((code, index) => (
|
||||||
<li key={index}>
|
<li key={index}>
|
||||||
<span>{index + 1}:</span> {code.slice(0, 4)}-{code.slice(4, 8)}-{code.slice(8)}
|
<span>{index + 1}:</span> {code.slice(0, 4)}-{code.slice(4, 8)}-{code.slice(8)}
|
||||||
@ -168,7 +168,7 @@ export default function LoginRecoveryAuthnCodeConfig(props: PageProps<Extract<Kc
|
|||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
{/* actions */}
|
{/* actions */}
|
||||||
<div className={getClassName("kcRecoveryCodesActions")}>
|
<div className={kcClsx("kcRecoveryCodesActions")}>
|
||||||
<button id="printRecoveryCodes" className={clsx("pf-c-button", "pf-m-link")} type="button">
|
<button id="printRecoveryCodes" className={clsx("pf-c-button", "pf-m-link")} type="button">
|
||||||
<i className="pficon-print" aria-hidden="true" /> {msg("recovery-codes-print")}
|
<i className="pficon-print" aria-hidden="true" /> {msg("recovery-codes-print")}
|
||||||
</button>
|
</button>
|
||||||
@ -181,9 +181,9 @@ export default function LoginRecoveryAuthnCodeConfig(props: PageProps<Extract<Kc
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* confirmation checkbox */}
|
{/* confirmation checkbox */}
|
||||||
<div className={getClassName("kcFormOptionsClass")}>
|
<div className={kcClsx("kcFormOptionsClass")}>
|
||||||
<input
|
<input
|
||||||
className={getClassName("kcCheckInputClass")}
|
className={kcClsx("kcCheckInputClass")}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="kcRecoveryCodesConfirmationCheck"
|
id="kcRecoveryCodesConfirmationCheck"
|
||||||
name="kcRecoveryCodesConfirmationCheck"
|
name="kcRecoveryCodesConfirmationCheck"
|
||||||
@ -195,25 +195,25 @@ export default function LoginRecoveryAuthnCodeConfig(props: PageProps<Extract<Kc
|
|||||||
<label htmlFor="kcRecoveryCodesConfirmationCheck">{msg("recovery-codes-confirmation-message")}</label>
|
<label htmlFor="kcRecoveryCodesConfirmationCheck">{msg("recovery-codes-confirmation-message")}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form action={kcContext.url.loginAction} className={getClassName("kcFormGroupClass")} id="kc-recovery-codes-settings-form" method="post">
|
<form action={kcContext.url.loginAction} className={kcClsx("kcFormGroupClass")} id="kc-recovery-codes-settings-form" method="post">
|
||||||
<input type="hidden" name="generatedRecoveryAuthnCodes" value={recoveryAuthnCodesConfigBean.generatedRecoveryAuthnCodesAsString} />
|
<input type="hidden" name="generatedRecoveryAuthnCodes" value={recoveryAuthnCodesConfigBean.generatedRecoveryAuthnCodesAsString} />
|
||||||
<input type="hidden" name="generatedAt" value={recoveryAuthnCodesConfigBean.generatedAt} />
|
<input type="hidden" name="generatedAt" value={recoveryAuthnCodesConfigBean.generatedAt} />
|
||||||
<input type="hidden" id="userLabel" name="userLabel" value={msgStr("recovery-codes-label-default")} />
|
<input type="hidden" id="userLabel" name="userLabel" value={msgStr("recovery-codes-label-default")} />
|
||||||
|
|
||||||
<LogoutOtherSessions {...{ getClassName, i18n }} />
|
<LogoutOtherSessions kcClsx={kcClsx} i18n={i18n} />
|
||||||
|
|
||||||
{isAppInitiatedAction ? (
|
{isAppInitiatedAction ? (
|
||||||
<>
|
<>
|
||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(getClassName("kcButtonClass"), getClassName("kcButtonPrimaryClass"), getClassName("kcButtonLargeClass"))}
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
id="saveRecoveryAuthnCodesBtn"
|
id="saveRecoveryAuthnCodesBtn"
|
||||||
value={msgStr("recovery-codes-action-complete")}
|
value={msgStr("recovery-codes-action-complete")}
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(getClassName("kcButtonClass"), getClassName("kcButtonDefaultClass"), getClassName("kcButtonLargeClass"))}
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
|
||||||
id="cancelRecoveryAuthnCodesBtn"
|
id="cancelRecoveryAuthnCodesBtn"
|
||||||
name="cancel-aia"
|
name="cancel-aia"
|
||||||
value="true"
|
value="true"
|
||||||
@ -224,12 +224,7 @@ export default function LoginRecoveryAuthnCodeConfig(props: PageProps<Extract<Kc
|
|||||||
) : (
|
) : (
|
||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
id="saveRecoveryAuthnCodesBtn"
|
id="saveRecoveryAuthnCodesBtn"
|
||||||
value={msgStr("recovery-codes-action-complete")}
|
value={msgStr("recovery-codes-action-complete")}
|
||||||
disabled
|
disabled
|
||||||
@ -240,14 +235,14 @@ export default function LoginRecoveryAuthnCodeConfig(props: PageProps<Extract<Kc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function LogoutOtherSessions(props: { getClassName: ReturnType<typeof useGetClassName>["getClassName"]; i18n: I18n }) {
|
function LogoutOtherSessions(props: { kcClsx: KcClsx; i18n: I18n }) {
|
||||||
const { getClassName, i18n } = props;
|
const { kcClsx, i18n } = props;
|
||||||
|
|
||||||
const { msg } = i18n;
|
const { msg } = i18n;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}>
|
||||||
<div className="checkbox">
|
<div className="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
|
<input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -7,7 +6,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function LoginRecoveryAuthnCodeInput(props: PageProps<Extract<KcContext, { pageId: "login-recovery-authn-code-input.ftl" }>>) {
|
export default function LoginRecoveryAuthnCodeInput(props: PageProps<Extract<KcContext, { pageId: "login-recovery-authn-code-input.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -18,18 +17,20 @@ export default function LoginRecoveryAuthnCodeInput(props: PageProps<Extract<KcC
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
headerNode={msg("auth-recovery-code-header")}
|
headerNode={msg("auth-recovery-code-header")}
|
||||||
displayMessage={!messagesPerField.existsError("recoveryCodeInput")}
|
displayMessage={!messagesPerField.existsError("recoveryCodeInput")}
|
||||||
>
|
>
|
||||||
<form id="kc-recovery-code-login-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
|
<form id="kc-recovery-code-login-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label htmlFor="recoveryCodeInput" className={getClassName("kcLabelClass")}>
|
<label htmlFor="recoveryCodeInput" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("auth-recovery-code-prompt", `${recoveryAuthnCodesInputBean.codeNumber}`)}
|
{msg("auth-recovery-code-prompt", `${recoveryAuthnCodesInputBean.codeNumber}`)}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<input
|
<input
|
||||||
tabIndex={1}
|
tabIndex={1}
|
||||||
id="recoveryCodeInput"
|
id="recoveryCodeInput"
|
||||||
@ -37,29 +38,24 @@ export default function LoginRecoveryAuthnCodeInput(props: PageProps<Extract<KcC
|
|||||||
aria-invalid={messagesPerField.existsError("recoveryCodeInput")}
|
aria-invalid={messagesPerField.existsError("recoveryCodeInput")}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
type="text"
|
type="text"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
{messagesPerField.existsError("recoveryCodeInput") && (
|
{messagesPerField.existsError("recoveryCodeInput") && (
|
||||||
<span id="input-error" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.get("recoveryCodeInput")}
|
{messagesPerField.get("recoveryCodeInput")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsWrapperClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsWrapperClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")} />
|
<div className={kcClsx("kcFormOptionsWrapperClass")} />
|
||||||
</div>
|
</div>
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<input
|
<input
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="login"
|
name="login"
|
||||||
id="kc-login"
|
id="kc-login"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Fragment } from "react";
|
import { Fragment } from "react";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -8,7 +7,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function LoginResetOtp(props: PageProps<Extract<KcContext, { pageId: "login-reset-otp.ftl" }>>) {
|
export default function LoginResetOtp(props: PageProps<Extract<KcContext, { pageId: "login-reset-otp.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -18,41 +17,42 @@ export default function LoginResetOtp(props: PageProps<Extract<KcContext, { page
|
|||||||
const { msg, msgStr } = useI18n({ kcContext });
|
const { msg, msgStr } = useI18n({ kcContext });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} displayMessage={!messagesPerField.existsError("totp")} headerNode={msg("doLogIn")}>
|
<Template
|
||||||
<form id="kc-otp-reset-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
|
kcContext={kcContext}
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
<div className={getClassName("kcInfoAreaWrapperClass")}>
|
classes={classes}
|
||||||
|
displayMessage={!messagesPerField.existsError("totp")}
|
||||||
|
headerNode={msg("doLogIn")}
|
||||||
|
>
|
||||||
|
<form id="kc-otp-reset-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
|
<div className={kcClsx("kcInfoAreaWrapperClass")}>
|
||||||
<p id="kc-otp-reset-form-description">{msg("otp-reset-description")}</p>
|
<p id="kc-otp-reset-form-description">{msg("otp-reset-description")}</p>
|
||||||
{configuredOtpCredentials.userOtpCredentials.map((otpCredential, index) => (
|
{configuredOtpCredentials.userOtpCredentials.map((otpCredential, index) => (
|
||||||
<Fragment key={otpCredential.id}>
|
<Fragment key={otpCredential.id}>
|
||||||
<input
|
<input
|
||||||
id={`kc-otp-credential-${index}`}
|
id={`kc-otp-credential-${index}`}
|
||||||
className={getClassName("kcLoginOTPListInputClass")}
|
className={kcClsx("kcLoginOTPListInputClass")}
|
||||||
type="radio"
|
type="radio"
|
||||||
name="selectedCredentialId"
|
name="selectedCredentialId"
|
||||||
value={otpCredential.id}
|
value={otpCredential.id}
|
||||||
defaultChecked={otpCredential.id === configuredOtpCredentials.selectedCredentialId}
|
defaultChecked={otpCredential.id === configuredOtpCredentials.selectedCredentialId}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={`kc-otp-credential-${index}`} className={getClassName("kcLoginOTPListClass")} tabIndex={index}>
|
<label htmlFor={`kc-otp-credential-${index}`} className={kcClsx("kcLoginOTPListClass")} tabIndex={index}>
|
||||||
<span className={getClassName("kcLoginOTPListItemHeaderClass")}>
|
<span className={kcClsx("kcLoginOTPListItemHeaderClass")}>
|
||||||
<span className={getClassName("kcLoginOTPListItemIconBodyClass")}>
|
<span className={kcClsx("kcLoginOTPListItemIconBodyClass")}>
|
||||||
<i className={getClassName("kcLoginOTPListItemIconClass")} aria-hidden="true"></i>
|
<i className={kcClsx("kcLoginOTPListItemIconClass")} aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
<span className={getClassName("kcLoginOTPListItemTitleClass")}>{otpCredential.userLabel}</span>
|
<span className={kcClsx("kcLoginOTPListItemTitleClass")}>{otpCredential.userLabel}</span>
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<input
|
<input
|
||||||
id="kc-otp-reset-form-submit"
|
id="kc-otp-reset-form-submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doSubmit")}
|
value={msgStr("doSubmit")}
|
||||||
/>
|
/>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -7,7 +6,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function LoginResetPassword(props: PageProps<Extract<KcContext, { pageId: "login-reset-password.ftl" }>>) {
|
export default function LoginResetPassword(props: PageProps<Extract<KcContext, { pageId: "login-reset-password.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -18,16 +17,18 @@ export default function LoginResetPassword(props: PageProps<Extract<KcContext, {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
displayInfo
|
displayInfo
|
||||||
displayMessage={!messagesPerField.existsError("username")}
|
displayMessage={!messagesPerField.existsError("username")}
|
||||||
infoNode={realm.duplicateEmailsAllowed ? msg("emailInstructionUsername") : msg("emailInstruction")}
|
infoNode={realm.duplicateEmailsAllowed ? msg("emailInstructionUsername") : msg("emailInstruction")}
|
||||||
headerNode={msg("emailForgotTitle")}
|
headerNode={msg("emailForgotTitle")}
|
||||||
>
|
>
|
||||||
<form id="kc-reset-password-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
|
<form id="kc-reset-password-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label htmlFor="username" className={getClassName("kcLabelClass")}>
|
<label htmlFor="username" className={kcClsx("kcLabelClass")}>
|
||||||
{!realm.loginWithEmailAllowed
|
{!realm.loginWithEmailAllowed
|
||||||
? msg("username")
|
? msg("username")
|
||||||
: !realm.registrationEmailAsUsername
|
: !realm.registrationEmailAsUsername
|
||||||
@ -35,40 +36,35 @@ export default function LoginResetPassword(props: PageProps<Extract<KcContext, {
|
|||||||
: msg("email")}
|
: msg("email")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="username"
|
id="username"
|
||||||
name="username"
|
name="username"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
autoFocus
|
autoFocus
|
||||||
defaultValue={auth.attemptedUsername ?? ""}
|
defaultValue={auth.attemptedUsername ?? ""}
|
||||||
aria-invalid={messagesPerField.existsError("username")}
|
aria-invalid={messagesPerField.existsError("username")}
|
||||||
/>
|
/>
|
||||||
{messagesPerField.existsError("username") && (
|
{messagesPerField.existsError("username") && (
|
||||||
<span id="input-error-username" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error-username" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.get("username")}
|
{messagesPerField.get("username")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={clsx(getClassName("kcFormGroupClass"), getClassName("kcFormSettingClass"))}>
|
<div className={kcClsx("kcFormGroupClass", "kcFormSettingClass")}>
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}>
|
||||||
<span>
|
<span>
|
||||||
<a href={url.loginUrl}>{msg("backToLogin")}</a>
|
<a href={url.loginUrl}>{msg("backToLogin")}</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<input
|
<input
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doSubmit")}
|
value={msgStr("doSubmit")}
|
||||||
/>
|
/>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { useEffect, useReducer } from "react";
|
import { useEffect, useReducer } from "react";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
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";
|
||||||
import { useI18n, type I18n } from "../i18n";
|
import { useI18n, type I18n } from "../i18n";
|
||||||
@ -9,7 +8,7 @@ import { useI18n, type I18n } from "../i18n";
|
|||||||
export default function LoginUpdatePassword(props: PageProps<Extract<KcContext, { pageId: "login-update-password.ftl" }>>) {
|
export default function LoginUpdatePassword(props: PageProps<Extract<KcContext, { pageId: "login-update-password.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -21,23 +20,25 @@ export default function LoginUpdatePassword(props: PageProps<Extract<KcContext,
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
displayMessage={!messagesPerField.existsError("password", "password-confirm")}
|
displayMessage={!messagesPerField.existsError("password", "password-confirm")}
|
||||||
headerNode={msg("updatePasswordTitle")}
|
headerNode={msg("updatePasswordTitle")}
|
||||||
>
|
>
|
||||||
<form id="kc-passwd-update-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
|
<form id="kc-passwd-update-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label htmlFor="password-new" className={getClassName("kcLabelClass")}>
|
<label htmlFor="password-new" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("passwordNew")}
|
{msg("passwordNew")}
|
||||||
</label>
|
</label>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<PasswordWrapper {...{ getClassName, i18n }} passwordInputId="password-new">
|
<PasswordWrapper kcClsx={kcClsx} i18n={i18n} passwordInputId="password-new">
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
id="password-new"
|
id="password-new"
|
||||||
name="password-new"
|
name="password-new"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
autoFocus
|
autoFocus
|
||||||
autoComplete="new-password"
|
autoComplete="new-password"
|
||||||
aria-invalid={messagesPerField.existsError("password", "password-confirm")}
|
aria-invalid={messagesPerField.existsError("password", "password-confirm")}
|
||||||
@ -45,7 +46,7 @@ export default function LoginUpdatePassword(props: PageProps<Extract<KcContext,
|
|||||||
</PasswordWrapper>
|
</PasswordWrapper>
|
||||||
|
|
||||||
{messagesPerField.existsError("password") && (
|
{messagesPerField.existsError("password") && (
|
||||||
<span id="input-error-password" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error-password" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.get("password")}
|
{messagesPerField.get("password")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@ -53,19 +54,19 @@ export default function LoginUpdatePassword(props: PageProps<Extract<KcContext,
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label htmlFor="password-confirm" className={getClassName("kcLabelClass")}>
|
<label htmlFor="password-confirm" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("passwordConfirm")}
|
{msg("passwordConfirm")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<PasswordWrapper {...{ getClassName, i18n }} passwordInputId="password-confirm">
|
<PasswordWrapper kcClsx={kcClsx} i18n={i18n} passwordInputId="password-confirm">
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
id="password-confirm"
|
id="password-confirm"
|
||||||
name="password-confirm"
|
name="password-confirm"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
autoFocus
|
autoFocus
|
||||||
autoComplete="new-password"
|
autoComplete="new-password"
|
||||||
aria-invalid={messagesPerField.existsError("password", "password-confirm")}
|
aria-invalid={messagesPerField.existsError("password", "password-confirm")}
|
||||||
@ -73,33 +74,29 @@ export default function LoginUpdatePassword(props: PageProps<Extract<KcContext,
|
|||||||
</PasswordWrapper>
|
</PasswordWrapper>
|
||||||
|
|
||||||
{messagesPerField.existsError("password-confirm") && (
|
{messagesPerField.existsError("password-confirm") && (
|
||||||
<span id="input-error-password-confirm" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error-password-confirm" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.get("password-confirm")}
|
{messagesPerField.get("password-confirm")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<LogoutOtherSessions {...{ getClassName, i18n }} />
|
<LogoutOtherSessions kcClsx={kcClsx} i18n={i18n} />
|
||||||
|
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<input
|
<input
|
||||||
className={clsx(
|
className={kcClsx(
|
||||||
getClassName("kcButtonClass"),
|
"kcButtonClass",
|
||||||
getClassName("kcButtonPrimaryClass"),
|
"kcButtonPrimaryClass",
|
||||||
isAppInitiatedAction && getClassName("kcButtonBlockClass"),
|
isAppInitiatedAction && "kcButtonBlockClass",
|
||||||
getClassName("kcButtonLargeClass")
|
"kcButtonLargeClass"
|
||||||
)}
|
)}
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doSubmit")}
|
value={msgStr("doSubmit")}
|
||||||
/>
|
/>
|
||||||
{isAppInitiatedAction && (
|
{isAppInitiatedAction && (
|
||||||
<button
|
<button
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
type="submit"
|
type="submit"
|
||||||
name="cancel-aia"
|
name="cancel-aia"
|
||||||
value="true"
|
value="true"
|
||||||
@ -115,14 +112,14 @@ export default function LoginUpdatePassword(props: PageProps<Extract<KcContext,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function LogoutOtherSessions(props: { getClassName: ReturnType<typeof useGetClassName>["getClassName"]; i18n: I18n }) {
|
function LogoutOtherSessions(props: { kcClsx: KcClsx; i18n: I18n }) {
|
||||||
const { getClassName, i18n } = props;
|
const { kcClsx, i18n } = props;
|
||||||
|
|
||||||
const { msg } = i18n;
|
const { msg } = i18n;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}>
|
||||||
<div className="checkbox">
|
<div className="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
|
<input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
|
||||||
@ -134,13 +131,8 @@ function LogoutOtherSessions(props: { getClassName: ReturnType<typeof useGetClas
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function PasswordWrapper(props: {
|
function PasswordWrapper(props: { kcClsx: KcClsx; i18n: I18n; passwordInputId: string; children: JSX.Element }) {
|
||||||
getClassName: ReturnType<typeof useGetClassName>["getClassName"];
|
const { kcClsx, i18n, passwordInputId, children } = props;
|
||||||
i18n: I18n;
|
|
||||||
passwordInputId: string;
|
|
||||||
children: JSX.Element;
|
|
||||||
}) {
|
|
||||||
const { getClassName, i18n, passwordInputId, children } = props;
|
|
||||||
|
|
||||||
const { msgStr } = i18n;
|
const { msgStr } = i18n;
|
||||||
|
|
||||||
@ -155,19 +147,16 @@ function PasswordWrapper(props: {
|
|||||||
}, [isPasswordRevealed]);
|
}, [isPasswordRevealed]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={getClassName("kcInputGroup")}>
|
<div className={kcClsx("kcInputGroup")}>
|
||||||
{children}
|
{children}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={getClassName("kcFormPasswordVisibilityButtonClass")}
|
className={kcClsx("kcFormPasswordVisibilityButtonClass")}
|
||||||
aria-label={msgStr(isPasswordRevealed ? "hidePassword" : "showPassword")}
|
aria-label={msgStr(isPasswordRevealed ? "hidePassword" : "showPassword")}
|
||||||
aria-controls={passwordInputId}
|
aria-controls={passwordInputId}
|
||||||
onClick={toggleIsPasswordRevealed}
|
onClick={toggleIsPasswordRevealed}
|
||||||
>
|
>
|
||||||
<i
|
<i className={kcClsx(isPasswordRevealed ? "kcFormPasswordVisibilityIconHide" : "kcFormPasswordVisibilityIconShow")} aria-hidden />
|
||||||
className={getClassName(isPasswordRevealed ? "kcFormPasswordVisibilityIconHide" : "kcFormPasswordVisibilityIconShow")}
|
|
||||||
aria-hidden
|
|
||||||
/>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import type { UserProfileFormFieldsProps } from "keycloakify/login/UserProfileFormFields";
|
import type { UserProfileFormFieldsProps } from "keycloakify/login/UserProfileFormFields";
|
||||||
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";
|
||||||
@ -14,51 +13,46 @@ type LoginUpdateProfileProps = PageProps<Extract<KcContext, { pageId: "login-upd
|
|||||||
export default function LoginUpdateProfile(props: LoginUpdateProfileProps) {
|
export default function LoginUpdateProfile(props: LoginUpdateProfileProps) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
|
const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
|
|
||||||
const { url, messagesPerField, isAppInitiatedAction } = kcContext;
|
const { url, isAppInitiatedAction } = kcContext;
|
||||||
|
|
||||||
const { msg, msgStr } = useI18n({ kcContext });
|
const { msg, msgStr } = useI18n({ kcContext });
|
||||||
|
|
||||||
const [isFormSubmittable, setIsFormSubmittable] = useState(false);
|
const [isFormSubmittable, setIsFormSubmittable] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} displayRequiredFields headerNode={msg("loginProfileTitle")}>
|
<Template
|
||||||
<form id="kc-update-profile-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
|
kcContext={kcContext}
|
||||||
<UserProfileFormFields
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
{...{
|
classes={classes}
|
||||||
kcContext,
|
displayRequiredFields
|
||||||
getClassName,
|
headerNode={msg("loginProfileTitle")}
|
||||||
messagesPerField
|
>
|
||||||
}}
|
<form id="kc-update-profile-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
onIsFormSubmittableValueChange={setIsFormSubmittable}
|
<UserProfileFormFields kcContext={kcContext} kcClsx={kcClsx} onIsFormSubmittableValueChange={setIsFormSubmittable} />
|
||||||
/>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div className={kcClsx("kcFormOptionsWrapperClass")} />
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")} />
|
|
||||||
</div>
|
</div>
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<input
|
<input
|
||||||
disabled={!isFormSubmittable}
|
disabled={!isFormSubmittable}
|
||||||
className={clsx(
|
className={kcClsx(
|
||||||
getClassName("kcButtonClass"),
|
"kcButtonClass",
|
||||||
getClassName("kcButtonPrimaryClass"),
|
"kcButtonPrimaryClass",
|
||||||
!isAppInitiatedAction && getClassName("kcButtonBlockClass"),
|
!isAppInitiatedAction && "kcButtonBlockClass",
|
||||||
getClassName("kcButtonLargeClass")
|
"kcButtonLargeClass"
|
||||||
)}
|
)}
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doSubmit")}
|
value={msgStr("doSubmit")}
|
||||||
/>
|
/>
|
||||||
{isAppInitiatedAction && (
|
{isAppInitiatedAction && (
|
||||||
<button
|
<button
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
type="submit"
|
type="submit"
|
||||||
name="cancel-aia"
|
name="cancel-aia"
|
||||||
value="true"
|
value="true"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
import { getKcClsx } 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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -8,7 +8,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function LoginUsername(props: PageProps<Extract<KcContext, { pageId: "login-username.ftl" }>>) {
|
export default function LoginUsername(props: PageProps<Extract<KcContext, { pageId: "login-username.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -21,7 +21,9 @@ export default function LoginUsername(props: PageProps<Extract<KcContext, { page
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
displayMessage={!messagesPerField.existsError("username")}
|
displayMessage={!messagesPerField.existsError("username")}
|
||||||
displayInfo={realm.password && realm.registrationAllowed && !registrationDisabled}
|
displayInfo={realm.password && realm.registrationAllowed && !registrationDisabled}
|
||||||
infoNode={
|
infoNode={
|
||||||
@ -38,32 +40,23 @@ export default function LoginUsername(props: PageProps<Extract<KcContext, { page
|
|||||||
socialProvidersNode={
|
socialProvidersNode={
|
||||||
<>
|
<>
|
||||||
{realm.password && social.providers?.length && (
|
{realm.password && social.providers?.length && (
|
||||||
<div id="kc-social-providers" className={getClassName("kcFormSocialAccountSectionClass")}>
|
<div id="kc-social-providers" className={kcClsx("kcFormSocialAccountSectionClass")}>
|
||||||
<hr />
|
<hr />
|
||||||
<h2>{msg("identity-provider-login-label")}</h2>
|
<h2>{msg("identity-provider-login-label")}</h2>
|
||||||
<ul
|
<ul className={kcClsx("kcFormSocialAccountListClass", social.providers.length > 3 && "kcFormSocialAccountListGridClass")}>
|
||||||
className={clsx(
|
|
||||||
getClassName("kcFormSocialAccountListClass"),
|
|
||||||
social.providers.length > 3 && getClassName("kcFormSocialAccountListGridClass")
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{social.providers.map((...[p, , providers]) => (
|
{social.providers.map((...[p, , providers]) => (
|
||||||
<li key={p.alias}>
|
<li key={p.alias}>
|
||||||
<a
|
<a
|
||||||
id={`social-${p.alias}`}
|
id={`social-${p.alias}`}
|
||||||
className={clsx(
|
className={kcClsx(
|
||||||
getClassName("kcFormSocialAccountListButtonClass"),
|
"kcFormSocialAccountListButtonClass",
|
||||||
providers.length > 3 && getClassName("kcFormSocialAccountGridItem")
|
providers.length > 3 && "kcFormSocialAccountGridItem"
|
||||||
)}
|
)}
|
||||||
type="button"
|
type="button"
|
||||||
href={p.loginUrl}
|
href={p.loginUrl}
|
||||||
>
|
>
|
||||||
{p.iconClasses && (
|
{p.iconClasses && <i className={clsx(kcClsx("kcCommonLogoIdP"), p.iconClasses)} aria-hidden="true"></i>}
|
||||||
<i className={clsx(getClassName("kcCommonLogoIdP"), p.iconClasses)} aria-hidden="true"></i>
|
<span className={clsx(kcClsx("kcFormSocialAccountNameClass"), p.iconClasses && "kc-social-icon-text")}>
|
||||||
)}
|
|
||||||
<span
|
|
||||||
className={clsx(getClassName("kcFormSocialAccountNameClass"), p.iconClasses && "kc-social-icon-text")}
|
|
||||||
>
|
|
||||||
{p.displayName}
|
{p.displayName}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
@ -88,8 +81,8 @@ export default function LoginUsername(props: PageProps<Extract<KcContext, { page
|
|||||||
method="post"
|
method="post"
|
||||||
>
|
>
|
||||||
{!usernameHidden && (
|
{!usernameHidden && (
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<label htmlFor="username" className={getClassName("kcLabelClass")}>
|
<label htmlFor="username" className={kcClsx("kcLabelClass")}>
|
||||||
{!realm.loginWithEmailAllowed
|
{!realm.loginWithEmailAllowed
|
||||||
? msg("username")
|
? msg("username")
|
||||||
: !realm.registrationEmailAsUsername
|
: !realm.registrationEmailAsUsername
|
||||||
@ -99,7 +92,7 @@ export default function LoginUsername(props: PageProps<Extract<KcContext, { page
|
|||||||
<input
|
<input
|
||||||
tabIndex={2}
|
tabIndex={2}
|
||||||
id="username"
|
id="username"
|
||||||
className={getClassName("kcInputClass")}
|
className={kcClsx("kcInputClass")}
|
||||||
name="username"
|
name="username"
|
||||||
defaultValue={login.username ?? ""}
|
defaultValue={login.username ?? ""}
|
||||||
type="text"
|
type="text"
|
||||||
@ -108,14 +101,14 @@ export default function LoginUsername(props: PageProps<Extract<KcContext, { page
|
|||||||
aria-invalid={messagesPerField.existsError("username")}
|
aria-invalid={messagesPerField.existsError("username")}
|
||||||
/>
|
/>
|
||||||
{messagesPerField.existsError("username") && (
|
{messagesPerField.existsError("username") && (
|
||||||
<span id="input-error" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.getFirstError("username")}
|
{messagesPerField.getFirstError("username")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={clsx(getClassName("kcFormGroupClass"), getClassName("kcFormSettingClass"))}>
|
<div className={kcClsx("kcFormGroupClass", "kcFormSettingClass")}>
|
||||||
<div id="kc-form-options">
|
<div id="kc-form-options">
|
||||||
{realm.rememberMe && !usernameHidden && (
|
{realm.rememberMe && !usernameHidden && (
|
||||||
<div className="checkbox">
|
<div className="checkbox">
|
||||||
@ -134,16 +127,11 @@ export default function LoginUsername(props: PageProps<Extract<KcContext, { page
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormGroupClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormGroupClass")}>
|
||||||
<input
|
<input
|
||||||
tabIndex={4}
|
tabIndex={4}
|
||||||
disabled={isLoginButtonDisabled}
|
disabled={isLoginButtonDisabled}
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="login"
|
name="login"
|
||||||
id="kc-login"
|
id="kc-login"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -11,7 +11,9 @@ export default function LoginVerifyEmail(props: PageProps<Extract<KcContext, { p
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
displayInfo
|
displayInfo
|
||||||
headerNode={msg("emailVerifyTitle")}
|
headerNode={msg("emailVerifyTitle")}
|
||||||
infoNode={
|
infoNode={
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -7,7 +6,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function LoginX509Info(props: PageProps<Extract<KcContext, { pageId: "login-x509-info.ftl" }>>) {
|
export default function LoginX509Info(props: PageProps<Extract<KcContext, { pageId: "login-x509-info.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -17,56 +16,52 @@ export default function LoginX509Info(props: PageProps<Extract<KcContext, { page
|
|||||||
const { msg, msgStr } = useI18n({ kcContext });
|
const { msg, msgStr } = useI18n({ kcContext });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("doLogIn")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("doLogIn")}>
|
||||||
<form id="kc-x509-login-info" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
|
<form id="kc-x509-login-info" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label htmlFor="certificate_subjectDN" className={getClassName("kcLabelClass")}>
|
<label htmlFor="certificate_subjectDN" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("clientCertificate")}
|
{msg("clientCertificate")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{x509.formData.subjectDN ? (
|
{x509.formData.subjectDN ? (
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label id="certificate_subjectDN" className={getClassName("kcLabelClass")}>
|
<label id="certificate_subjectDN" className={kcClsx("kcLabelClass")}>
|
||||||
{x509.formData.subjectDN}
|
{x509.formData.subjectDN}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label id="certificate_subjectDN" className={getClassName("kcLabelClass")}>
|
<label id="certificate_subjectDN" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("noCertificate")}
|
{msg("noCertificate")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
{x509.formData.isUserEnabled && (
|
{x509.formData.isUserEnabled && (
|
||||||
<>
|
<>
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label htmlFor="username" className={getClassName("kcLabelClass")}>
|
<label htmlFor="username" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("doX509Login")}
|
{msg("doX509Login")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<label id="username" className={getClassName("kcLabelClass")}>
|
<label id="username" className={kcClsx("kcLabelClass")}>
|
||||||
{x509.formData.username}
|
{x509.formData.username}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")} />
|
<div className={kcClsx("kcFormOptionsWrapperClass")} />
|
||||||
</div>
|
</div>
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<div className={getClassName("kcFormButtonsWrapperClass")}>
|
<div className={kcClsx("kcFormButtonsWrapperClass")}>
|
||||||
<input
|
<input
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="login"
|
name="login"
|
||||||
id="kc-login"
|
id="kc-login"
|
||||||
type="submit"
|
type="submit"
|
||||||
@ -74,11 +69,7 @@ export default function LoginX509Info(props: PageProps<Extract<KcContext, { page
|
|||||||
/>
|
/>
|
||||||
{x509.formData.isUserEnabled && (
|
{x509.formData.isUserEnabled && (
|
||||||
<input
|
<input
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="cancel"
|
name="cancel"
|
||||||
id="kc-cancel"
|
id="kc-cancel"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -7,7 +6,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function LogoutConfirm(props: PageProps<Extract<KcContext, { pageId: "logout-confirm.ftl" }>>) {
|
export default function LogoutConfirm(props: PageProps<Extract<KcContext, { pageId: "logout-confirm.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -17,24 +16,19 @@ export default function LogoutConfirm(props: PageProps<Extract<KcContext, { page
|
|||||||
const { msg, msgStr } = useI18n({ kcContext });
|
const { msg, msgStr } = useI18n({ kcContext });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("logoutConfirmTitle")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("logoutConfirmTitle")}>
|
||||||
<div id="kc-logout-confirm" className="content-area">
|
<div id="kc-logout-confirm" className="content-area">
|
||||||
<p className="instruction">{msg("logoutConfirmHeader")}</p>
|
<p className="instruction">{msg("logoutConfirmHeader")}</p>
|
||||||
<form className="form-actions" action={url.logoutConfirmAction} method="POST">
|
<form className="form-actions" action={url.logoutConfirmAction} method="POST">
|
||||||
<input type="hidden" name="session_code" value={logoutConfirm.code} />
|
<input type="hidden" name="session_code" value={logoutConfirm.code} />
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div id="kc-form-options">
|
<div id="kc-form-options">
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}></div>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormGroupClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormGroupClass")}>
|
||||||
<input
|
<input
|
||||||
tabIndex={4}
|
tabIndex={4}
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="confirmLogout"
|
name="confirmLogout"
|
||||||
id="kc-logout"
|
id="kc-logout"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
|
||||||
import { Markdown } from "keycloakify/tools/Markdown";
|
import { Markdown } from "keycloakify/tools/Markdown";
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
import { useTermsMarkdown } from "keycloakify/login/lib/useDownloadTerms";
|
import { useTermsMarkdown } from "keycloakify/login/lib/useDownloadTerms";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import type { UserProfileFormFieldsProps } from "keycloakify/login/UserProfileFormFields";
|
import type { UserProfileFormFieldsProps } from "keycloakify/login/UserProfileFormFields";
|
||||||
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";
|
||||||
@ -16,7 +15,7 @@ type RegisterProps = PageProps<Extract<KcContext, { pageId: "register.ftl" }>> &
|
|||||||
export default function Register(props: RegisterProps) {
|
export default function Register(props: RegisterProps) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
|
const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -29,49 +28,29 @@ export default function Register(props: RegisterProps) {
|
|||||||
const [isFormSubmittable, setIsFormSubmittable] = useState(false);
|
const [isFormSubmittable, setIsFormSubmittable] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("registerTitle")} displayRequiredFields>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("registerTitle")} displayRequiredFields>
|
||||||
<form id="kc-register-form" className={getClassName("kcFormClass")} action={url.registrationAction} method="post">
|
<form id="kc-register-form" className={kcClsx("kcFormClass")} action={url.registrationAction} method="post">
|
||||||
<UserProfileFormFields
|
<UserProfileFormFields kcContext={kcContext} kcClsx={kcClsx} onIsFormSubmittableValueChange={setIsFormSubmittable} />
|
||||||
{...{
|
{termsAcceptanceRequired && <TermsAcceptance i18n={i18n} kcClsx={kcClsx} messagesPerField={messagesPerField} />}
|
||||||
kcContext,
|
|
||||||
getClassName,
|
|
||||||
messagesPerField
|
|
||||||
}}
|
|
||||||
onIsFormSubmittableValueChange={setIsFormSubmittable}
|
|
||||||
/>
|
|
||||||
{termsAcceptanceRequired && (
|
|
||||||
<TermsAcceptance
|
|
||||||
{...{
|
|
||||||
i18n,
|
|
||||||
getClassName,
|
|
||||||
messagesPerField
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{recaptchaRequired && (
|
{recaptchaRequired && (
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
<div className="g-recaptcha" data-size="compact" data-sitekey={recaptchaSiteKey}></div>
|
<div className="g-recaptcha" data-size="compact" data-sitekey={recaptchaSiteKey}></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}>
|
||||||
<span>
|
<span>
|
||||||
<a href={url.loginUrl}>{msg("backToLogin")}</a>
|
<a href={url.loginUrl}>{msg("backToLogin")}</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<input
|
<input
|
||||||
disabled={!isFormSubmittable}
|
disabled={!isFormSubmittable}
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doRegister")}
|
value={msgStr("doRegister")}
|
||||||
/>
|
/>
|
||||||
@ -82,12 +61,8 @@ export default function Register(props: RegisterProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TermsAcceptance(props: {
|
function TermsAcceptance(props: { i18n: I18n; kcClsx: KcClsx; messagesPerField: Pick<KcContext["messagesPerField"], "existsError" | "get"> }) {
|
||||||
i18n: I18n;
|
const { i18n, kcClsx, messagesPerField } = props;
|
||||||
getClassName: ReturnType<typeof useGetClassName>["getClassName"];
|
|
||||||
messagesPerField: Pick<KcContext["messagesPerField"], "existsError" | "get">;
|
|
||||||
}) {
|
|
||||||
const { i18n, getClassName, messagesPerField } = props;
|
|
||||||
|
|
||||||
const { msg } = i18n;
|
const { msg } = i18n;
|
||||||
|
|
||||||
@ -101,7 +76,7 @@ function TermsAcceptance(props: {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<div className={getClassName("kcInputWrapperClass")}>
|
<div className={kcClsx("kcInputWrapperClass")}>
|
||||||
{msg("termsTitle")}
|
{msg("termsTitle")}
|
||||||
<div id="kc-registration-terms-text">
|
<div id="kc-registration-terms-text">
|
||||||
<Markdown>{termsMarkdown}</Markdown>
|
<Markdown>{termsMarkdown}</Markdown>
|
||||||
@ -109,21 +84,21 @@ function TermsAcceptance(props: {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="termsAccepted"
|
id="termsAccepted"
|
||||||
name="termsAccepted"
|
name="termsAccepted"
|
||||||
className={getClassName("kcCheckboxInputClass")}
|
className={kcClsx("kcCheckboxInputClass")}
|
||||||
aria-invalid={messagesPerField.existsError("termsAccepted")}
|
aria-invalid={messagesPerField.existsError("termsAccepted")}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="termsAccepted" className={getClassName("kcLabelClass")}>
|
<label htmlFor="termsAccepted" className={kcClsx("kcLabelClass")}>
|
||||||
{msg("acceptTerms")}
|
{msg("acceptTerms")}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{messagesPerField.existsError("termsAccepted") && (
|
{messagesPerField.existsError("termsAccepted") && (
|
||||||
<div className={getClassName("kcLabelWrapperClass")}>
|
<div className={kcClsx("kcLabelWrapperClass")}>
|
||||||
<span id="input-error-terms-accepted" className={getClassName("kcInputErrorMessageClass")} aria-live="polite">
|
<span id="input-error-terms-accepted" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
{messagesPerField.get("termsAccepted")}
|
{messagesPerField.get("termsAccepted")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,7 +26,7 @@ export default function SamlPostForm(props: PageProps<Extract<KcContext, { pageI
|
|||||||
htmlFormElement.submit();
|
htmlFormElement.submit();
|
||||||
}, [htmlFormElement]);
|
}, [htmlFormElement]);
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} headerNode={msg("saml.post-form.title")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} headerNode={msg("saml.post-form.title")}>
|
||||||
<p>{msg("saml.post-form.message")}</p>
|
<p>{msg("saml.post-form.message")}</p>
|
||||||
<form name="saml-post-binding" method="post" action={samlPost.url} ref={setHtmlFormElement}>
|
<form name="saml-post-binding" method="post" action={samlPost.url} ref={setHtmlFormElement}>
|
||||||
{samlPost.SAMLRequest && <input type="hidden" name="SAMLRequest" value={samlPost.SAMLRequest} />}
|
{samlPost.SAMLRequest && <input type="hidden" name="SAMLRequest" value={samlPost.SAMLRequest} />}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -8,36 +7,37 @@ export default function SelectAuthenticator(props: PageProps<Extract<KcContext,
|
|||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
const { url, auth } = kcContext;
|
const { url, auth } = kcContext;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({ doUseDefaultCss, classes });
|
const { kcClsx } = getKcClsx({ doUseDefaultCss, classes });
|
||||||
const { msg } = useI18n({ kcContext });
|
const { msg } = useI18n({ kcContext });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} displayInfo={false} headerNode={msg("loginChooseAuthenticator")}>
|
<Template
|
||||||
<form id="kc-select-credential-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
|
kcContext={kcContext}
|
||||||
<div className={getClassName("kcSelectAuthListClass")}>
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
|
displayInfo={false}
|
||||||
|
headerNode={msg("loginChooseAuthenticator")}
|
||||||
|
>
|
||||||
|
<form id="kc-select-credential-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
|
<div className={kcClsx("kcSelectAuthListClass")}>
|
||||||
{auth.authenticationSelections.map((authenticationSelection, i) => (
|
{auth.authenticationSelections.map((authenticationSelection, i) => (
|
||||||
<button
|
<button
|
||||||
key={i}
|
key={i}
|
||||||
className={getClassName("kcSelectAuthListItemClass")}
|
className={kcClsx("kcSelectAuthListItemClass")}
|
||||||
type="submit"
|
type="submit"
|
||||||
name="authenticationExecution"
|
name="authenticationExecution"
|
||||||
value={authenticationSelection.authExecId}
|
value={authenticationSelection.authExecId}
|
||||||
>
|
>
|
||||||
<div className={getClassName("kcSelectAuthListItemIconClass")}>
|
<div className={kcClsx("kcSelectAuthListItemIconClass")}>
|
||||||
<i
|
<i className={kcClsx(authenticationSelection.iconCssClass, "kcSelectAuthListItemIconPropertyClass")} />
|
||||||
className={clsx(
|
|
||||||
getClassName(authenticationSelection.iconCssClass),
|
|
||||||
getClassName("kcSelectAuthListItemIconPropertyClass")
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcSelectAuthListItemBodyClass")}>
|
<div className={kcClsx("kcSelectAuthListItemBodyClass")}>
|
||||||
<div className={getClassName("kcSelectAuthListItemHeadingClass")}>{msg(authenticationSelection.displayName)}</div>
|
<div className={kcClsx("kcSelectAuthListItemHeadingClass")}>{msg(authenticationSelection.displayName)}</div>
|
||||||
<div className={getClassName("kcSelectAuthListItemDescriptionClass")}>{msg(authenticationSelection.helpText)}</div>
|
<div className={kcClsx("kcSelectAuthListItemDescriptionClass")}>{msg(authenticationSelection.helpText)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcSelectAuthListItemFillClass")} />
|
<div className={kcClsx("kcSelectAuthListItemFillClass")} />
|
||||||
<div className={getClassName("kcSelectAuthListItemArrowClass")}>
|
<div className={kcClsx("kcSelectAuthListItemArrowClass")}>
|
||||||
<i className={getClassName("kcSelectAuthListItemArrowIconClass")} />
|
<i className={kcClsx("kcSelectAuthListItemArrowIconClass")} />
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
|
||||||
import { Markdown } from "keycloakify/tools/Markdown";
|
import { Markdown } from "keycloakify/tools/Markdown";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useTermsMarkdown } from "keycloakify/login/lib/useDownloadTerms";
|
import { useTermsMarkdown } from "keycloakify/login/lib/useDownloadTerms";
|
||||||
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";
|
||||||
@ -9,7 +8,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function Terms(props: PageProps<Extract<KcContext, { pageId: "terms.ftl" }>>) {
|
export default function Terms(props: PageProps<Extract<KcContext, { pageId: "terms.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -25,26 +24,20 @@ export default function Terms(props: PageProps<Extract<KcContext, { pageId: "ter
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} displayMessage={false} headerNode={msg("termsTitle")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} displayMessage={false} headerNode={msg("termsTitle")}>
|
||||||
<div id="kc-terms-text" lang={termsLanguageTag !== locale?.currentLanguageTag ? termsLanguageTag : undefined}>
|
<div id="kc-terms-text" lang={termsLanguageTag !== locale?.currentLanguageTag ? termsLanguageTag : undefined}>
|
||||||
<Markdown>{termsMarkdown}</Markdown>
|
<Markdown>{termsMarkdown}</Markdown>
|
||||||
</div>
|
</div>
|
||||||
<form className="form-actions" action={url.loginAction} method="POST">
|
<form className="form-actions" action={url.loginAction} method="POST">
|
||||||
<input
|
<input
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonClass", "kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="accept"
|
name="accept"
|
||||||
id="kc-accept"
|
id="kc-accept"
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doAccept")}
|
value={msgStr("doAccept")}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
className={clsx(getClassName("kcButtonClass"), getClassName("kcButtonDefaultClass"), getClassName("kcButtonLargeClass"))}
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
|
||||||
name="cancel"
|
name="cancel"
|
||||||
id="kc-decline"
|
id="kc-decline"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
|
||||||
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import type { UserProfileFormFieldsProps } from "keycloakify/login/UserProfileFormFields";
|
import type { UserProfileFormFieldsProps } from "keycloakify/login/UserProfileFormFields";
|
||||||
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";
|
||||||
@ -14,7 +13,7 @@ type UpdateEmailProps = PageProps<Extract<KcContext, { pageId: "update-email.ftl
|
|||||||
export default function UpdateEmail(props: UpdateEmailProps) {
|
export default function UpdateEmail(props: UpdateEmailProps) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
|
const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
@ -28,47 +27,38 @@ export default function UpdateEmail(props: UpdateEmailProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
displayMessage={messagesPerField.exists("global")}
|
displayMessage={messagesPerField.exists("global")}
|
||||||
displayRequiredFields
|
displayRequiredFields
|
||||||
headerNode={msg("updateEmailTitle")}
|
headerNode={msg("updateEmailTitle")}
|
||||||
>
|
>
|
||||||
<form id="kc-update-email-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
|
<form id="kc-update-email-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
<UserProfileFormFields
|
<UserProfileFormFields kcContext={kcContext} kcClsx={kcClsx} onIsFormSubmittableValueChange={setIsFormSubmittable} />
|
||||||
{...{
|
|
||||||
kcContext,
|
|
||||||
getClassName,
|
|
||||||
messagesPerField
|
|
||||||
}}
|
|
||||||
onIsFormSubmittableValueChange={setIsFormSubmittable}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")} />
|
<div className={kcClsx("kcFormOptionsWrapperClass")} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<LogoutOtherSessions {...{ getClassName, i18n }} />
|
<LogoutOtherSessions kcClsx={kcClsx} i18n={i18n} />
|
||||||
|
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<input
|
<input
|
||||||
disabled={!isFormSubmittable}
|
disabled={!isFormSubmittable}
|
||||||
className={clsx(
|
className={kcClsx(
|
||||||
getClassName("kcButtonClass"),
|
"kcButtonClass",
|
||||||
getClassName("kcButtonPrimaryClass"),
|
"kcButtonPrimaryClass",
|
||||||
isAppInitiatedAction && getClassName("kcButtonBlockClass"),
|
isAppInitiatedAction && "kcButtonBlockClass",
|
||||||
getClassName("kcButtonLargeClass")
|
"kcButtonLargeClass"
|
||||||
)}
|
)}
|
||||||
type="submit"
|
type="submit"
|
||||||
value={msgStr("doSubmit")}
|
value={msgStr("doSubmit")}
|
||||||
/>
|
/>
|
||||||
{isAppInitiatedAction && (
|
{isAppInitiatedAction && (
|
||||||
<button
|
<button
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
type="submit"
|
type="submit"
|
||||||
name="cancel-aia"
|
name="cancel-aia"
|
||||||
value="true"
|
value="true"
|
||||||
@ -83,14 +73,14 @@ export default function UpdateEmail(props: UpdateEmailProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function LogoutOtherSessions(props: { getClassName: ReturnType<typeof useGetClassName>["getClassName"]; i18n: I18n }) {
|
function LogoutOtherSessions(props: { kcClsx: KcClsx; i18n: I18n }) {
|
||||||
const { getClassName, i18n } = props;
|
const { kcClsx, i18n } = props;
|
||||||
|
|
||||||
const { msg } = i18n;
|
const { msg } = i18n;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}>
|
||||||
<div className="checkbox">
|
<div className="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
|
<input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
|
||||||
|
@ -2,7 +2,7 @@ import { useEffect, Fragment } from "react";
|
|||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { clsx } from "keycloakify/tools/clsx";
|
||||||
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
import { getKcClsx } 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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -10,7 +10,7 @@ import { useI18n } from "../i18n";
|
|||||||
export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext, { pageId: "webauthn-authenticate.ftl" }>>) {
|
export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext, { pageId: "webauthn-authenticate.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({ doUseDefaultCss, classes });
|
const { kcClsx } = getKcClsx({ doUseDefaultCss, classes });
|
||||||
|
|
||||||
const {
|
const {
|
||||||
url,
|
url,
|
||||||
@ -136,7 +136,9 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
displayMessage={!messagesPerField.existsError("username")}
|
displayMessage={!messagesPerField.existsError("username")}
|
||||||
displayInfo={realm.password && realm.registrationAllowed && !registrationDisabled}
|
displayInfo={realm.password && realm.registrationAllowed && !registrationDisabled}
|
||||||
infoNode={
|
infoNode={
|
||||||
@ -151,7 +153,7 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
|
|||||||
}
|
}
|
||||||
headerNode={msg("webauthn-login-title")}
|
headerNode={msg("webauthn-login-title")}
|
||||||
>
|
>
|
||||||
<div id="kc-form-webauthn" className={getClassName("kcFormClass")}>
|
<div id="kc-form-webauthn" className={kcClsx("kcFormClass")}>
|
||||||
<form id="webauth" action={url.loginAction} method="post">
|
<form id="webauth" action={url.loginAction} method="post">
|
||||||
<input type="hidden" id="clientDataJSON" name="clientDataJSON" />
|
<input type="hidden" id="clientDataJSON" name="clientDataJSON" />
|
||||||
<input type="hidden" id="authenticatorData" name="authenticatorData" />
|
<input type="hidden" id="authenticatorData" name="authenticatorData" />
|
||||||
@ -160,10 +162,10 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
|
|||||||
<input type="hidden" id="userHandle" name="userHandle" />
|
<input type="hidden" id="userHandle" name="userHandle" />
|
||||||
<input type="hidden" id="error" name="error" />
|
<input type="hidden" id="error" name="error" />
|
||||||
</form>
|
</form>
|
||||||
<div className={clsx(getClassName("kcFormGroupClass"), "no-bottom-margin")}>
|
<div className={clsx(kcClsx("kcFormGroupClass"), "no-bottom-margin")}>
|
||||||
{authenticators && (
|
{authenticators && (
|
||||||
<>
|
<>
|
||||||
<form id="authn_select" className={getClassName("kcFormClass")}>
|
<form id="authn_select" className={kcClsx("kcFormClass")}>
|
||||||
{authenticators.authenticators.map(authenticator => (
|
{authenticators.authenticators.map(authenticator => (
|
||||||
<input type="hidden" name="authn_use_chk" value={authenticator.credentialId} />
|
<input type="hidden" name="authn_use_chk" value={authenticator.credentialId} />
|
||||||
))}
|
))}
|
||||||
@ -172,36 +174,33 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
|
|||||||
{shouldDisplayAuthenticators && (
|
{shouldDisplayAuthenticators && (
|
||||||
<>
|
<>
|
||||||
{authenticators.authenticators.length > 1 && (
|
{authenticators.authenticators.length > 1 && (
|
||||||
<p className={getClassName("kcSelectAuthListItemTitle")}>{msg("webauthn-available-authenticators")}</p>
|
<p className={kcClsx("kcSelectAuthListItemTitle")}>{msg("webauthn-available-authenticators")}</p>
|
||||||
)}
|
)}
|
||||||
<div className={getClassName("kcFormOptionsClass")}>
|
<div className={kcClsx("kcFormOptionsClass")}>
|
||||||
{authenticators.authenticators.map((authenticator, i) => (
|
{authenticators.authenticators.map((authenticator, i) => (
|
||||||
<div key={i} id="kc-webauthn-authenticator" className={getClassName("kcSelectAuthListItemClass")}>
|
<div key={i} id="kc-webauthn-authenticator" className={kcClsx("kcSelectAuthListItemClass")}>
|
||||||
<div className={getClassName("kcSelectAuthListItemIconClass")}>
|
<div className={kcClsx("kcSelectAuthListItemIconClass")}>
|
||||||
<i
|
<i
|
||||||
className={clsx(
|
className={clsx(
|
||||||
(() => {
|
(() => {
|
||||||
const className = getClassName(authenticator.transports.iconClass as any);
|
const className = kcClsx(authenticator.transports.iconClass as any);
|
||||||
if (className === authenticator.transports.iconClass) {
|
if (className === authenticator.transports.iconClass) {
|
||||||
return getClassName("kcWebAuthnDefaultIcon");
|
return kcClsx("kcWebAuthnDefaultIcon");
|
||||||
}
|
}
|
||||||
return className;
|
return className;
|
||||||
})(),
|
})(),
|
||||||
getClassName("kcSelectAuthListItemIconPropertyClass")
|
kcClsx("kcSelectAuthListItemIconPropertyClass")
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcSelectAuthListItemArrowIconClass")}>
|
<div className={kcClsx("kcSelectAuthListItemArrowIconClass")}>
|
||||||
<div
|
<div id="kc-webauthn-authenticator-label" className={kcClsx("kcSelectAuthListItemHeadingClass")}>
|
||||||
id="kc-webauthn-authenticator-label"
|
|
||||||
className={getClassName("kcSelectAuthListItemHeadingClass")}
|
|
||||||
>
|
|
||||||
{advancedMsg(authenticator.label)}
|
{advancedMsg(authenticator.label)}
|
||||||
</div>
|
</div>
|
||||||
{authenticator.transports.displayNameProperties?.length && (
|
{authenticator.transports.displayNameProperties?.length && (
|
||||||
<div
|
<div
|
||||||
id="kc-webauthn-authenticator-transport"
|
id="kc-webauthn-authenticator-transport"
|
||||||
className={getClassName("kcSelectAuthListItemDescriptionClass")}
|
className={kcClsx("kcSelectAuthListItemDescriptionClass")}
|
||||||
>
|
>
|
||||||
{authenticator.transports.displayNameProperties
|
{authenticator.transports.displayNameProperties
|
||||||
.map((nameProperty, i, arr) => ({
|
.map((nameProperty, i, arr) => ({
|
||||||
@ -216,11 +215,11 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={getClassName("kcSelectAuthListItemDescriptionClass")}>
|
<div className={kcClsx("kcSelectAuthListItemDescriptionClass")}>
|
||||||
<span id="kc-webauthn-authenticator-created-label">{msg("webauthn-createdAt-label")}</span>
|
<span id="kc-webauthn-authenticator-created-label">{msg("webauthn-createdAt-label")}</span>
|
||||||
<span id="kc-webauthn-authenticator-created">{authenticator.createdAt}</span>
|
<span id="kc-webauthn-authenticator-created">{authenticator.createdAt}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={getClassName("kcSelectAuthListItemFillClass")} />
|
<div className={kcClsx("kcSelectAuthListItemFillClass")} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -230,7 +229,7 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
|
<div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
|
||||||
<input
|
<input
|
||||||
id="authenticateWebAuthnButton"
|
id="authenticateWebAuthnButton"
|
||||||
type="button"
|
type="button"
|
||||||
@ -241,12 +240,7 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
|
|||||||
}}
|
}}
|
||||||
autoFocus
|
autoFocus
|
||||||
value={msgStr("webauthn-doAuthenticate")}
|
value={msgStr("webauthn-doAuthenticate")}
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
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";
|
||||||
import { useI18n } from "../i18n";
|
import { useI18n } from "../i18n";
|
||||||
@ -11,14 +10,14 @@ export default function WebauthnError(props: PageProps<Extract<KcContext, { page
|
|||||||
|
|
||||||
const { msg, msgStr } = useI18n({ kcContext });
|
const { msg, msgStr } = useI18n({ kcContext });
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { kcClsx } = getKcClsx({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, doUseDefaultCss, classes }} displayMessage headerNode={msg("webauthn-error-title")}>
|
<Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} displayMessage headerNode={msg("webauthn-error-title")}>
|
||||||
<form id="kc-error-credential-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
|
<form id="kc-error-credential-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
<input type="hidden" id="executionValue" name="authenticationExecution" />
|
<input type="hidden" id="executionValue" name="authenticationExecution" />
|
||||||
<input type="hidden" id="isSetRetry" name="isSetRetry" />
|
<input type="hidden" id="isSetRetry" name="isSetRetry" />
|
||||||
</form>
|
</form>
|
||||||
@ -33,26 +32,16 @@ export default function WebauthnError(props: PageProps<Extract<KcContext, { page
|
|||||||
document.getElementById("kc-error-credential-form").submit();
|
document.getElementById("kc-error-credential-form").submit();
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
name="try-again"
|
name="try-again"
|
||||||
id="kc-try-again"
|
id="kc-try-again"
|
||||||
value={msgStr("doTryAgain")}
|
value={msgStr("doTryAgain")}
|
||||||
/>
|
/>
|
||||||
{isAppInitiatedAction && (
|
{isAppInitiatedAction && (
|
||||||
<form action={url.loginAction} className={getClassName("kcFormClass")} id="kc-webauthn-settings-form" method="post">
|
<form action={url.loginAction} className={kcClsx("kcFormClass")} id="kc-webauthn-settings-form" method="post">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
id="cancelWebAuthnAIA"
|
id="cancelWebAuthnAIA"
|
||||||
name="cancel-aia"
|
name="cancel-aia"
|
||||||
value="true"
|
value="true"
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import { clsx } from "keycloakify/tools/clsx";
|
import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
|
||||||
import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
|
|
||||||
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
|
||||||
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";
|
||||||
@ -10,7 +9,7 @@ import { useI18n, type I18n } from "../i18n";
|
|||||||
export default function WebauthnRegister(props: PageProps<Extract<KcContext, { pageId: "webauthn-register.ftl" }>>) {
|
export default function WebauthnRegister(props: PageProps<Extract<KcContext, { pageId: "webauthn-register.ftl" }>>) {
|
||||||
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({ doUseDefaultCss, classes });
|
const { kcClsx } = getKcClsx({ doUseDefaultCss, classes });
|
||||||
|
|
||||||
const {
|
const {
|
||||||
url,
|
url,
|
||||||
@ -207,33 +206,30 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Template
|
<Template
|
||||||
{...{ kcContext, doUseDefaultCss, classes }}
|
kcContext={kcContext}
|
||||||
|
doUseDefaultCss={doUseDefaultCss}
|
||||||
|
classes={classes}
|
||||||
headerNode={
|
headerNode={
|
||||||
<>
|
<>
|
||||||
<span className={getClassName("kcWebAuthnKeyIcon")} />
|
<span className={kcClsx("kcWebAuthnKeyIcon")} />
|
||||||
{msg("webauthn-registration-title")}
|
{msg("webauthn-registration-title")}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<form id="register" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
|
<form id="register" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
|
||||||
<div className={getClassName("kcFormGroupClass")}>
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
<input type="hidden" id="clientDataJSON" name="clientDataJSON" />
|
<input type="hidden" id="clientDataJSON" name="clientDataJSON" />
|
||||||
<input type="hidden" id="attestationObject" name="attestationObject" />
|
<input type="hidden" id="attestationObject" name="attestationObject" />
|
||||||
<input type="hidden" id="publicKeyCredentialId" name="publicKeyCredentialId" />
|
<input type="hidden" id="publicKeyCredentialId" name="publicKeyCredentialId" />
|
||||||
<input type="hidden" id="authenticatorLabel" name="authenticatorLabel" />
|
<input type="hidden" id="authenticatorLabel" name="authenticatorLabel" />
|
||||||
<input type="hidden" id="transports" name="transports" />
|
<input type="hidden" id="transports" name="transports" />
|
||||||
<input type="hidden" id="error" name="error" />
|
<input type="hidden" id="error" name="error" />
|
||||||
<LogoutOtherSessions {...{ i18n, getClassName }} />
|
<LogoutOtherSessions kcClsx={kcClsx} i18n={i18n} />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonPrimaryClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
id="registerWebAuthn"
|
id="registerWebAuthn"
|
||||||
value={msgStr("doRegisterSecurityKey")}
|
value={msgStr("doRegisterSecurityKey")}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -244,15 +240,10 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{!isSetRetry && isAppInitiatedAction && (
|
{!isSetRetry && isAppInitiatedAction && (
|
||||||
<form action={url.loginAction} className={getClassName("kcFormClass")} id="kc-webauthn-settings-form" method="post">
|
<form action={url.loginAction} className={kcClsx("kcFormClass")} id="kc-webauthn-settings-form" method="post">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className={clsx(
|
className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
getClassName("kcButtonClass"),
|
|
||||||
getClassName("kcButtonDefaultClass"),
|
|
||||||
getClassName("kcButtonBlockClass"),
|
|
||||||
getClassName("kcButtonLargeClass")
|
|
||||||
)}
|
|
||||||
id="cancelWebAuthnAIA"
|
id="cancelWebAuthnAIA"
|
||||||
name="cancel-aia"
|
name="cancel-aia"
|
||||||
value="true"
|
value="true"
|
||||||
@ -265,14 +256,14 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function LogoutOtherSessions(props: { i18n: I18n; getClassName: ReturnType<typeof useGetClassName>["getClassName"] }) {
|
function LogoutOtherSessions(props: { kcClsx: KcClsx; i18n: I18n }) {
|
||||||
const { getClassName, i18n } = props;
|
const { kcClsx, i18n } = props;
|
||||||
|
|
||||||
const { msg } = i18n;
|
const { msg } = i18n;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
|
<div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
|
||||||
<div className={getClassName("kcFormOptionsWrapperClass")}>
|
<div className={kcClsx("kcFormOptionsWrapperClass")}>
|
||||||
<div className="checkbox">
|
<div className="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
|
<input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
|
||||||
|
@ -1,50 +1,8 @@
|
|||||||
import { assert } from "tsafe/assert";
|
import { id } from "tsafe";
|
||||||
import { typeGuard } from "tsafe/typeGuard";
|
import { clsx_withTransform, type CxArg as CxArg_generic } from "./clsx_withTransform";
|
||||||
|
|
||||||
export type CxArg =
|
export type CxArg = CxArg_generic<string>;
|
||||||
| undefined
|
|
||||||
| null
|
|
||||||
| string
|
|
||||||
| boolean
|
|
||||||
| Partial<Record<string, boolean | null | undefined>>
|
|
||||||
| readonly CxArg[];
|
|
||||||
|
|
||||||
export const clsx = (...args: CxArg[]): string => {
|
export function clsx(...args: CxArg[]): string {
|
||||||
const len = args.length;
|
return clsx_withTransform({ args, transform: id });
|
||||||
let i = 0;
|
}
|
||||||
let cls = "";
|
|
||||||
for (; i < len; i++) {
|
|
||||||
const arg = args[i];
|
|
||||||
if (arg == null) continue;
|
|
||||||
|
|
||||||
let toAdd;
|
|
||||||
switch (typeof arg) {
|
|
||||||
case "boolean":
|
|
||||||
break;
|
|
||||||
case "object": {
|
|
||||||
if (Array.isArray(arg)) {
|
|
||||||
toAdd = clsx(...arg);
|
|
||||||
} else {
|
|
||||||
assert(!typeGuard<{ length: number }>(arg, false));
|
|
||||||
|
|
||||||
toAdd = "";
|
|
||||||
for (const k in arg) {
|
|
||||||
if (arg[k as string] && k) {
|
|
||||||
toAdd && (toAdd += " ");
|
|
||||||
toAdd += k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
toAdd = arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (toAdd) {
|
|
||||||
cls && (cls += " ");
|
|
||||||
cls += toAdd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cls;
|
|
||||||
};
|
|
||||||
|
55
src/tools/clsx_withTransform.ts
Normal file
55
src/tools/clsx_withTransform.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { assert } from "tsafe/assert";
|
||||||
|
import { typeGuard } from "tsafe/typeGuard";
|
||||||
|
|
||||||
|
export type CxArg<ClassName extends string = string> =
|
||||||
|
| undefined
|
||||||
|
| null
|
||||||
|
| ClassName
|
||||||
|
| boolean
|
||||||
|
| Partial<Record<ClassName, boolean | null | undefined>>
|
||||||
|
| readonly CxArg<ClassName>[];
|
||||||
|
|
||||||
|
export function clsx_withTransform(params: {
|
||||||
|
args: CxArg[];
|
||||||
|
transform: (arg: string) => string;
|
||||||
|
}): string {
|
||||||
|
const { args, transform } = params;
|
||||||
|
|
||||||
|
const len = args.length;
|
||||||
|
let i = 0;
|
||||||
|
let cls = "";
|
||||||
|
for (; i < len; i++) {
|
||||||
|
const arg = args[i];
|
||||||
|
if (arg == null) continue;
|
||||||
|
|
||||||
|
let toAdd;
|
||||||
|
switch (typeof arg) {
|
||||||
|
case "boolean":
|
||||||
|
break;
|
||||||
|
case "object": {
|
||||||
|
if (Array.isArray(arg)) {
|
||||||
|
toAdd = clsx_withTransform({ args: arg, transform });
|
||||||
|
} else {
|
||||||
|
assert(!typeGuard<{ length: number }>(arg, false));
|
||||||
|
|
||||||
|
toAdd = "";
|
||||||
|
for (const k in arg) {
|
||||||
|
if (arg[k] && k) {
|
||||||
|
toAdd && (toAdd += " ");
|
||||||
|
toAdd += transform(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
toAdd = transform(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (toAdd) {
|
||||||
|
cls && (cls += " ");
|
||||||
|
cls += toAdd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cls;
|
||||||
|
}
|
@ -1,17 +1,10 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Fallback from "../../dist/account/Fallback";
|
import Fallback from "../../dist/account/Fallback";
|
||||||
import type { KcContext } from "./KcContext";
|
import type { KcContext } from "./KcContext";
|
||||||
import { useI18n } from "./i18n";
|
|
||||||
import Template from "../../dist/account/Template";
|
import Template from "../../dist/account/Template";
|
||||||
|
|
||||||
export default function KcApp(props: { kcContext: KcContext }) {
|
export default function KcApp(props: { kcContext: KcContext }) {
|
||||||
const { kcContext } = props;
|
const { kcContext } = props;
|
||||||
|
|
||||||
const i18n = useI18n({ kcContext });
|
return <Fallback kcContext={kcContext} Template={Template} doUseDefaultCss={true} />;
|
||||||
|
|
||||||
if (i18n === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Fallback {...{ kcContext, i18n }} Template={Template} doUseDefaultCss={true} />;
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import type { ExtendKcContext } from "../../dist/account";
|
import type { ExtendKcContext } from "../../dist/account";
|
||||||
|
import type { KcEnvName, ThemeName } from "../kc.gen";
|
||||||
|
|
||||||
export type KcContextExtraProperties = {};
|
export type KcContextExtension = {
|
||||||
|
themeName: ThemeName;
|
||||||
|
properties: Record<KcEnvName, string> & {};
|
||||||
|
};
|
||||||
|
|
||||||
export type KcContextExtraPropertiesPerPage = {};
|
export type KcContextExtensionPerPage = {};
|
||||||
|
|
||||||
export type KcContext = ExtendKcContext<
|
export type KcContext = ExtendKcContext<KcContextExtension, KcContextExtensionPerPage>;
|
||||||
KcContextExtraProperties,
|
|
||||||
KcContextExtraPropertiesPerPage
|
|
||||||
>;
|
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import type { KcContext } from "./KcContext";
|
|
||||||
import KcApp from "./KcApp";
|
|
||||||
import type { DeepPartial } from "../../dist/tools/DeepPartial";
|
import type { DeepPartial } from "../../dist/tools/DeepPartial";
|
||||||
|
import type { KcContext } from "./KcContext";
|
||||||
import { createGetKcContextMock } from "../../dist/account/KcContext";
|
import { createGetKcContextMock } from "../../dist/account/KcContext";
|
||||||
import type { KcContextExtraProperties, KcContextExtraPropertiesPerPage } from "./KcContext";
|
import type { KcContextExtension, KcContextExtensionPerPage } from "./KcContext";
|
||||||
|
import KcApp from "./KcApp";
|
||||||
|
import { themeNames, kcEnvDefaults } from "../kc.gen";
|
||||||
|
|
||||||
const kcContextExtraProperties: KcContextExtraProperties = {};
|
const kcContextExtension: KcContextExtension = {
|
||||||
const kcContextExtraPropertiesPerPage: KcContextExtraPropertiesPerPage = {};
|
themeName: themeNames[0],
|
||||||
|
properties: {
|
||||||
|
...kcEnvDefaults
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const kcContextExtensionPerPage: KcContextExtensionPerPage = {};
|
||||||
|
|
||||||
export const { getKcContextMock } = createGetKcContextMock({
|
export const { getKcContextMock } = createGetKcContextMock({
|
||||||
kcContextExtraProperties,
|
kcContextExtension,
|
||||||
kcContextExtraPropertiesPerPage
|
kcContextExtensionPerPage,
|
||||||
|
overrides: {},
|
||||||
|
overridesPerPage: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
export function createPageStory<PageId extends KcContext["pageId"]>(params: { pageId: PageId }) {
|
export function createPageStory<PageId extends KcContext["pageId"]>(params: { pageId: PageId }) {
|
||||||
|
7
stories/kc.gen.ts
Normal file
7
stories/kc.gen.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export const themeNames = ["keycloakify"] as const;
|
||||||
|
|
||||||
|
export type ThemeName = (typeof themeNames)[number];
|
||||||
|
|
||||||
|
export type KcEnvName = never;
|
||||||
|
|
||||||
|
export const kcEnvDefaults: Record<KcEnvName, string> = {};
|
@ -1,7 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Fallback from "../../dist/login/Fallback";
|
import Fallback from "../../dist/login/Fallback";
|
||||||
import type { KcContext } from "./KcContext";
|
import type { KcContext } from "./KcContext";
|
||||||
import { useI18n } from "./i18n";
|
|
||||||
import { useDownloadTerms } from "../../dist/login/lib/useDownloadTerms";
|
import { useDownloadTerms } from "../../dist/login/lib/useDownloadTerms";
|
||||||
import Template from "../../dist/login/Template";
|
import Template from "../../dist/login/Template";
|
||||||
import UserProfileFormFields from "../../dist/login/UserProfileFormFields";
|
import UserProfileFormFields from "../../dist/login/UserProfileFormFields";
|
||||||
@ -9,8 +8,6 @@ import UserProfileFormFields from "../../dist/login/UserProfileFormFields";
|
|||||||
export default function KcApp(props: { kcContext: KcContext }) {
|
export default function KcApp(props: { kcContext: KcContext }) {
|
||||||
const { kcContext } = props;
|
const { kcContext } = props;
|
||||||
|
|
||||||
const i18n = useI18n({ kcContext });
|
|
||||||
|
|
||||||
useDownloadTerms({
|
useDownloadTerms({
|
||||||
kcContext,
|
kcContext,
|
||||||
downloadTermsMarkdown: async ({ currentLanguageTag }) => {
|
downloadTermsMarkdown: async ({ currentLanguageTag }) => {
|
||||||
@ -36,19 +33,5 @@ export default function KcApp(props: { kcContext: KcContext }) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (i18n === null) {
|
return <Fallback kcContext={kcContext} Template={Template} UserProfileFormFields={UserProfileFormFields} doUseDefaultCss={true} />;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Fallback
|
|
||||||
{...{
|
|
||||||
kcContext,
|
|
||||||
i18n,
|
|
||||||
Template,
|
|
||||||
UserProfileFormFields
|
|
||||||
}}
|
|
||||||
doUseDefaultCss={true}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import type { ExtendKcContext } from "../../dist/login";
|
import type { ExtendKcContext } from "../../dist/login";
|
||||||
|
import type { KcEnvName, ThemeName } from "../kc.gen";
|
||||||
|
|
||||||
export type KcContextExtraProperties = {};
|
export type KcContextExtension = {
|
||||||
|
themeName: ThemeName;
|
||||||
|
properties: Record<KcEnvName, string> & {};
|
||||||
|
};
|
||||||
|
|
||||||
export type KcContextExtraPropertiesPerPage = {};
|
export type KcContextExtensionPerPage = {};
|
||||||
|
|
||||||
export type KcContext = ExtendKcContext<
|
export type KcContext = ExtendKcContext<KcContextExtension, KcContextExtensionPerPage>;
|
||||||
KcContextExtraProperties,
|
|
||||||
KcContextExtraPropertiesPerPage
|
|
||||||
>;
|
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import type { KcContext } from "./KcContext";
|
|
||||||
import KcApp from "./KcApp";
|
|
||||||
import type { DeepPartial } from "../../dist/tools/DeepPartial";
|
import type { DeepPartial } from "../../dist/tools/DeepPartial";
|
||||||
|
import type { KcContext } from "./KcContext";
|
||||||
import { createGetKcContextMock } from "../../dist/login/KcContext";
|
import { createGetKcContextMock } from "../../dist/login/KcContext";
|
||||||
import type { KcContextExtraProperties, KcContextExtraPropertiesPerPage } from "./KcContext";
|
import type { KcContextExtension, KcContextExtensionPerPage } from "./KcContext";
|
||||||
|
import KcApp from "./KcApp";
|
||||||
|
import { themeNames, kcEnvDefaults } from "../kc.gen";
|
||||||
|
|
||||||
const kcContextExtraProperties: KcContextExtraProperties = {};
|
const kcContextExtension: KcContextExtension = {
|
||||||
const kcContextExtraPropertiesPerPage: KcContextExtraPropertiesPerPage = {};
|
themeName: themeNames[0],
|
||||||
|
properties: {
|
||||||
|
...kcEnvDefaults
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const kcContextExtensionPerPage: KcContextExtensionPerPage = {};
|
||||||
|
|
||||||
const { getKcContextMock } = createGetKcContextMock({
|
export const { getKcContextMock } = createGetKcContextMock({
|
||||||
kcContextExtraProperties,
|
kcContextExtension,
|
||||||
kcContextExtraPropertiesPerPage
|
kcContextExtensionPerPage,
|
||||||
|
overrides: {},
|
||||||
|
overridesPerPage: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
export function createPageStory<PageId extends KcContext["pageId"]>(params: { pageId: PageId }) {
|
export function createPageStory<PageId extends KcContext["pageId"]>(params: { pageId: PageId }) {
|
||||||
|
@ -5,13 +5,13 @@ import { assert, type Equals } from "tsafe/assert";
|
|||||||
import { Reflect } from "tsafe/Reflect";
|
import { Reflect } from "tsafe/Reflect";
|
||||||
|
|
||||||
{
|
{
|
||||||
type KcContextExtraProperties = {
|
type KcContextExtension = {
|
||||||
properties: {
|
properties: {
|
||||||
myCustomProperty: string | undefined;
|
myCustomProperty: string | undefined;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type KcContextExtraPropertiesPerPage = {
|
type KcContextExtensionPerPage = {
|
||||||
"login.ftl": {
|
"login.ftl": {
|
||||||
foo: string;
|
foo: string;
|
||||||
};
|
};
|
||||||
@ -20,10 +20,7 @@ import { Reflect } from "tsafe/Reflect";
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type KcContext = ExtendKcContext<
|
type KcContext = ExtendKcContext<KcContextExtension, KcContextExtensionPerPage>;
|
||||||
KcContextExtraProperties,
|
|
||||||
KcContextExtraPropertiesPerPage
|
|
||||||
>;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
type Got = Extract<KcContext, { pageId: "login.ftl" }>;
|
type Got = Extract<KcContext, { pageId: "login.ftl" }>;
|
||||||
@ -47,7 +44,7 @@ import { Reflect } from "tsafe/Reflect";
|
|||||||
type Got = Extract<KcContext, { pageId: "my-custom-page.ftl" }>;
|
type Got = Extract<KcContext, { pageId: "my-custom-page.ftl" }>;
|
||||||
|
|
||||||
type Expected = KcContextBase.Common &
|
type Expected = KcContextBase.Common &
|
||||||
KcContextExtraProperties & { pageId: "my-custom-page.ftl" } & {
|
KcContextExtension & { pageId: "my-custom-page.ftl" } & {
|
||||||
properties: { myCustomProperty: string | undefined };
|
properties: { myCustomProperty: string | undefined };
|
||||||
} & { bar: number };
|
} & { bar: number };
|
||||||
|
|
||||||
@ -56,8 +53,8 @@ import { Reflect } from "tsafe/Reflect";
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { getKcContextMock } = createGetKcContextMock({
|
const { getKcContextMock } = createGetKcContextMock({
|
||||||
kcContextExtraProperties: Reflect<KcContextExtraProperties>(),
|
kcContextExtension: Reflect<KcContextExtension>(),
|
||||||
kcContextExtraPropertiesPerPage: Reflect<KcContextExtraPropertiesPerPage>()
|
kcContextExtensionPerPage: Reflect<KcContextExtensionPerPage>()
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -104,8 +101,8 @@ import { Reflect } from "tsafe/Reflect";
|
|||||||
});
|
});
|
||||||
|
|
||||||
createGetKcContextMock({
|
createGetKcContextMock({
|
||||||
kcContextExtraProperties: Reflect<KcContextExtraProperties>(),
|
kcContextExtension: Reflect<KcContextExtension>(),
|
||||||
kcContextExtraPropertiesPerPage: Reflect<KcContextExtraPropertiesPerPage>(),
|
kcContextExtensionPerPage: Reflect<KcContextExtensionPerPage>(),
|
||||||
overrides: {
|
overrides: {
|
||||||
locale: {
|
locale: {
|
||||||
currentLanguageTag: "fr"
|
currentLanguageTag: "fr"
|
||||||
@ -137,8 +134,8 @@ import { Reflect } from "tsafe/Reflect";
|
|||||||
});
|
});
|
||||||
|
|
||||||
createGetKcContextMock({
|
createGetKcContextMock({
|
||||||
kcContextExtraProperties: Reflect<KcContextExtraProperties>(),
|
kcContextExtension: Reflect<KcContextExtension>(),
|
||||||
kcContextExtraPropertiesPerPage: Reflect<KcContextExtraPropertiesPerPage>(),
|
kcContextExtensionPerPage: Reflect<KcContextExtensionPerPage>(),
|
||||||
overridesPerPage: {
|
overridesPerPage: {
|
||||||
"register.ftl": {
|
"register.ftl": {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@ -149,14 +146,11 @@ import { Reflect } from "tsafe/Reflect";
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
type KcContextExtraProperties = {};
|
type KcContextExtension = {};
|
||||||
|
|
||||||
type KcContextExtraPropertiesPerPage = {};
|
type KcContextExtensionPerPage = {};
|
||||||
|
|
||||||
type KcContext = ExtendKcContext<
|
type KcContext = ExtendKcContext<KcContextExtension, KcContextExtensionPerPage>;
|
||||||
KcContextExtraProperties,
|
|
||||||
KcContextExtraPropertiesPerPage
|
|
||||||
>;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
type Got = Extract<KcContext, { pageId: "login.ftl" }>;
|
type Got = Extract<KcContext, { pageId: "login.ftl" }>;
|
||||||
@ -173,8 +167,8 @@ import { Reflect } from "tsafe/Reflect";
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { getKcContextMock } = createGetKcContextMock({
|
const { getKcContextMock } = createGetKcContextMock({
|
||||||
kcContextExtraProperties: Reflect<KcContextExtraProperties>(),
|
kcContextExtension: Reflect<KcContextExtension>(),
|
||||||
kcContextExtraPropertiesPerPage: Reflect<KcContextExtraPropertiesPerPage>()
|
kcContextExtensionPerPage: Reflect<KcContextExtensionPerPage>()
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -9,13 +9,13 @@ import { structuredCloneButFunctions } from "keycloakify/tools/structuredCloneBu
|
|||||||
import { expect, it, describe } from "vitest";
|
import { expect, it, describe } from "vitest";
|
||||||
|
|
||||||
describe("createGetKcContextMock", () => {
|
describe("createGetKcContextMock", () => {
|
||||||
type KcContextExtraProperties = {
|
type KcContextExtension = {
|
||||||
properties: {
|
properties: {
|
||||||
MY_ENV_VAR?: string;
|
MY_ENV_VAR?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type KcContextExtraPropertiesPerPage = {
|
type KcContextExtensionPerPage = {
|
||||||
"register.ftl": {
|
"register.ftl": {
|
||||||
authorizedMailDomains: string[];
|
authorizedMailDomains: string[];
|
||||||
};
|
};
|
||||||
@ -25,12 +25,12 @@ describe("createGetKcContextMock", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { getKcContextMock } = createGetKcContextMock({
|
const { getKcContextMock } = createGetKcContextMock({
|
||||||
kcContextExtraProperties: id<KcContextExtraProperties>({
|
kcContextExtension: id<KcContextExtension>({
|
||||||
properties: {
|
properties: {
|
||||||
MY_ENV_VAR: "my env var value"
|
MY_ENV_VAR: "my env var value"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
kcContextExtraPropertiesPerPage: id<KcContextExtraPropertiesPerPage>({
|
kcContextExtensionPerPage: id<KcContextExtensionPerPage>({
|
||||||
"register.ftl": {
|
"register.ftl": {
|
||||||
authorizedMailDomains: ["gmail.com", "hotmail.com"]
|
authorizedMailDomains: ["gmail.com", "hotmail.com"]
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user