@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,233 +1,233 @@
1
- import { clsx } from "@keycloakify/login-ui/tools/clsx";
2
- import { useKcClsx } from "@keycloakify/login-ui/useKcClsx";
3
- import { Fragment } from "react";
4
- import { assert } from "tsafe/assert";
5
- import { useKcContext } from "../../KcContext";
6
- import { Template } from "../../components/Template";
7
- import { useI18n } from "../../i18n";
8
- import { useScript } from "./useScript";
9
-
10
- export function Page() {
11
- const { kcContext } = useKcContext();
12
- assert(kcContext.pageId === "login-passkeys-conditional-authenticate.ftl");
13
-
14
- const {
15
- messagesPerField,
16
- login,
17
- url,
18
- usernameHidden,
19
- shouldDisplayAuthenticators,
20
- authenticators,
21
- registrationDisabled,
22
- realm
23
- } = kcContext;
24
-
25
- const { msg, msgStr, advancedMsg } = useI18n();
26
-
27
- const { kcClsx } = useKcClsx();
28
-
29
- const webAuthnButtonId = "authenticateWebAuthnButton";
30
-
31
- useScript({ webAuthnButtonId });
32
-
33
- return (
34
- <Template
35
- headerNode={msg("passkey-login-title")}
36
- infoNode={
37
- realm.registrationAllowed &&
38
- !registrationDisabled && (
39
- <div id="kc-registration">
40
- <span>
41
- ${msg("noAccount")}{" "}
42
- <a tabIndex={6} href={url.registrationUrl}>
43
- {msg("doRegister")}
44
- </a>
45
- </span>
46
- </div>
47
- )
48
- }
49
- >
50
- <form id="webauth" action={url.loginAction} method="post">
51
- <input type="hidden" id="clientDataJSON" name="clientDataJSON" />
52
- <input type="hidden" id="authenticatorData" name="authenticatorData" />
53
- <input type="hidden" id="signature" name="signature" />
54
- <input type="hidden" id="credentialId" name="credentialId" />
55
- <input type="hidden" id="userHandle" name="userHandle" />
56
- <input type="hidden" id="error" name="error" />
57
- </form>
58
-
59
- <div className={kcClsx("kcFormGroupClass")} style={{ marginBottom: 0 }}>
60
- {authenticators !== undefined && Object.keys(authenticators).length !== 0 && (
61
- <>
62
- <form id="authn_select" className={kcClsx("kcFormClass")}>
63
- {authenticators.authenticators.map((authenticator, i) => (
64
- <input
65
- key={i}
66
- type="hidden"
67
- name="authn_use_chk"
68
- readOnly
69
- value={authenticator.credentialId}
70
- />
71
- ))}
72
- </form>
73
- {shouldDisplayAuthenticators && (
74
- <>
75
- {authenticators.authenticators.length > 1 && (
76
- <p className={kcClsx("kcSelectAuthListItemTitle")}>
77
- {msg("passkey-available-authenticators")}
78
- </p>
79
- )}
80
- <div className={kcClsx("kcFormClass")}>
81
- {authenticators.authenticators.map((authenticator, i) => (
82
- <div
83
- key={i}
84
- id={`kc-webauthn-authenticator-item-${i}`}
85
- className={kcClsx("kcSelectAuthListItemClass")}
86
- >
87
- <i
88
- className={clsx(
89
- (() => {
90
- const className = kcClsx(
91
- authenticator.transports.iconClass as any
92
- );
93
- if (
94
- className ===
95
- authenticator.transports.iconClass
96
- ) {
97
- return kcClsx("kcWebAuthnDefaultIcon");
98
- }
99
- return className;
100
- })(),
101
- kcClsx("kcSelectAuthListItemIconPropertyClass")
102
- )}
103
- />
104
- <div className={kcClsx("kcSelectAuthListItemBodyClass")}>
105
- <div
106
- id={`kc-webauthn-authenticator-label-${i}`}
107
- className={kcClsx(
108
- "kcSelectAuthListItemHeadingClass"
109
- )}
110
- >
111
- {advancedMsg(authenticator.label)}
112
- </div>
113
- {authenticator.transports !== undefined &&
114
- authenticator.transports.displayNameProperties !==
115
- undefined &&
116
- authenticator.transports.displayNameProperties
117
- .length !== 0 && (
118
- <div
119
- id={`kc-webauthn-authenticator-transport-${i}`}
120
- className={kcClsx(
121
- "kcSelectAuthListItemDescriptionClass"
122
- )}
123
- >
124
- {authenticator.transports.displayNameProperties.map(
125
- (nameProperty, i, arr) => (
126
- <Fragment key={i}>
127
- <span key={i}>
128
- {" "}
129
- {advancedMsg(
130
- nameProperty
131
- )}{" "}
132
- </span>
133
- {i !== arr.length - 1 && (
134
- <span>, </span>
135
- )}
136
- </Fragment>
137
- )
138
- )}
139
- </div>
140
- )}
141
- <div
142
- className={kcClsx(
143
- "kcSelectAuthListItemDescriptionClass"
144
- )}
145
- >
146
- <span
147
- id={`kc-webauthn-authenticator-createdlabel-${i}`}
148
- >
149
- {msg("passkey-createdAt-label")}
150
- </span>
151
- <span id={`kc-webauthn-authenticator-created-${i}`}>
152
- {authenticator.createdAt}
153
- </span>
154
- </div>
155
- </div>
156
- <div className={kcClsx("kcSelectAuthListItemFillClass")} />
157
- </div>
158
- ))}
159
- </div>
160
- </>
161
- )}
162
- </>
163
- )}
164
- <div id="kc-form">
165
- <div id="kc-form-wrapper">
166
- {realm.password && (
167
- <form
168
- id="kc-form-login"
169
- action={url.loginAction}
170
- method="post"
171
- style={{ display: "none" }}
172
- onSubmit={event => {
173
- try {
174
- // @ts-expect-error: Ok
175
- event.target.login.disabled = true;
176
- } catch { /* empty */ }
177
-
178
- return true;
179
- }}
180
- >
181
- {!usernameHidden && (
182
- <div className={kcClsx("kcFormGroupClass")}>
183
- <label htmlFor="username" className={kcClsx("kcLabelClass")}>
184
- {msg("passkey-autofill-select")}
185
- </label>
186
- <input
187
- tabIndex={1}
188
- id="username"
189
- aria-invalid={messagesPerField.existsError("username")}
190
- className={kcClsx("kcInputClass")}
191
- name="username"
192
- defaultValue={login.username ?? ""}
193
- autoComplete="username webauthn"
194
- type="text"
195
- autoFocus
196
- />
197
- {messagesPerField.existsError("username") && (
198
- <span
199
- id="input-error-username"
200
- className={kcClsx("kcInputErrorMessageClass")}
201
- aria-live="polite"
202
- >
203
- {messagesPerField.get("username")}
204
- </span>
205
- )}
206
- </div>
207
- )}
208
- </form>
209
- )}
210
- <div
211
- id="kc-form-passkey-button"
212
- className={kcClsx("kcFormButtonsClass")}
213
- style={{ display: "none" }}
214
- >
215
- <input
216
- id={webAuthnButtonId}
217
- type="button"
218
- autoFocus
219
- value={msgStr("passkey-doAuthenticate")}
220
- className={kcClsx(
221
- "kcButtonClass",
222
- "kcButtonPrimaryClass",
223
- "kcButtonBlockClass",
224
- "kcButtonLargeClass"
225
- )}
226
- />
227
- </div>
228
- </div>
229
- </div>
230
- </div>
231
- </Template>
232
- );
233
- }
1
+ import { clsx } from "@keycloakify/login-ui/tools/clsx";
2
+ import { useKcClsx } from "@keycloakify/login-ui/useKcClsx";
3
+ import { Fragment } from "react";
4
+ import { assert } from "tsafe/assert";
5
+ import { useKcContext } from "../../KcContext";
6
+ import { Template } from "../../components/Template";
7
+ import { useI18n } from "../../i18n";
8
+ import { useScript } from "./useScript";
9
+
10
+ export function Page() {
11
+ const { kcContext } = useKcContext();
12
+ assert(kcContext.pageId === "login-passkeys-conditional-authenticate.ftl");
13
+
14
+ const {
15
+ messagesPerField,
16
+ login,
17
+ url,
18
+ usernameHidden,
19
+ shouldDisplayAuthenticators,
20
+ authenticators,
21
+ registrationDisabled,
22
+ realm
23
+ } = kcContext;
24
+
25
+ const { msg, msgStr, advancedMsg } = useI18n();
26
+
27
+ const { kcClsx } = useKcClsx();
28
+
29
+ const webAuthnButtonId = "authenticateWebAuthnButton";
30
+
31
+ useScript({ webAuthnButtonId });
32
+
33
+ return (
34
+ <Template
35
+ headerNode={msg("passkey-login-title")}
36
+ infoNode={
37
+ realm.registrationAllowed &&
38
+ !registrationDisabled && (
39
+ <div id="kc-registration">
40
+ <span>
41
+ ${msg("noAccount")}{" "}
42
+ <a tabIndex={6} href={url.registrationUrl}>
43
+ {msg("doRegister")}
44
+ </a>
45
+ </span>
46
+ </div>
47
+ )
48
+ }
49
+ >
50
+ <form id="webauth" action={url.loginAction} method="post">
51
+ <input type="hidden" id="clientDataJSON" name="clientDataJSON" />
52
+ <input type="hidden" id="authenticatorData" name="authenticatorData" />
53
+ <input type="hidden" id="signature" name="signature" />
54
+ <input type="hidden" id="credentialId" name="credentialId" />
55
+ <input type="hidden" id="userHandle" name="userHandle" />
56
+ <input type="hidden" id="error" name="error" />
57
+ </form>
58
+
59
+ <div className={kcClsx("kcFormGroupClass")} style={{ marginBottom: 0 }}>
60
+ {authenticators !== undefined && Object.keys(authenticators).length !== 0 && (
61
+ <>
62
+ <form id="authn_select" className={kcClsx("kcFormClass")}>
63
+ {authenticators.authenticators.map((authenticator, i) => (
64
+ <input
65
+ key={i}
66
+ type="hidden"
67
+ name="authn_use_chk"
68
+ readOnly
69
+ value={authenticator.credentialId}
70
+ />
71
+ ))}
72
+ </form>
73
+ {shouldDisplayAuthenticators && (
74
+ <>
75
+ {authenticators.authenticators.length > 1 && (
76
+ <p className={kcClsx("kcSelectAuthListItemTitle")}>
77
+ {msg("passkey-available-authenticators")}
78
+ </p>
79
+ )}
80
+ <div className={kcClsx("kcFormClass")}>
81
+ {authenticators.authenticators.map((authenticator, i) => (
82
+ <div
83
+ key={i}
84
+ id={`kc-webauthn-authenticator-item-${i}`}
85
+ className={kcClsx("kcSelectAuthListItemClass")}
86
+ >
87
+ <i
88
+ className={clsx(
89
+ (() => {
90
+ const className = kcClsx(
91
+ authenticator.transports.iconClass as any
92
+ );
93
+ if (
94
+ className ===
95
+ authenticator.transports.iconClass
96
+ ) {
97
+ return kcClsx("kcWebAuthnDefaultIcon");
98
+ }
99
+ return className;
100
+ })(),
101
+ kcClsx("kcSelectAuthListItemIconPropertyClass")
102
+ )}
103
+ />
104
+ <div className={kcClsx("kcSelectAuthListItemBodyClass")}>
105
+ <div
106
+ id={`kc-webauthn-authenticator-label-${i}`}
107
+ className={kcClsx(
108
+ "kcSelectAuthListItemHeadingClass"
109
+ )}
110
+ >
111
+ {advancedMsg(authenticator.label)}
112
+ </div>
113
+ {authenticator.transports !== undefined &&
114
+ authenticator.transports.displayNameProperties !==
115
+ undefined &&
116
+ authenticator.transports.displayNameProperties
117
+ .length !== 0 && (
118
+ <div
119
+ id={`kc-webauthn-authenticator-transport-${i}`}
120
+ className={kcClsx(
121
+ "kcSelectAuthListItemDescriptionClass"
122
+ )}
123
+ >
124
+ {authenticator.transports.displayNameProperties.map(
125
+ (nameProperty, i, arr) => (
126
+ <Fragment key={i}>
127
+ <span key={i}>
128
+ {" "}
129
+ {advancedMsg(
130
+ nameProperty
131
+ )}{" "}
132
+ </span>
133
+ {i !== arr.length - 1 && (
134
+ <span>, </span>
135
+ )}
136
+ </Fragment>
137
+ )
138
+ )}
139
+ </div>
140
+ )}
141
+ <div
142
+ className={kcClsx(
143
+ "kcSelectAuthListItemDescriptionClass"
144
+ )}
145
+ >
146
+ <span
147
+ id={`kc-webauthn-authenticator-createdlabel-${i}`}
148
+ >
149
+ {msg("passkey-createdAt-label")}
150
+ </span>
151
+ <span id={`kc-webauthn-authenticator-created-${i}`}>
152
+ {authenticator.createdAt}
153
+ </span>
154
+ </div>
155
+ </div>
156
+ <div className={kcClsx("kcSelectAuthListItemFillClass")} />
157
+ </div>
158
+ ))}
159
+ </div>
160
+ </>
161
+ )}
162
+ </>
163
+ )}
164
+ <div id="kc-form">
165
+ <div id="kc-form-wrapper">
166
+ {realm.password && (
167
+ <form
168
+ id="kc-form-login"
169
+ action={url.loginAction}
170
+ method="post"
171
+ style={{ display: "none" }}
172
+ onSubmit={event => {
173
+ try {
174
+ // @ts-expect-error: Ok
175
+ event.target.login.disabled = true;
176
+ } catch { /* empty */ }
177
+
178
+ return true;
179
+ }}
180
+ >
181
+ {!usernameHidden && (
182
+ <div className={kcClsx("kcFormGroupClass")}>
183
+ <label htmlFor="username" className={kcClsx("kcLabelClass")}>
184
+ {msg("passkey-autofill-select")}
185
+ </label>
186
+ <input
187
+ tabIndex={1}
188
+ id="username"
189
+ aria-invalid={messagesPerField.existsError("username")}
190
+ className={kcClsx("kcInputClass")}
191
+ name="username"
192
+ defaultValue={login.username ?? ""}
193
+ autoComplete="username webauthn"
194
+ type="text"
195
+ autoFocus
196
+ />
197
+ {messagesPerField.existsError("username") && (
198
+ <span
199
+ id="input-error-username"
200
+ className={kcClsx("kcInputErrorMessageClass")}
201
+ aria-live="polite"
202
+ >
203
+ {messagesPerField.get("username")}
204
+ </span>
205
+ )}
206
+ </div>
207
+ )}
208
+ </form>
209
+ )}
210
+ <div
211
+ id="kc-form-passkey-button"
212
+ className={kcClsx("kcFormButtonsClass")}
213
+ style={{ display: "none" }}
214
+ >
215
+ <input
216
+ id={webAuthnButtonId}
217
+ type="button"
218
+ autoFocus
219
+ value={msgStr("passkey-doAuthenticate")}
220
+ className={kcClsx(
221
+ "kcButtonClass",
222
+ "kcButtonPrimaryClass",
223
+ "kcButtonBlockClass",
224
+ "kcButtonLargeClass"
225
+ )}
226
+ />
227
+ </div>
228
+ </div>
229
+ </div>
230
+ </div>
231
+ </Template>
232
+ );
233
+ }
@@ -1,3 +1,3 @@
1
- import { Page } from "./Page";
2
-
3
- export default Page;
1
+ import { Page } from "./Page";
2
+
3
+ export default Page;
@@ -1,63 +1,63 @@
1
- import { useInsertScriptTags } from "@keycloakify/login-ui/tools/useInsertScriptTags";
2
- import { waitForElementMountedOnDom } from "@keycloakify/login-ui/tools/waitForElementMountedOnDom";
3
- import { useEffect } from "react";
4
- import { assert } from "tsafe/assert";
5
-
6
- import { useI18n } from "../../i18n";
7
- import { useKcContext } from "../../KcContext";
8
-
9
- export function useScript(params: { webAuthnButtonId: string }) {
10
- const { webAuthnButtonId } = params;
11
-
12
- const { kcContext } = useKcContext();
13
- assert(kcContext.pageId === "login-passkeys-conditional-authenticate.ftl");
14
-
15
- const { msgStr, isFetchingTranslations } = useI18n();
16
-
17
- const { insertScriptTags } = useInsertScriptTags({
18
- effectId: "LoginRecoveryAuthnCodeConfig",
19
- scriptTags: [
20
- {
21
- type: "module",
22
- textContent: () => `
23
- import { authenticateByWebAuthn } from "${import.meta.env.BASE_URL}keycloak-theme/login/js/webauthnAuthenticate.js";
24
- import { initAuthenticate } from "${import.meta.env.BASE_URL}keycloak-theme/login/js/passkeysConditionalAuth.js";
25
-
26
- const authButton = document.getElementById("${webAuthnButtonId}");
27
- const input = {
28
- isUserIdentified : ${kcContext.isUserIdentified},
29
- challenge : ${JSON.stringify(kcContext.challenge)},
30
- userVerification : ${JSON.stringify(kcContext.userVerification)},
31
- rpId : ${JSON.stringify(kcContext.rpId)},
32
- createTimeout : ${kcContext.createTimeout}
33
- };
34
- authButton.addEventListener("click", () => {
35
- authenticateByWebAuthn({
36
- ...input,
37
- errmsg : ${JSON.stringify(msgStr("webauthn-unsupported-browser-text"))}
38
- });
39
- });
40
-
41
- initAuthenticate({
42
- ...input,
43
- errmsg : ${JSON.stringify(msgStr("passkey-unsupported-browser-text"))}
44
- });
45
- `
46
- }
47
- ]
48
- });
49
-
50
- useEffect(() => {
51
- if (isFetchingTranslations) {
52
- return;
53
- }
54
-
55
- (async () => {
56
- await waitForElementMountedOnDom({
57
- elementId: webAuthnButtonId
58
- });
59
-
60
- insertScriptTags();
61
- })();
62
- }, [isFetchingTranslations]);
63
- }
1
+ import { useInsertScriptTags } from "@keycloakify/login-ui/tools/useInsertScriptTags";
2
+ import { waitForElementMountedOnDom } from "@keycloakify/login-ui/tools/waitForElementMountedOnDom";
3
+ import { useEffect } from "react";
4
+ import { assert } from "tsafe/assert";
5
+
6
+ import { useI18n } from "../../i18n";
7
+ import { useKcContext } from "../../KcContext";
8
+
9
+ export function useScript(params: { webAuthnButtonId: string }) {
10
+ const { webAuthnButtonId } = params;
11
+
12
+ const { kcContext } = useKcContext();
13
+ assert(kcContext.pageId === "login-passkeys-conditional-authenticate.ftl");
14
+
15
+ const { msgStr, isFetchingTranslations } = useI18n();
16
+
17
+ const { insertScriptTags } = useInsertScriptTags({
18
+ effectId: "LoginRecoveryAuthnCodeConfig",
19
+ scriptTags: [
20
+ {
21
+ type: "module",
22
+ textContent: () => `
23
+ import { authenticateByWebAuthn } from "${import.meta.env.BASE_URL}keycloak-theme/login/js/webauthnAuthenticate.js";
24
+ import { initAuthenticate } from "${import.meta.env.BASE_URL}keycloak-theme/login/js/passkeysConditionalAuth.js";
25
+
26
+ const authButton = document.getElementById("${webAuthnButtonId}");
27
+ const input = {
28
+ isUserIdentified : ${kcContext.isUserIdentified},
29
+ challenge : ${JSON.stringify(kcContext.challenge)},
30
+ userVerification : ${JSON.stringify(kcContext.userVerification)},
31
+ rpId : ${JSON.stringify(kcContext.rpId)},
32
+ createTimeout : ${kcContext.createTimeout}
33
+ };
34
+ authButton.addEventListener("click", () => {
35
+ authenticateByWebAuthn({
36
+ ...input,
37
+ errmsg : ${JSON.stringify(msgStr("webauthn-unsupported-browser-text"))}
38
+ });
39
+ });
40
+
41
+ initAuthenticate({
42
+ ...input,
43
+ errmsg : ${JSON.stringify(msgStr("passkey-unsupported-browser-text"))}
44
+ });
45
+ `
46
+ }
47
+ ]
48
+ });
49
+
50
+ useEffect(() => {
51
+ if (isFetchingTranslations) {
52
+ return;
53
+ }
54
+
55
+ (async () => {
56
+ await waitForElementMountedOnDom({
57
+ elementId: webAuthnButtonId
58
+ });
59
+
60
+ insertScriptTags();
61
+ })();
62
+ }, [isFetchingTranslations]);
63
+ }