@oussemasahbeni/keycloakify-login-shadcn 250004.0.3 → 250004.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/keycloak-theme/login/KcContext.ts +23 -23
  2. package/keycloak-theme/login/KcPage.tsx +47 -47
  3. package/keycloak-theme/login/assets/img/auth-logo.svg +100 -100
  4. package/keycloak-theme/login/assets/img/shape.svg +71 -71
  5. package/keycloak-theme/login/components/LogoutOtherSessions.tsx +26 -26
  6. package/keycloak-theme/login/components/PasswordWrapper.tsx +35 -35
  7. package/keycloak-theme/login/components/Template/Template.tsx +227 -227
  8. package/keycloak-theme/login/components/Template/index.ts +1 -1
  9. package/keycloak-theme/login/components/Template/useInitializeTemplate.ts +61 -61
  10. package/keycloak-theme/login/components/UserProfileFormFields/AddRemoveButtonsMultiValuedAttribute.tsx +61 -61
  11. package/keycloak-theme/login/components/UserProfileFormFields/DO_MAKE_USER_CONFIRM_PASSWORD.ts +2 -2
  12. package/keycloak-theme/login/components/UserProfileFormFields/FieldErrors.tsx +28 -28
  13. package/keycloak-theme/login/components/UserProfileFormFields/GroupLabel.tsx +70 -70
  14. package/keycloak-theme/login/components/UserProfileFormFields/InputFieldByType.tsx +58 -58
  15. package/keycloak-theme/login/components/UserProfileFormFields/InputTag.tsx +116 -116
  16. package/keycloak-theme/login/components/UserProfileFormFields/InputTagSelects.tsx +135 -135
  17. package/keycloak-theme/login/components/UserProfileFormFields/SelectTag.tsx +114 -114
  18. package/keycloak-theme/login/components/UserProfileFormFields/TextareaTag.tsx +42 -42
  19. package/keycloak-theme/login/components/UserProfileFormFields/UserProfileFormFields.tsx +127 -127
  20. package/keycloak-theme/login/components/UserProfileFormFields/index.ts +1 -1
  21. package/keycloak-theme/login/i18n.ts +47 -47
  22. package/keycloak-theme/login/mocks/getKcContextMock.ts +22 -22
  23. package/keycloak-theme/login/pages/PageIndex.tsx +134 -134
  24. package/keycloak-theme/login/pages/code/Page.stories.tsx +54 -66
  25. package/keycloak-theme/login/pages/code/Page.tsx +89 -89
  26. package/keycloak-theme/login/pages/code/index.ts +3 -3
  27. package/keycloak-theme/login/pages/delete-account-confirm/Page.stories.tsx +39 -46
  28. package/keycloak-theme/login/pages/delete-account-confirm/Page.tsx +63 -63
  29. package/keycloak-theme/login/pages/delete-account-confirm/index.ts +3 -3
  30. package/keycloak-theme/login/pages/delete-credential/Page.stories.tsx +26 -30
  31. package/keycloak-theme/login/pages/delete-credential/Page.tsx +51 -51
  32. package/keycloak-theme/login/pages/delete-credential/index.ts +3 -3
  33. package/keycloak-theme/login/pages/error/Page.stories.tsx +47 -58
  34. package/keycloak-theme/login/pages/error/Page.tsx +42 -42
  35. package/keycloak-theme/login/pages/error/index.ts +3 -3
  36. package/keycloak-theme/login/pages/frontchannel-logout/Page.stories.tsx +25 -32
  37. package/keycloak-theme/login/pages/frontchannel-logout/Page.tsx +84 -84
  38. package/keycloak-theme/login/pages/frontchannel-logout/index.ts +3 -3
  39. package/keycloak-theme/login/pages/idp-review-user-profile/Page.stories.tsx +46 -58
  40. package/keycloak-theme/login/pages/idp-review-user-profile/Page.tsx +52 -52
  41. package/keycloak-theme/login/pages/idp-review-user-profile/index.ts +3 -3
  42. package/keycloak-theme/login/pages/info/Page.stories.tsx +50 -60
  43. package/keycloak-theme/login/pages/info/Page.tsx +92 -92
  44. package/keycloak-theme/login/pages/link-idp-action/Page.stories.tsx +32 -16
  45. package/keycloak-theme/login/pages/link-idp-action/Page.tsx +43 -43
  46. package/keycloak-theme/login/pages/link-idp-action/index.ts +3 -3
  47. package/keycloak-theme/login/pages/login/Form.tsx +242 -242
  48. package/keycloak-theme/login/pages/login/Info.tsx +29 -29
  49. package/keycloak-theme/login/pages/login/Page.stories.tsx +345 -365
  50. package/keycloak-theme/login/pages/login/Page.tsx +44 -44
  51. package/keycloak-theme/login/pages/login/SocialProviders.tsx +107 -107
  52. package/keycloak-theme/login/pages/login/index.ts +3 -3
  53. package/keycloak-theme/login/pages/login/providers/apple.svg +3 -3
  54. package/keycloak-theme/login/pages/login/providers/bitbucket.svg +11 -11
  55. package/keycloak-theme/login/pages/login/providers/discord.svg +4 -4
  56. package/keycloak-theme/login/pages/login/providers/facebook.svg +5 -5
  57. package/keycloak-theme/login/pages/login/providers/github.svg +3 -3
  58. package/keycloak-theme/login/pages/login/providers/gitlab.svg +7 -7
  59. package/keycloak-theme/login/pages/login/providers/google.svg +7 -7
  60. package/keycloak-theme/login/pages/login/providers/instagram.svg +31 -31
  61. package/keycloak-theme/login/pages/login/providers/linkedin.svg +3 -3
  62. package/keycloak-theme/login/pages/login/providers/microsoft.svg +6 -6
  63. package/keycloak-theme/login/pages/login/providers/oidc.svg +5 -5
  64. package/keycloak-theme/login/pages/login/providers/openshift.svg +7 -7
  65. package/keycloak-theme/login/pages/login/providers/paypal.svg +6 -6
  66. package/keycloak-theme/login/pages/login/providers/slack.svg +11 -11
  67. package/keycloak-theme/login/pages/login/providers/stackoverflow.svg +5 -5
  68. package/keycloak-theme/login/pages/login/providers/x.svg +3 -3
  69. package/keycloak-theme/login/pages/login/useProviderLogos.tsx +39 -39
  70. package/keycloak-theme/login/pages/login/useScript.tsx +62 -62
  71. package/keycloak-theme/login/pages/login-config-totp/Page.stories.tsx +45 -59
  72. package/keycloak-theme/login/pages/login-config-totp/Page.tsx +240 -240
  73. package/keycloak-theme/login/pages/login-config-totp/index.ts +3 -3
  74. package/keycloak-theme/login/pages/login-idp-link-confirm/Page.stories.tsx +30 -34
  75. package/keycloak-theme/login/pages/login-idp-link-confirm/Page.tsx +43 -43
  76. package/keycloak-theme/login/pages/login-idp-link-confirm/index.ts +3 -3
  77. package/keycloak-theme/login/pages/login-idp-link-confirm-override/Page.stories.tsx +16 -22
  78. package/keycloak-theme/login/pages/login-idp-link-confirm-override/Page.tsx +47 -47
  79. package/keycloak-theme/login/pages/login-idp-link-confirm-override/index.ts +3 -3
  80. package/keycloak-theme/login/pages/login-idp-link-email/Page.stories.tsx +54 -62
  81. package/keycloak-theme/login/pages/login-idp-link-email/Page.tsx +54 -54
  82. package/keycloak-theme/login/pages/login-idp-link-email/index.ts +3 -3
  83. package/keycloak-theme/login/pages/login-oauth-grant/Page.stories.tsx +39 -45
  84. package/keycloak-theme/login/pages/login-oauth-grant/Page.tsx +126 -126
  85. package/keycloak-theme/login/pages/login-oauth-grant/index.ts +3 -3
  86. package/keycloak-theme/login/pages/login-oauth2-device-verify-user-code/Page.stories.tsx +38 -48
  87. package/keycloak-theme/login/pages/login-oauth2-device-verify-user-code/Page.tsx +58 -58
  88. package/keycloak-theme/login/pages/login-oauth2-device-verify-user-code/index.ts +3 -3
  89. package/keycloak-theme/login/pages/login-otp/Page.stories.tsx +82 -96
  90. package/keycloak-theme/login/pages/login-otp/Page.tsx +108 -108
  91. package/keycloak-theme/login/pages/login-otp/index.ts +3 -3
  92. package/keycloak-theme/login/pages/login-page-expired/Page.stories.tsx +28 -36
  93. package/keycloak-theme/login/pages/login-page-expired/Page.tsx +47 -47
  94. package/keycloak-theme/login/pages/login-page-expired/index.ts +3 -3
  95. package/keycloak-theme/login/pages/login-passkeys-conditional-authenticate/Page.stories.tsx +20 -0
  96. package/keycloak-theme/login/pages/login-passkeys-conditional-authenticate/Page.tsx +233 -233
  97. package/keycloak-theme/login/pages/login-passkeys-conditional-authenticate/index.ts +3 -3
  98. package/keycloak-theme/login/pages/login-passkeys-conditional-authenticate/useScript.tsx +63 -63
  99. package/keycloak-theme/login/pages/login-password/Page.stories.tsx +55 -56
  100. package/keycloak-theme/login/pages/login-password/Page.tsx +149 -149
  101. package/keycloak-theme/login/pages/login-password/index.ts +3 -3
  102. package/keycloak-theme/login/pages/login-password/useScript.tsx +63 -63
  103. package/keycloak-theme/login/pages/login-recovery-authn-code-config/Page.stories.tsx +28 -36
  104. package/keycloak-theme/login/pages/login-recovery-authn-code-config/Page.tsx +181 -181
  105. package/keycloak-theme/login/pages/login-recovery-authn-code-config/index.ts +3 -3
  106. package/keycloak-theme/login/pages/login-recovery-authn-code-config/useScript.tsx +145 -145
  107. package/keycloak-theme/login/pages/login-recovery-authn-code-input/Page.stories.tsx +16 -22
  108. package/keycloak-theme/login/pages/login-recovery-authn-code-input/Page.tsx +70 -70
  109. package/keycloak-theme/login/pages/login-recovery-authn-code-input/index.ts +3 -3
  110. package/keycloak-theme/login/pages/login-reset-otp/Page.stories.tsx +62 -74
  111. package/keycloak-theme/login/pages/login-reset-otp/Page.tsx +86 -86
  112. package/keycloak-theme/login/pages/login-reset-otp/index.ts +3 -3
  113. package/keycloak-theme/login/pages/login-reset-password/Form.tsx +68 -68
  114. package/keycloak-theme/login/pages/login-reset-password/Page.stories.tsx +44 -54
  115. package/keycloak-theme/login/pages/login-reset-password/Page.tsx +27 -27
  116. package/keycloak-theme/login/pages/login-reset-password/index.ts +3 -3
  117. package/keycloak-theme/login/pages/login-update-password/Page.stories.tsx +40 -50
  118. package/keycloak-theme/login/pages/login-update-password/Page.tsx +111 -111
  119. package/keycloak-theme/login/pages/login-update-password/index.ts +3 -3
  120. package/keycloak-theme/login/pages/login-update-profile/Page.stories.tsx +28 -36
  121. package/keycloak-theme/login/pages/login-update-profile/Page.tsx +68 -68
  122. package/keycloak-theme/login/pages/login-update-profile/index.ts +3 -3
  123. package/keycloak-theme/login/pages/login-username/Page.stories.tsx +32 -42
  124. package/keycloak-theme/login/pages/login-username/Page.tsx +246 -246
  125. package/keycloak-theme/login/pages/login-username/index.ts +3 -3
  126. package/keycloak-theme/login/pages/login-username/useScript.tsx +62 -62
  127. package/keycloak-theme/login/pages/login-verify-email/Page.stories.tsx +68 -80
  128. package/keycloak-theme/login/pages/login-verify-email/Page.tsx +38 -38
  129. package/keycloak-theme/login/pages/login-verify-email/index.ts +3 -3
  130. package/keycloak-theme/login/pages/login-x509-info/Page.stories.tsx +29 -37
  131. package/keycloak-theme/login/pages/login-x509-info/Page.tsx +75 -75
  132. package/keycloak-theme/login/pages/login-x509-info/index.ts +3 -3
  133. package/keycloak-theme/login/pages/logout-confirm/Page.stories.tsx +34 -42
  134. package/keycloak-theme/login/pages/logout-confirm/Page.tsx +53 -53
  135. package/keycloak-theme/login/pages/logout-confirm/index.ts +3 -3
  136. package/keycloak-theme/login/pages/register/Form.tsx +106 -106
  137. package/keycloak-theme/login/pages/register/Page.stories.tsx +23 -6
  138. package/keycloak-theme/login/pages/register/Page.tsx +26 -26
  139. package/keycloak-theme/login/pages/register/TermsAcceptance.tsx +56 -56
  140. package/keycloak-theme/login/pages/register/index.ts +3 -3
  141. package/keycloak-theme/login/pages/saml-post-form/Page.stories.tsx +16 -22
  142. package/keycloak-theme/login/pages/saml-post-form/Page.tsx +66 -66
  143. package/keycloak-theme/login/pages/saml-post-form/index.ts +3 -3
  144. package/keycloak-theme/login/pages/select-authenticator/Page.stories.tsx +83 -95
  145. package/keycloak-theme/login/pages/select-authenticator/Page.tsx +100 -100
  146. package/keycloak-theme/login/pages/select-authenticator/index.ts +3 -3
  147. package/keycloak-theme/login/pages/select-organization/Page.stories.tsx +62 -49
  148. package/keycloak-theme/login/pages/select-organization/Page.tsx +126 -126
  149. package/keycloak-theme/login/pages/select-organization/index.ts +3 -3
  150. package/keycloak-theme/login/pages/terms/Page.stories.tsx +15 -0
  151. package/keycloak-theme/login/pages/terms/Page.tsx +51 -51
  152. package/keycloak-theme/login/pages/terms/index.ts +3 -3
  153. package/keycloak-theme/login/pages/update-email/Page.stories.tsx +27 -35
  154. package/keycloak-theme/login/pages/update-email/Page.tsx +62 -62
  155. package/keycloak-theme/login/pages/update-email/index.ts +3 -3
  156. package/keycloak-theme/login/pages/webauthn-authenticate/Page.stories.tsx +112 -126
  157. package/keycloak-theme/login/pages/webauthn-authenticate/Page.tsx +202 -202
  158. package/keycloak-theme/login/pages/webauthn-authenticate/index.ts +3 -3
  159. package/keycloak-theme/login/pages/webauthn-authenticate/useScript.tsx +55 -55
  160. package/keycloak-theme/login/pages/webauthn-error/Page.stories.tsx +54 -66
  161. package/keycloak-theme/login/pages/webauthn-error/Page.tsx +73 -73
  162. package/keycloak-theme/login/pages/webauthn-error/index.ts +3 -3
  163. package/keycloak-theme/login/pages/webauthn-register/Page.stories.tsx +39 -49
  164. package/keycloak-theme/login/pages/webauthn-register/Page.tsx +78 -78
  165. package/keycloak-theme/login/pages/webauthn-register/index.ts +3 -3
  166. package/keycloak-theme/login/pages/webauthn-register/useScript.tsx +62 -62
  167. package/keycloak-theme/login/shared/getColorScheme.ts +45 -45
  168. package/keycloak-theme/login/styleLevelCustomization.tsx +35 -35
  169. package/package.json +5 -1
