diff --git a/src/KcApp.tsx b/src/Fallback.tsx similarity index 52% rename from src/KcApp.tsx rename to src/Fallback.tsx index 9c04548d..9b640d55 100644 --- a/src/KcApp.tsx +++ b/src/Fallback.tsx @@ -1,11 +1,7 @@ import { lazy, Suspense } from "react"; -import { __unsafe_useI18n as useI18n } from "./i18n"; -import type { KcContext } from "./kcContext/KcContext"; +import type { KcContext } from "keycloakify/kcContext"; import type { PageProps } from "keycloakify/pages/PageProps"; -import type { I18nBase } from "./i18n"; -import type { SetOptional } from "./tools/SetOptional"; - -const DefaultTemplate = lazy(() => import("keycloakify/Template")); +import type { I18n } from "keycloakify/i18n"; const Login = lazy(() => import("keycloakify/pages/Login")); const Register = lazy(() => import("keycloakify/pages/Register")); @@ -29,71 +25,55 @@ const LogoutConfirm = lazy(() => import("keycloakify/pages/LogoutConfirm")); const UpdateUserProfile = lazy(() => import("keycloakify/pages/UpdateUserProfile")); const IdpReviewUserProfile = lazy(() => import("keycloakify/pages/IdpReviewUserProfile")); -export default function KcApp(props_: SetOptional, "Template">) { - const { kcContext, i18n: userProvidedI18n, Template = DefaultTemplate, ...kcProps } = props_; - - const i18n = (function useClosure() { - const i18n = useI18n({ - kcContext, - "extraMessages": {}, - "doSkip": userProvidedI18n !== undefined - }); - - return userProvidedI18n ?? i18n; - })(); - - if (i18n === null) { - return null; - } - - const commonProps = { i18n, Template, ...kcProps }; +export default function Fallback(props: PageProps) { + const { kcContext, ...rest } = props; return ( {(() => { switch (kcContext.pageId) { case "login.ftl": - return ; + return ; case "register.ftl": - return ; + return ; case "register-user-profile.ftl": - return ; + return ; case "info.ftl": - return ; + return ; case "error.ftl": - return ; + return ; case "login-reset-password.ftl": - return ; + return ; case "login-verify-email.ftl": - return ; + return ; case "terms.ftl": - return ; + return ; case "login-otp.ftl": - return ; + return ; case "login-username.ftl": - return ; + return ; case "login-password.ftl": - return ; + return ; case "webauthn-authenticate.ftl": - return ; + return ; case "login-update-password.ftl": - return ; + return ; case "login-update-profile.ftl": - return ; + return ; case "login-idp-link-confirm.ftl": - return ; + return ; case "login-idp-link-email.ftl": - return ; + return ; case "login-page-expired.ftl": - return ; + return ; case "login-config-totp.ftl": - return ; + return ; case "logout-confirm.ftl": - return ; + return ; case "update-user-profile.ftl": - return ; + return ; case "idp-review-user-profile.ftl": - return ; + return ; } })()} diff --git a/src/Template.tsx b/src/Template.tsx index 8ca049ac..c05dbdb1 100644 --- a/src/Template.tsx +++ b/src/Template.tsx @@ -4,7 +4,7 @@ import { usePrepareTemplate } from "keycloakify/lib/usePrepareTemplate"; import { type TemplateProps, defaultTemplateClasses } from "keycloakify/TemplateProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; type KcContext = import("./kcContext/KcContext").KcContext.Common; -import type { I18nBase as I18n } from "./i18n"; +import type { I18n } from "./i18n"; export default function Template(props: TemplateProps) { const { diff --git a/src/TemplateProps.ts b/src/TemplateProps.ts index 0ce86ccc..63ddfc4f 100644 --- a/src/TemplateProps.ts +++ b/src/TemplateProps.ts @@ -1,10 +1,10 @@ import type { ReactNode } from "react"; import type { KcContext } from "keycloakify/kcContext"; -import type { I18nBase } from "keycloakify/i18n"; +import type { I18n } from "keycloakify/i18n"; -export type TemplateProps = { +export type TemplateProps = { kcContext: KcContext; - i18n: I18n; + i18n: I18nExtended; doUseDefaultCss: boolean; classes?: Partial>; diff --git a/src/i18n/i18n.tsx b/src/i18n/i18n.tsx index 19ecd29c..62973d2b 100644 --- a/src/i18n/i18n.tsx +++ b/src/i18n/i18n.tsx @@ -19,7 +19,7 @@ assert(); export type MessageKeyBase = keyof typeof baseMessages | keyof (typeof keycloakifyExtraMessages)[typeof fallbackLanguageTag]; -export type I18n = { +export type GenericI18n = { /** * e.g: "en", "fr", "zh-CN" * @@ -67,21 +67,20 @@ export type I18n = { advancedMsgStr: (key: string, ...args: (string | undefined)[]) => string; }; -export type I18nBase = I18n; +export type I18n = GenericI18n; -export function __unsafe_useI18n(params: { +export function useI18n(params: { kcContext: KcContextLike; extraMessages: { [languageTag: string]: { [key in ExtraMessageKey]: string } }; - doSkip: boolean; -}): I18n | null { - const { kcContext, extraMessages, doSkip } = params; +}): GenericI18n | null { + const { kcContext, extraMessages } = params; - const [i18n, setI18n] = useState | undefined>(undefined); + const [i18n, setI18n] = useState | undefined>(undefined); const refHasStartedFetching = useRef(false); useEffect(() => { - if (doSkip || refHasStartedFetching.current) { + if (refHasStartedFetching.current) { return; } @@ -181,22 +180,10 @@ export function __unsafe_useI18n(params: return i18n ?? null; } -const useI18n_private = __unsafe_useI18n; - -export function useI18n(params: { - kcContext: KcContextLike; - extraMessages: { [languageTag: string]: { [key in ExtraMessageKey]: string } }; -}): I18n | null { - return useI18n_private({ - ...params, - "doSkip": false - }); -} - function createI18nTranslationFunctions(params: { fallbackMessages: Record; messages: Record; -}): Pick, "msg" | "msgStr" | "advancedMsg" | "advancedMsgStr"> { +}): Pick, "msg" | "msgStr" | "advancedMsg" | "advancedMsgStr"> { const { fallbackMessages, messages } = params; function resolveMsg(props: { key: string; args: (string | undefined)[]; doRenderMarkdown: boolean }): string | JSX.Element | undefined { diff --git a/src/index.ts b/src/index.ts index e238fd2c..94f0094b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ -import KcApp from "./KcApp"; +import Fallback from "./Fallback"; -export default KcApp; +export default Fallback; diff --git a/src/lib/useFormValidation.tsx b/src/lib/useFormValidation.tsx index a84bb2f9..05dfa8f3 100644 --- a/src/lib/useFormValidation.tsx +++ b/src/lib/useFormValidation.tsx @@ -6,7 +6,7 @@ import type { Attribute, Validators } from "keycloakify/kcContext"; import { useConstCallback } from "keycloakify/tools/useConstCallback"; import { emailRegexp } from "keycloakify/tools/emailRegExp"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; /** * NOTE: The attributesWithPassword returned is actually augmented with diff --git a/src/pages/Error.tsx b/src/pages/Error.tsx index 090789f1..85b8ea81 100644 --- a/src/pages/Error.tsx +++ b/src/pages/Error.tsx @@ -1,6 +1,6 @@ import { type PageProps } from "keycloakify/pages/PageProps"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function Error(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/IdpReviewUserProfile.tsx b/src/pages/IdpReviewUserProfile.tsx index 3220c4e9..a69792b6 100644 --- a/src/pages/IdpReviewUserProfile.tsx +++ b/src/pages/IdpReviewUserProfile.tsx @@ -4,7 +4,7 @@ import { UserProfileFormFields } from "./shared/UserProfileCommons"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function IdpReviewUserProfile(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/Info.tsx b/src/pages/Info.tsx index d3cfbf1d..aaee4498 100644 --- a/src/pages/Info.tsx +++ b/src/pages/Info.tsx @@ -1,7 +1,7 @@ import { assert } from "../tools/assert"; import { type PageProps } from "keycloakify/pages/PageProps"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function Info(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index f372aab1..c5edd7e9 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -4,7 +4,7 @@ import { useConstCallback } from "../tools/useConstCallback"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function Login(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LoginConfigTotp.tsx b/src/pages/LoginConfigTotp.tsx index 33199959..f6e7a615 100644 --- a/src/pages/LoginConfigTotp.tsx +++ b/src/pages/LoginConfigTotp.tsx @@ -2,7 +2,7 @@ import { clsx } from "keycloakify/tools/clsx"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function LoginConfigTotp(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LoginIdpLinkConfirm.tsx b/src/pages/LoginIdpLinkConfirm.tsx index 288c1f75..c07a2fe4 100644 --- a/src/pages/LoginIdpLinkConfirm.tsx +++ b/src/pages/LoginIdpLinkConfirm.tsx @@ -2,7 +2,7 @@ import { clsx } from "keycloakify/tools/clsx"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function LoginIdpLinkConfirm(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LoginIdpLinkEmail.tsx b/src/pages/LoginIdpLinkEmail.tsx index 07342081..fa2f6bfb 100644 --- a/src/pages/LoginIdpLinkEmail.tsx +++ b/src/pages/LoginIdpLinkEmail.tsx @@ -1,6 +1,6 @@ import type { KcContext } from "keycloakify/kcContext"; import { type PageProps } from "keycloakify/pages/PageProps"; -import type { I18nBase as I18n } from "keycloakify/i18n"; +import type { I18n } from "keycloakify/i18n"; export default function LoginIdpLinkEmail(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LoginOtp.tsx b/src/pages/LoginOtp.tsx index 55250e25..513fffce 100644 --- a/src/pages/LoginOtp.tsx +++ b/src/pages/LoginOtp.tsx @@ -5,7 +5,7 @@ import { clsx } from "keycloakify/tools/clsx"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function LoginOtp(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LoginPageExpired.tsx b/src/pages/LoginPageExpired.tsx index 7fe89fe0..1b08d082 100644 --- a/src/pages/LoginPageExpired.tsx +++ b/src/pages/LoginPageExpired.tsx @@ -1,6 +1,6 @@ import { type PageProps } from "keycloakify/pages/PageProps"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function LoginPageExpired(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LoginPassword.tsx b/src/pages/LoginPassword.tsx index a18000cc..0c66b3fc 100644 --- a/src/pages/LoginPassword.tsx +++ b/src/pages/LoginPassword.tsx @@ -5,7 +5,7 @@ import type { FormEventHandler } from "react"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function LoginPassword(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LoginResetPassword.tsx b/src/pages/LoginResetPassword.tsx index 0507690b..25e879b4 100644 --- a/src/pages/LoginResetPassword.tsx +++ b/src/pages/LoginResetPassword.tsx @@ -2,7 +2,7 @@ import { clsx } from "keycloakify/tools/clsx"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function LoginResetPassword(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LoginUpdatePassword.tsx b/src/pages/LoginUpdatePassword.tsx index c62affb6..71a29942 100644 --- a/src/pages/LoginUpdatePassword.tsx +++ b/src/pages/LoginUpdatePassword.tsx @@ -2,7 +2,7 @@ import { clsx } from "keycloakify/tools/clsx"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function LoginUpdatePassword(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LoginUpdateProfile.tsx b/src/pages/LoginUpdateProfile.tsx index 193719d7..63bdbdaa 100644 --- a/src/pages/LoginUpdateProfile.tsx +++ b/src/pages/LoginUpdateProfile.tsx @@ -2,7 +2,7 @@ import { clsx } from "keycloakify/tools/clsx"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function LoginUpdateProfile(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LoginUsername.tsx b/src/pages/LoginUsername.tsx index 2e87715a..01365137 100644 --- a/src/pages/LoginUsername.tsx +++ b/src/pages/LoginUsername.tsx @@ -5,7 +5,7 @@ import type { FormEventHandler } from "react"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function LoginUsername(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LoginVerifyEmail.tsx b/src/pages/LoginVerifyEmail.tsx index d16af376..317b873a 100644 --- a/src/pages/LoginVerifyEmail.tsx +++ b/src/pages/LoginVerifyEmail.tsx @@ -1,6 +1,6 @@ import { type PageProps } from "keycloakify/pages/PageProps"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function LoginVerifyEmail(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/LogoutConfirm.tsx b/src/pages/LogoutConfirm.tsx index 463717c4..2a91d3ab 100644 --- a/src/pages/LogoutConfirm.tsx +++ b/src/pages/LogoutConfirm.tsx @@ -2,7 +2,7 @@ import { clsx } from "keycloakify/tools/clsx"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function LogoutConfirm(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/PageProps.ts b/src/pages/PageProps.ts index 893a0645..5296560f 100644 --- a/src/pages/PageProps.ts +++ b/src/pages/PageProps.ts @@ -1,11 +1,11 @@ import type { LazyExoticComponent } from "react"; -import type { I18nBase } from "keycloakify/i18n"; +import type { I18n } from "keycloakify/i18n"; import { type TemplateProps, type TemplateClassKey, defaultTemplateClasses } from "keycloakify/TemplateProps"; -export type PageProps = { +export type PageProps = { Template: LazyExoticComponent<(props: TemplateProps) => JSX.Element | null>; kcContext: KcContext; - i18n: I18n; + i18n: I18nExtended; doUseDefaultCss: boolean; classes?: Partial>; }; diff --git a/src/pages/Register.tsx b/src/pages/Register.tsx index f880233c..6ad5e872 100644 --- a/src/pages/Register.tsx +++ b/src/pages/Register.tsx @@ -2,7 +2,7 @@ import { clsx } from "keycloakify/tools/clsx"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function Register(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/RegisterUserProfile.tsx b/src/pages/RegisterUserProfile.tsx index 814baf3d..37067982 100644 --- a/src/pages/RegisterUserProfile.tsx +++ b/src/pages/RegisterUserProfile.tsx @@ -4,7 +4,7 @@ import { UserProfileFormFields } from "./shared/UserProfileCommons"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function RegisterUserProfile(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/Terms.tsx b/src/pages/Terms.tsx index e536462f..0b189cf5 100644 --- a/src/pages/Terms.tsx +++ b/src/pages/Terms.tsx @@ -5,7 +5,7 @@ import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import { evtTermMarkdown } from "keycloakify/lib/useDownloadTerms"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function Terms(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/UpdateUserProfile.tsx b/src/pages/UpdateUserProfile.tsx index 7b540ddc..8fc2855e 100644 --- a/src/pages/UpdateUserProfile.tsx +++ b/src/pages/UpdateUserProfile.tsx @@ -4,7 +4,7 @@ import { UserProfileFormFields } from "./shared/UserProfileCommons"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function UpdateUserProfile(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/WebauthnAuthenticate.tsx b/src/pages/WebauthnAuthenticate.tsx index 98d4e231..721eb145 100644 --- a/src/pages/WebauthnAuthenticate.tsx +++ b/src/pages/WebauthnAuthenticate.tsx @@ -6,7 +6,7 @@ import { useConstCallback } from "../tools/useConstCallback"; import { type PageProps, defaultClasses } from "keycloakify/pages/PageProps"; import { useGetClassName } from "keycloakify/lib/useGetClassName"; import type { KcContext } from "../kcContext"; -import type { I18nBase as I18n } from "../i18n"; +import type { I18n } from "../i18n"; export default function WebauthnAuthenticate(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; diff --git a/src/pages/shared/UserProfileCommons.tsx b/src/pages/shared/UserProfileCommons.tsx index 4e49a7ea..e362cf60 100644 --- a/src/pages/shared/UserProfileCommons.tsx +++ b/src/pages/shared/UserProfileCommons.tsx @@ -3,7 +3,7 @@ import type { ClassKey } from "keycloakify/pages/PageProps"; import { clsx } from "keycloakify/tools/clsx"; import { useFormValidation } from "keycloakify/lib/useFormValidation"; import type { Attribute } from "keycloakify/kcContext"; -import type { I18nBase as I18n } from "../../i18n"; +import type { I18n } from "../../i18n"; export type UserProfileFormFieldsProps = { kcContext: Parameters[0]["kcContext"];