@@ -1,35 +1,35 @@
1
- import { useI18n } from '@/login/i18n';
2
- import { useKcContext } from '@/login/KcContext';
3
- import { useIsPasswordRevealed } from "keycloakify/tools/useIsPasswordRevealed";
4
- import { FiEye, FiEyeOff } from "react-icons/fi";
5
-
6
- export function PasswordWrapper(props: {
7
- passwordInputId: string;
8
- children: JSX.Element;
9
- }) {
10
- const { passwordInputId, children } = props;
11
- const { kcContext } = useKcContext();
12
-
13
- const { msgStr } = useI18n();
14
-
15
-
16
- const { isPasswordRevealed, toggleIsPasswordRevealed } = useIsPasswordRevealed({
17
- passwordInputId
18
- });
19
-
20
-
21
- return (
22
- <div className="relative">
23
- {children}
24
- <button
25
- type="button"
26
- className={`absolute inset-y-0 ${kcContext.locale?.rtl ? "left-0 pl-3" : "right-0 pr-3"} flex items-center text-sm leading-5`}
27
- aria-label={msgStr(isPasswordRevealed ? "hidePassword" : "showPassword")}
28
- aria-controls={passwordInputId}
29
- onClick={toggleIsPasswordRevealed}
30
- >
31
- {isPasswordRevealed ? <FiEye /> : <FiEyeOff />}
32
- </button>
33
- </div>
34
- );
35
- }
1
+ import { useI18n } from '@/login/i18n';
2
+ import { useKcContext } from '@/login/KcContext';
3
+ import { useIsPasswordRevealed } from "keycloakify/tools/useIsPasswordRevealed";
4
+ import { FiEye, FiEyeOff } from "react-icons/fi";
5
+
6
+ export function PasswordWrapper(props: {
7
+ passwordInputId: string;
8
+ children: JSX.Element;
9
+ }) {
10
+ const { passwordInputId, children } = props;
11
+ const { kcContext } = useKcContext();
12
+
13
+ const { msgStr } = useI18n();
14
+
15
+
16
+ const { isPasswordRevealed, toggleIsPasswordRevealed } = useIsPasswordRevealed({
17
+ passwordInputId
18
+ });
19
+
20
+
21
+ return (
22
+ <div className="relative">
23
+ {children}
24
+ <button
25
+ type="button"
26
+ className={`absolute inset-y-0 ${kcContext.locale?.rtl ? "left-0 pl-3" : "right-0 pr-3"} flex items-center text-sm leading-5`}
27
+ aria-label={msgStr(isPasswordRevealed ? "hidePassword" : "showPassword")}
28
+ aria-controls={passwordInputId}
29
+ onClick={toggleIsPasswordRevealed}
30
+ >
31
+ {isPasswordRevealed ? <FiEye /> : <FiEyeOff />}
32
+ </button>
33
+ </div>
34
+ );
35
+ }
@@ -1,227 +1,227 @@
1
- import { Languages } from '@/components/langauges';
2
- import { ModeToggle } from '@/components/theme-toggle';
3
- import { Alert, AlertDescription } from '@/components/ui/alert';
4
- import { Button } from '@/components/ui/button';
5
- import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
6
- import { redirectUrlOrigin } from '@/login/shared/redirectUrlOrigin';
7
- import { kcSanitize } from "@keycloakify/login-ui/kcSanitize";
8
- import { useKcClsx } from "@keycloakify/login-ui/useKcClsx";
9
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@radix-ui/react-tooltip';
10
- import { useSetClassName } from "keycloakify/tools/useSetClassName";
11
- import { RotateCcw } from 'lucide-react';
12
- import type { ReactNode } from "react";
13
- import { useEffect } from "react";
14
- import { FiHome } from 'react-icons/fi';
15
- import { useI18n } from "../../i18n";
16
- import { useKcContext } from "../../KcContext";
17
- import companylogo from "./../../assets/img/auth-logo.svg";
18
- import shape from "./../../assets/img/shape.svg";
19
- import { useInitializeTemplate } from "./useInitializeTemplate";
20
-
21
- const APP_NAME = "Acme Inc.";
22
-
23
- export function Template(props: {
24
- displayInfo?: boolean;
25
- displayMessage?: boolean;
26
- displayRequiredFields?: boolean;
27
- headerNode: ReactNode;
28
- socialProvidersNode?: ReactNode;
29
- infoNode?: ReactNode;
30
- documentTitle?: string;
31
- bodyClassName?: string;
32
- children: ReactNode;
33
- }) {
34
- const {
35
- displayInfo = false,
36
- displayMessage = true,
37
- displayRequiredFields = false,
38
- headerNode,
39
- socialProvidersNode = null,
40
- infoNode = null,
41
- documentTitle,
42
- bodyClassName,
43
- children
44
- } = props;
45
-
46
- const { kcContext } = useKcContext();
47
-
48
- const { auth, url, message, isAppInitiatedAction } = kcContext;
49
-
50
-
51
- const { msg, msgStr, enabledLanguages } = useI18n();
52
-
53
- const { kcClsx } = useKcClsx();
54
-
55
- useEffect(() => {
56
- document.title =
57
- documentTitle ?? msgStr("loginTitle", kcContext.realm.displayName);
58
- }, []);
59
-
60
- useSetClassName({
61
- qualifiedName: "html",
62
- className: kcClsx("kcHtmlClass")
63
- });
64
-
65
- useSetClassName({
66
- qualifiedName: "body",
67
- className: bodyClassName ?? kcClsx("kcBodyClass")
68
- });
69
-
70
- const { isReadyToRender } = useInitializeTemplate();
71
-
72
- if (!isReadyToRender) {
73
- return null;
74
- }
75
-
76
- return (
77
- <div className="grid min-h-svh lg:grid-cols-2 bg-white dark:bg-background lg:bg-transparent">
78
- {/* Main content */}
79
- <div className="flex flex-col gap-4 px-0 py-0 pb-6 lg:p-6 lg:md:p-10 lg:pt-10 min-h-screen lg:min-h-0">
80
- {/* navigation */}
81
- <div className="absolute top-4 right-4 lg:left-4 z-20 flex gap-2">
82
- <Button variant="outline" size="icon" >
83
- <a href={kcContext.client.baseUrl ?? redirectUrlOrigin}>
84
- <FiHome />
85
- </a>
86
- </Button>
87
-
88
- {enabledLanguages.length > 1 && (
89
- <Languages />
90
- )}
91
-
92
-
93
- {kcContext.darkMode !== false && (
94
- <ModeToggle />
95
- )}
96
- </div>
97
-
98
- {/* Mobile header with logo */}
99
- <div className="lg:hidden relative pt-8 px-6">
100
- {/* Logo and welcome message */}
101
- <div className="flex flex-col items-center justify-center gap-3 mt-4">
102
- <div className=" mb-4 flex items-center gap-3">
103
- <img src={companylogo} alt="Logo" />
104
- <span className=" text-xl"> {APP_NAME}</span>
105
- </div>
106
- </div>
107
- </div>
108
-
109
- <div className="flex flex-1 items-start lg:items-center justify-center lg:mt-0 ">
110
- <div className="w-full max-w-xl ">
111
- <Card className=" shadow-none bg-transparent lg:bg-card border-0 lg:rounded-lg lg:border lg:shadow-sm rounded-t-2xl">
112
- <CardHeader className="text-center mb-3 px-6 pt-8 pb-4 lg:pt-6">
113
- <CardTitle>
114
- {(() => {
115
- const node = !(auth !== undefined && auth.showUsername && !auth.showResetCredentials) ? (
116
- <h1 className="text-xl">{headerNode}</h1>
117
- ) : (
118
- <div id="kc-username" className="flex items-center justify-center gap-2">
119
- <label className="font-semibold text-lg" id="kc-attempted-username">
120
- {auth.attemptedUsername}
121
- </label>
122
-
123
- <TooltipProvider>
124
- <Tooltip>
125
- <TooltipTrigger asChild>
126
- <Button variant="outline" size="icon" asChild>
127
- <a
128
- id="reset-login"
129
- href={url.loginRestartFlowUrl}
130
- aria-label={msgStr("restartLoginTooltip")}
131
- >
132
- <RotateCcw className="h-4 w-4" />
133
- </a>
134
- </Button>
135
- </TooltipTrigger>
136
- <TooltipContent>
137
- <p>{msg("restartLoginTooltip")}</p>
138
- </TooltipContent>
139
- </Tooltip>
140
- </TooltipProvider>
141
- </div>
142
- );
143
-
144
- if (displayRequiredFields) {
145
- return (
146
- <div className="flex items-center justify-between gap-2">
147
- <div>{node}</div>
148
- <div>
149
- <span className="subtitle">
150
- <span className="text-red-500">*</span>
151
- {msg("requiredFields")}
152
- </span>
153
- </div>
154
- </div>
155
- );
156
- }
157
-
158
- return node;
159
- })()}
160
- </CardTitle>
161
- </CardHeader>
162
- <CardContent className="px-6 pb-8">
163
- <div id="kc-content">
164
- <div id="kc-content-wrapper">
165
- {displayMessage && message !== undefined && (message.type !== "warning" || !isAppInitiatedAction) && (
166
- <Alert variant={message.type} className="my-3">
167
- <AlertDescription>
168
- <div>
169
- <span
170
- dangerouslySetInnerHTML={{
171
- __html: kcSanitize(message.summary)
172
- }}
173
- />
174
- </div>
175
- </AlertDescription>
176
- </Alert>
177
- )}
178
- <div className="children">{children}</div>
179
- {socialProvidersNode}
180
- {auth !== undefined && auth.showTryAnotherWayLink && (
181
- <form id="kc-select-try-another-way-form" action={url.loginAction} method="post">
182
- <div className={kcClsx("kcFormGroupClass")}>
183
- <input type="hidden" name="tryAnotherWay" value="on" />
184
- <a
185
- href="#"
186
- id="try-another-way"
187
- onClick={() => {
188
- document.forms["kc-select-try-another-way-form" as never].submit();
189
- return false;
190
- }}
191
- >
192
- {msg("doTryAnotherWay")}
193
- </a>
194
- </div>
195
- </form>
196
- )}
197
- {displayInfo && <div className="text-center text-sm mt-4">{infoNode}</div>}
198
- </div>
199
- </div>
200
- </CardContent>
201
- </Card>
202
- </div>
203
- </div>
204
- </div>
205
-
206
- <div className="bg-slate-950 relative hidden lg:block dark:bg-white/5">
207
- <div className="flex items-center pt-20 h-full justify-center z-1">
208
- <div className="absolute right-0 top-0 w-full max-w-62.5 xl:max-w-112.5">
209
- <img src={shape} alt="grid" />
210
- </div>
211
- <div className="absolute bottom-0 left-0 w-full max-w-62.5 rotate-180 xl:max-w-112.5">
212
- <img src={shape} alt="grid" />
213
- </div>
214
-
215
- <div className="flex justify-center my-auto flex-col items-center max-w-xs">
216
- <div className=" mb-4 flex items-center gap-3">
217
- <img src={companylogo} alt="Logo" />
218
- <span className="text-white text-xl"> {APP_NAME}</span>
219
- </div>
220
-
221
- <p className="text-center text-gray-400 dark:text-white/60">{msg("welcomeMessage")}</p>
222
- </div>
223
- </div>
224
- </div>
225
- </div>
226
- );
227
- }
1
+ import { Languages } from '@/components/langauges';
2
+ import { ModeToggle } from '@/components/theme-toggle';
3
+ import { Alert, AlertDescription } from '@/components/ui/alert';
4
+ import { Button } from '@/components/ui/button';
5
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
6
+ import { redirectUrlOrigin } from '@/login/shared/redirectUrlOrigin';
7
+ import { kcSanitize } from "@keycloakify/login-ui/kcSanitize";
8
+ import { useKcClsx } from "@keycloakify/login-ui/useKcClsx";
9
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@radix-ui/react-tooltip';
10
+ import { useSetClassName } from "keycloakify/tools/useSetClassName";
11
+ import { RotateCcw } from 'lucide-react';
12
+ import type { ReactNode } from "react";
13
+ import { useEffect } from "react";
14
+ import { FiHome } from 'react-icons/fi';
15
+ import { useI18n } from "../../i18n";
16
+ import { useKcContext } from "../../KcContext";
17
+ import companylogo from "./../../assets/img/auth-logo.svg";
18
+ import shape from "./../../assets/img/shape.svg";
19
+ import { useInitializeTemplate } from "./useInitializeTemplate";
20
+
21
+ const APP_NAME = "Acme Inc.";
22
+
23
+ export function Template(props: {
24
+ displayInfo?: boolean;
25
+ displayMessage?: boolean;
26
+ displayRequiredFields?: boolean;
27
+ headerNode: ReactNode;
28
+ socialProvidersNode?: ReactNode;
29
+ infoNode?: ReactNode;
30
+ documentTitle?: string;
31
+ bodyClassName?: string;
32
+ children: ReactNode;
33
+ }) {
34
+ const {
35
+ displayInfo = false,
36
+ displayMessage = true,
37
+ displayRequiredFields = false,
38
+ headerNode,
39
+ socialProvidersNode = null,
40
+ infoNode = null,
41
+ documentTitle,
42
+ bodyClassName,
43
+ children
44
+ } = props;
45
+
46
+ const { kcContext } = useKcContext();
47
+
48
+ const { auth, url, message, isAppInitiatedAction } = kcContext;
49
+
50
+
51
+ const { msg, msgStr, enabledLanguages } = useI18n();
52
+
53
+ const { kcClsx } = useKcClsx();
54
+
55
+ useEffect(() => {
56
+ document.title =
57
+ documentTitle ?? msgStr("loginTitle", kcContext.realm.displayName);
58
+ }, []);
59
+
60
+ useSetClassName({
61
+ qualifiedName: "html",
62
+ className: kcClsx("kcHtmlClass")
63
+ });
64
+
65
+ useSetClassName({
66
+ qualifiedName: "body",
67
+ className: bodyClassName ?? kcClsx("kcBodyClass")
68
+ });
69
+
70
+ const { isReadyToRender } = useInitializeTemplate();
71
+
72
+ if (!isReadyToRender) {
73
+ return null;
74
+ }
75
+
76
+ return (
77
+ <div className="grid min-h-svh lg:grid-cols-2 bg-white dark:bg-background lg:bg-transparent">
78
+ {/* Main content */}
79
+ <div className="flex flex-col gap-4 px-0 py-0 pb-6 lg:p-6 lg:md:p-10 lg:pt-10 min-h-screen lg:min-h-0">
80
+ {/* navigation */}
81
+ <div className="absolute top-4 right-4 lg:left-4 z-20 flex gap-2">
82
+ <Button variant="outline" size="icon" >
83
+ <a href={kcContext.client.baseUrl ?? redirectUrlOrigin}>
84
+ <FiHome />
85
+ </a>
86
+ </Button>
87
+
88
+ {enabledLanguages.length > 1 && (
89
+ <Languages />
90
+ )}
91
+
92
+
93
+ {kcContext.darkMode !== false && (
94
+ <ModeToggle />
95
+ )}
96
+ </div>
97
+
98
+ {/* Mobile header with logo */}
99
+ <div className="lg:hidden relative pt-8 px-6">
100
+ {/* Logo and welcome message */}
101
+ <div className="flex flex-col items-center justify-center gap-3 mt-4">
102
+ <div className=" mb-4 flex items-center gap-3">
103
+ <img src={companylogo} alt="Logo" />
104
+ <span className=" text-xl"> {APP_NAME}</span>
105
+ </div>
106
+ </div>
107
+ </div>
108
+
109
+ <div className="flex flex-1 items-start lg:items-center justify-center lg:mt-0 ">
110
+ <div className="w-full max-w-xl ">
111
+ <Card className=" shadow-none bg-transparent lg:bg-card border-0 lg:rounded-lg lg:border lg:shadow-sm rounded-t-2xl">
112
+ <CardHeader className="text-center mb-3 px-6 pt-8 pb-4 lg:pt-6">
113
+ <CardTitle>
114
+ {(() => {
115
+ const node = !(auth !== undefined && auth.showUsername && !auth.showResetCredentials) ? (
116
+ <h1 className="text-xl">{headerNode}</h1>
117
+ ) : (
118
+ <div id="kc-username" className="flex items-center justify-center gap-2">
119
+ <label className="font-semibold text-lg" id="kc-attempted-username">
120
+ {auth.attemptedUsername}
121
+ </label>
122
+
123
+ <TooltipProvider>
124
+ <Tooltip>
125
+ <TooltipTrigger asChild>
126
+ <Button variant="outline" size="icon" asChild>
127
+ <a
128
+ id="reset-login"
129
+ href={url.loginRestartFlowUrl}
130
+ aria-label={msgStr("restartLoginTooltip")}
131
+ >
132
+ <RotateCcw className="h-4 w-4" />
133
+ </a>
134
+ </Button>
135
+ </TooltipTrigger>
136
+ <TooltipContent>
137
+ <p>{msg("restartLoginTooltip")}</p>
138
+ </TooltipContent>
139
+ </Tooltip>
140
+ </TooltipProvider>
141
+ </div>
142
+ );
143
+
144
+ if (displayRequiredFields) {
145
+ return (
146
+ <div className="flex items-center justify-between gap-2">
147
+ <div>{node}</div>
148
+ <div>
149
+ <span className="subtitle">
150
+ <span className="text-red-500">*</span>
151
+ {msg("requiredFields")}
152
+ </span>
153
+ </div>
154
+ </div>
155
+ );
156
+ }
157
+
158
+ return node;
159
+ })()}
160
+ </CardTitle>
161
+ </CardHeader>
162
+ <CardContent className="px-6 pb-8">
163
+ <div id="kc-content">
164
+ <div id="kc-content-wrapper">
165
+ {displayMessage && message !== undefined && (message.type !== "warning" || !isAppInitiatedAction) && (
166
+ <Alert variant={message.type} className="my-3">
167
+ <AlertDescription>
168
+ <div>
169
+ <span
170
+ dangerouslySetInnerHTML={{
171
+ __html: kcSanitize(message.summary)
172
+ }}
173
+ />
174
+ </div>
175
+ </AlertDescription>
176
+ </Alert>
177
+ )}
178
+ <div className="children">{children}</div>
179
+ {socialProvidersNode}
180
+ {auth !== undefined && auth.showTryAnotherWayLink && (
181
+ <form id="kc-select-try-another-way-form" action={url.loginAction} method="post">
182
+ <div className={kcClsx("kcFormGroupClass")}>
183
+ <input type="hidden" name="tryAnotherWay" value="on" />
184
+ <a
185
+ href="#"
186
+ id="try-another-way"
187
+ onClick={() => {
188
+ document.forms["kc-select-try-another-way-form" as never].submit();
189
+ return false;
190
+ }}
191
+ >
192
+ {msg("doTryAnotherWay")}
193
+ </a>
194
+ </div>
195
+ </form>
196
+ )}
197
+ {displayInfo && <div className="text-center text-sm mt-4">{infoNode}</div>}
198
+ </div>
199
+ </div>
200
+ </CardContent>
201
+ </Card>
202
+ </div>
203
+ </div>
204
+ </div>
205
+
206
+ <div className="bg-slate-950 relative hidden lg:block dark:bg-white/5">
207
+ <div className="flex items-center pt-20 h-full justify-center z-1">
208
+ <div className="absolute right-0 top-0 w-full max-w-62.5 xl:max-w-112.5">
209
+ <img src={shape} alt="grid" />
210
+ </div>
211
+ <div className="absolute bottom-0 left-0 w-full max-w-62.5 rotate-180 xl:max-w-112.5">
212
+ <img src={shape} alt="grid" />
213
+ </div>
214
+
215
+ <div className="flex justify-center my-auto flex-col items-center max-w-xs">
216
+ <div className=" mb-4 flex items-center gap-3">
217
+ <img src={companylogo} alt="Logo" />
218
+ <span className="text-white text-xl"> {APP_NAME}</span>
219
+ </div>
220
+
221
+ <p className="text-center text-gray-400 dark:text-white/60">{msg("welcomeMessage")}</p>
222
+ </div>
223
+ </div>
224
+ </div>
225
+ </div>
226
+ );
227
+ }
@@ -1 +1 @@
1
- export * from "./Template";
1
+ export * from "./Template";