@oussemasahbeni/keycloakify-login-shadcn 250004.0.7 → 250004.0.9

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 (108) hide show
  1. package/keycloak-theme/components/langauges.tsx +1 -1
  2. package/keycloak-theme/components/theme-toggle.tsx +0 -1
  3. package/keycloak-theme/components/ui/alert.tsx +69 -62
  4. package/keycloak-theme/components/ui/button.tsx +44 -39
  5. package/keycloak-theme/components/ui/card.tsx +59 -45
  6. package/keycloak-theme/components/ui/checkbox.tsx +24 -23
  7. package/keycloak-theme/components/ui/dropdown-menu.tsx +233 -168
  8. package/keycloak-theme/components/ui/field.tsx +50 -48
  9. package/keycloak-theme/components/ui/input-otp.tsx +55 -49
  10. package/keycloak-theme/components/ui/input.tsx +18 -22
  11. package/keycloak-theme/components/ui/label.tsx +19 -21
  12. package/keycloak-theme/components/ui/radio-group.tsx +27 -26
  13. package/keycloak-theme/components/ui/select.tsx +169 -122
  14. package/keycloak-theme/components/ui/separator.tsx +23 -24
  15. package/keycloak-theme/components/ui/tooltip.tsx +53 -24
  16. package/keycloak-theme/login/KcPage.tsx +2 -5
  17. package/keycloak-theme/login/components/LogoutOtherSessions.tsx +3 -5
  18. package/keycloak-theme/login/components/PasswordWrapper.tsx +4 -4
  19. package/keycloak-theme/login/components/Template/Template.tsx +110 -58
  20. package/keycloak-theme/login/components/UserProfileFormFields/AddRemoveButtonsMultiValuedAttribute.tsx +7 -3
  21. package/keycloak-theme/login/components/UserProfileFormFields/FieldErrors.tsx +8 -4
  22. package/keycloak-theme/login/components/UserProfileFormFields/GroupLabel.tsx +33 -14
  23. package/keycloak-theme/login/components/UserProfileFormFields/InputFieldByType.tsx +9 -2
  24. package/keycloak-theme/login/components/UserProfileFormFields/InputLabel.tsx +0 -1
  25. package/keycloak-theme/login/components/UserProfileFormFields/InputTag.tsx +25 -8
  26. package/keycloak-theme/login/components/UserProfileFormFields/InputTagSelects.tsx +30 -16
  27. package/keycloak-theme/login/components/UserProfileFormFields/SelectTag.tsx +32 -11
  28. package/keycloak-theme/login/components/UserProfileFormFields/TextareaTag.tsx +19 -7
  29. package/keycloak-theme/login/components/UserProfileFormFields/UserProfileFormFields.tsx +11 -5
  30. package/keycloak-theme/login/index.css +3 -20
  31. package/keycloak-theme/login/mocks/KcPageStory.tsx +6 -2
  32. package/keycloak-theme/login/pages/PageIndex.tsx +0 -4
  33. package/keycloak-theme/login/pages/code/Page.stories.tsx +4 -5
  34. package/keycloak-theme/login/pages/code/Page.tsx +6 -6
  35. package/keycloak-theme/login/pages/delete-account-confirm/Page.stories.tsx +0 -2
  36. package/keycloak-theme/login/pages/delete-account-confirm/Page.tsx +3 -6
  37. package/keycloak-theme/login/pages/delete-credential/Page.stories.tsx +0 -1
  38. package/keycloak-theme/login/pages/delete-credential/Page.tsx +11 -6
  39. package/keycloak-theme/login/pages/error/Page.stories.tsx +0 -1
  40. package/keycloak-theme/login/pages/error/Page.tsx +13 -12
  41. package/keycloak-theme/login/pages/frontchannel-logout/Page.tsx +2 -4
  42. package/keycloak-theme/login/pages/idp-review-user-profile/Page.stories.tsx +0 -1
  43. package/keycloak-theme/login/pages/idp-review-user-profile/Page.tsx +2 -5
  44. package/keycloak-theme/login/pages/info/Page.tsx +8 -6
  45. package/keycloak-theme/login/pages/link-idp-action/Page.tsx +5 -3
  46. package/keycloak-theme/login/pages/login/Form.tsx +36 -38
  47. package/keycloak-theme/login/pages/login/Page.stories.tsx +4 -3
  48. package/keycloak-theme/login/pages/login/Page.tsx +0 -1
  49. package/keycloak-theme/login/pages/login/SocialProviders.tsx +14 -23
  50. package/keycloak-theme/login/pages/login/providers/github.svg +4 -3
  51. package/keycloak-theme/login/pages/login/providers/x.svg +4 -3
  52. package/keycloak-theme/login/pages/login/useProviderLogos.tsx +2 -3
  53. package/keycloak-theme/login/pages/login-config-totp/Page.stories.tsx +0 -1
  54. package/keycloak-theme/login/pages/login-config-totp/Page.tsx +25 -12
  55. package/keycloak-theme/login/pages/login-idp-link-confirm/Page.stories.tsx +0 -1
  56. package/keycloak-theme/login/pages/login-idp-link-confirm/Page.tsx +4 -7
  57. package/keycloak-theme/login/pages/login-idp-link-confirm-override/Page.stories.tsx +0 -1
  58. package/keycloak-theme/login/pages/login-idp-link-confirm-override/Page.tsx +4 -7
  59. package/keycloak-theme/login/pages/login-idp-link-email/Page.stories.tsx +0 -1
  60. package/keycloak-theme/login/pages/login-idp-link-email/Page.tsx +4 -7
  61. package/keycloak-theme/login/pages/login-oauth-grant/Page.tsx +21 -11
  62. package/keycloak-theme/login/pages/login-oauth2-device-verify-user-code/Page.tsx +5 -7
  63. package/keycloak-theme/login/pages/login-otp/Page.stories.tsx +0 -1
  64. package/keycloak-theme/login/pages/login-otp/Page.tsx +35 -26
  65. package/keycloak-theme/login/pages/login-page-expired/Page.stories.tsx +0 -1
  66. package/keycloak-theme/login/pages/login-page-expired/Page.tsx +4 -6
  67. package/keycloak-theme/login/pages/login-passkeys-conditional-authenticate/Page.tsx +153 -96
  68. package/keycloak-theme/login/pages/login-password/Page.tsx +14 -15
  69. package/keycloak-theme/login/pages/login-password/useScript.tsx +0 -1
  70. package/keycloak-theme/login/pages/login-recovery-authn-code-config/Page.tsx +5 -8
  71. package/keycloak-theme/login/pages/login-recovery-authn-code-input/Page.tsx +2 -3
  72. package/keycloak-theme/login/pages/login-reset-otp/Page.stories.tsx +0 -1
  73. package/keycloak-theme/login/pages/login-reset-otp/Page.tsx +3 -4
  74. package/keycloak-theme/login/pages/login-reset-password/Form.tsx +5 -6
  75. package/keycloak-theme/login/pages/login-reset-password/Page.stories.tsx +0 -1
  76. package/keycloak-theme/login/pages/login-reset-password/Page.tsx +3 -3
  77. package/keycloak-theme/login/pages/login-update-password/Page.stories.tsx +0 -1
  78. package/keycloak-theme/login/pages/login-update-password/Page.tsx +5 -7
  79. package/keycloak-theme/login/pages/login-update-profile/Page.stories.tsx +0 -1
  80. package/keycloak-theme/login/pages/login-update-profile/Page.tsx +6 -7
  81. package/keycloak-theme/login/pages/login-username/Page.stories.tsx +0 -1
  82. package/keycloak-theme/login/pages/login-username/Page.tsx +6 -6
  83. package/keycloak-theme/login/pages/login-verify-email/Page.stories.tsx +0 -1
  84. package/keycloak-theme/login/pages/login-verify-email/Page.tsx +3 -4
  85. package/keycloak-theme/login/pages/login-x509-info/Page.stories.tsx +0 -1
  86. package/keycloak-theme/login/pages/login-x509-info/Page.tsx +3 -6
  87. package/keycloak-theme/login/pages/logout-confirm/Page.stories.tsx +0 -1
  88. package/keycloak-theme/login/pages/logout-confirm/Page.tsx +3 -6
  89. package/keycloak-theme/login/pages/register/Form.tsx +8 -7
  90. package/keycloak-theme/login/pages/register/Page.stories.tsx +17 -8
  91. package/keycloak-theme/login/pages/register/TermsAcceptance.tsx +6 -7
  92. package/keycloak-theme/login/pages/saml-post-form/Page.stories.tsx +0 -1
  93. package/keycloak-theme/login/pages/saml-post-form/Page.tsx +4 -6
  94. package/keycloak-theme/login/pages/select-authenticator/Page.stories.tsx +0 -1
  95. package/keycloak-theme/login/pages/select-authenticator/Page.tsx +3 -6
  96. package/keycloak-theme/login/pages/select-organization/Page.tsx +5 -8
  97. package/keycloak-theme/login/pages/terms/Page.tsx +1 -3
  98. package/keycloak-theme/login/pages/update-email/Page.stories.tsx +0 -1
  99. package/keycloak-theme/login/pages/update-email/Page.tsx +6 -7
  100. package/keycloak-theme/login/pages/webauthn-authenticate/Page.stories.tsx +0 -1
  101. package/keycloak-theme/login/pages/webauthn-authenticate/Page.tsx +50 -46
  102. package/keycloak-theme/login/pages/webauthn-error/Page.stories.tsx +2 -5
  103. package/keycloak-theme/login/pages/webauthn-error/Page.tsx +3 -6
  104. package/keycloak-theme/login/pages/webauthn-register/Page.stories.tsx +0 -1
  105. package/keycloak-theme/login/pages/webauthn-register/Page.tsx +4 -4
  106. package/keycloak-theme/login/styleLevelCustomization.tsx +5 -6
  107. package/keycloak-theme/public/site.webmanifest +11 -1
  108. package/package.json +2 -2
@@ -1,8 +1,8 @@
1
1
  import { Button } from "@/components/ui/button";
2
2
  import { CardDescription } from "@/components/ui/card";
3
- import { useI18n } from '@/login/i18n';
4
- import { useKcContext } from '@/login/KcContext';
5
- import { assert } from 'tsafe/assert';
3
+ import { useI18n } from "@/login/i18n";
4
+ import { useKcContext } from "@/login/KcContext";
5
+ import { assert } from "tsafe/assert";
6
6
  import { Template } from "../../components/Template";
7
7
 
8
8
  export function Page() {
@@ -11,7 +11,6 @@ export function Page() {
11
11
 
12
12
  const { msg, msgStr, advancedMsg, advancedMsgStr } = useI18n();
13
13
 
14
-
15
14
  return (
16
15
  <Template
17
16
  bodyClassName="oauth"
@@ -26,7 +25,10 @@ export function Page() {
26
25
  )}
27
26
  <p className="text-lg font-medium text-center">
28
27
  {kcContext.client.name
29
- ? msg("oauthGrantTitle", advancedMsgStr(kcContext.client.name))
28
+ ? msg(
29
+ "oauthGrantTitle",
30
+ advancedMsgStr(kcContext.client.name)
31
+ )
30
32
  : msg("oauthGrantTitle", kcContext.client.clientId)}
31
33
  </p>
32
34
  </div>
@@ -58,16 +60,20 @@ export function Page() {
58
60
  ))}
59
61
  </div>
60
62
 
61
- {(kcContext.client.attributes.policyUri || kcContext.client.attributes.tosUri) && (
63
+ {(kcContext.client.attributes.policyUri ||
64
+ kcContext.client.attributes.tosUri) && (
62
65
  <>
63
66
  <div className="space-y-2">
64
67
  <CardDescription className="text-xs">
65
68
  {kcContext.client.name
66
69
  ? msg(
67
- "oauthGrantInformation",
68
- advancedMsgStr(kcContext.client.name)
69
- )
70
- : msg("oauthGrantInformation", kcContext.client.clientId)}
70
+ "oauthGrantInformation",
71
+ advancedMsgStr(kcContext.client.name)
72
+ )
73
+ : msg(
74
+ "oauthGrantInformation",
75
+ kcContext.client.clientId
76
+ )}
71
77
  </CardDescription>
72
78
  <div className="flex flex-wrap gap-2 text-xs">
73
79
  {kcContext.client.attributes.tosUri && (
@@ -97,7 +103,11 @@ export function Page() {
97
103
  </div>
98
104
 
99
105
  <div>
100
- <form className="w-full" action={kcContext.url.oauthAction} method="POST">
106
+ <form
107
+ className="w-full"
108
+ action={kcContext.url.oauthAction}
109
+ method="POST"
110
+ >
101
111
  <input type="hidden" name="code" value={kcContext.oauth.code} />
102
112
  <div className="flex flex-col sm:flex-row gap-3 w-full">
103
113
  <Button
@@ -1,10 +1,10 @@
1
1
  import { Button } from "@/components/ui/button";
2
2
  import { Field, FieldLabel } from "@/components/ui/field";
3
3
  import { Input } from "@/components/ui/input";
4
- import { useI18n } from '@/login/i18n';
5
- import { useKcContext } from '@/login/KcContext';
6
- import { useKcClsx } from '@keycloakify/login-ui/useKcClsx';
7
- import { assert } from 'tsafe/assert';
4
+ import { useI18n } from "@/login/i18n";
5
+ import { useKcContext } from "@/login/KcContext";
6
+ import { useKcClsx } from "@keycloakify/login-ui/useKcClsx";
7
+ import { assert } from "tsafe/assert";
8
8
  import { Template } from "../../components/Template";
9
9
 
10
10
  export function Page() {
@@ -16,9 +16,7 @@ export function Page() {
16
16
  const { kcClsx } = useKcClsx();
17
17
 
18
18
  return (
19
- <Template
20
- headerNode={msg("oauth2DeviceVerificationTitle")}
21
- >
19
+ <Template headerNode={msg("oauth2DeviceVerificationTitle")}>
22
20
  <form
23
21
  id="kc-user-verify-device-user-code-form"
24
22
  className="space-y-5"
@@ -1,6 +1,5 @@
1
1
  import { createKcPageStory, type Meta, type StoryObj } from "../../mocks/KcPageStory";
2
2
 
3
-
4
3
  const { KcPageStory } = createKcPageStory({ pageId: "login-otp.ftl" });
5
4
 
6
5
  const meta = {
@@ -1,19 +1,18 @@
1
1
  import { Button } from "@/components/ui/button";
2
- import { FieldError } from '@/components/ui/field';
2
+ import { FieldError } from "@/components/ui/field";
3
3
  import { InputOTP, InputOTPGroup, InputOTPSlot } from "@/components/ui/input-otp";
4
4
  import { Label } from "@/components/ui/label";
5
5
  import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
6
- import { useI18n } from '@/login/i18n';
7
- import { useKcContext } from '@/login/KcContext';
6
+ import { useI18n } from "@/login/i18n";
7
+ import { useKcContext } from "@/login/KcContext";
8
8
  import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp";
9
9
  import { kcSanitize } from "keycloakify/lib/kcSanitize";
10
- import { useState } from 'react';
10
+ import { useState } from "react";
11
11
  import { MdOutlineDevices } from "react-icons/md";
12
12
  import { assert } from "tsafe/assert";
13
13
  import { Template } from "../../components/Template";
14
14
 
15
15
  export function Page() {
16
-
17
16
  const { kcContext } = useKcContext();
18
17
 
19
18
  assert(kcContext.pageId === "login-otp.ftl");
@@ -43,26 +42,28 @@ export function Page() {
43
42
  defaultValue={kcContext.otpLogin.selectedCredentialId}
44
43
  className="space-y-2"
45
44
  >
46
- {kcContext.otpLogin.userOtpCredentials.map((otpCredential, index) => (
47
- <div
48
- key={otpCredential.id}
49
- className="flex items-center space-x-3 p-3 border rounded-lg"
50
- >
51
- <RadioGroupItem
52
- value={otpCredential.id}
53
- id={`kc-otp-credential-${index}`}
54
- />
55
- <Label
56
- htmlFor={`kc-otp-credential-${index}`}
57
- className="flex items-center space-x-2 cursor-pointer flex-1"
45
+ {kcContext.otpLogin.userOtpCredentials.map(
46
+ (otpCredential, index) => (
47
+ <div
48
+ key={otpCredential.id}
49
+ className="flex items-center space-x-3 p-3 border rounded-lg"
58
50
  >
59
- <MdOutlineDevices />
60
- <span className="text-sm font-medium">
61
- {otpCredential.userLabel}
62
- </span>
63
- </Label>
64
- </div>
65
- ))}
51
+ <RadioGroupItem
52
+ value={otpCredential.id}
53
+ id={`kc-otp-credential-${index}`}
54
+ />
55
+ <Label
56
+ htmlFor={`kc-otp-credential-${index}`}
57
+ className="flex items-center space-x-2 cursor-pointer flex-1"
58
+ >
59
+ <MdOutlineDevices />
60
+ <span className="text-sm font-medium">
61
+ {otpCredential.userLabel}
62
+ </span>
63
+ </Label>
64
+ </div>
65
+ )
66
+ )}
66
67
  </RadioGroup>
67
68
  </div>
68
69
  )}
@@ -92,14 +93,22 @@ export function Page() {
92
93
  <FieldError id="input-error-otp-code">
93
94
  <span
94
95
  dangerouslySetInnerHTML={{
95
- __html: kcSanitize(kcContext.messagesPerField.get("totp"))
96
+ __html: kcSanitize(
97
+ kcContext.messagesPerField.get("totp")
98
+ )
96
99
  }}
97
100
  />
98
101
  </FieldError>
99
102
  )}
100
103
  </div>
101
104
 
102
- <Button className="w-full" name="login" id="kc-login" type="submit" disabled={isSubmitting}>
105
+ <Button
106
+ className="w-full"
107
+ name="login"
108
+ id="kc-login"
109
+ type="submit"
110
+ disabled={isSubmitting}
111
+ >
103
112
  {msgStr("doLogIn")}
104
113
  </Button>
105
114
  </form>
@@ -1,6 +1,5 @@
1
1
  import { createKcPageStory, type Meta, type StoryObj } from "../../mocks/KcPageStory";
2
2
 
3
-
4
3
  const { KcPageStory } = createKcPageStory({ pageId: "login-page-expired.ftl" });
5
4
 
6
5
  const meta = {
@@ -1,7 +1,7 @@
1
1
  import { Alert, AlertDescription } from "@/components/ui/alert";
2
- import { useI18n } from '@/login/i18n';
3
- import { useKcContext } from '@/login/KcContext';
4
- import { assert } from 'tsafe/assert';
2
+ import { useI18n } from "@/login/i18n";
3
+ import { useKcContext } from "@/login/KcContext";
4
+ import { assert } from "tsafe/assert";
5
5
  import { Template } from "../../components/Template";
6
6
 
7
7
  export function Page() {
@@ -11,9 +11,7 @@ export function Page() {
11
11
  const { msg } = useI18n();
12
12
 
13
13
  return (
14
- <Template
15
- headerNode={msg("pageExpiredTitle")}
16
- >
14
+ <Template headerNode={msg("pageExpiredTitle")}>
17
15
  <Alert variant="warning" className="my-6">
18
16
  <AlertDescription>
19
17
  <div className="space-y-3 text-sm leading-relaxed">
@@ -57,110 +57,158 @@ export function Page() {
57
57
  </form>
58
58
 
59
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")}
60
+ {authenticators !== undefined &&
61
+ Object.keys(authenticators).length !== 0 && (
62
+ <>
63
+ <form id="authn_select" className={kcClsx("kcFormClass")}>
64
+ {authenticators.authenticators.map((authenticator, i) => (
65
+ <input
66
+ key={i}
67
+ type="hidden"
68
+ name="authn_use_chk"
69
+ readOnly
70
+ value={authenticator.credentialId}
71
+ />
72
+ ))}
73
+ </form>
74
+ {shouldDisplayAuthenticators && (
75
+ <>
76
+ {authenticators.authenticators.length > 1 && (
77
+ <p
78
+ className={kcClsx(
79
+ "kcSelectAuthListItemTitle"
80
+ )}
86
81
  >
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")}>
82
+ {msg("passkey-available-authenticators")}
83
+ </p>
84
+ )}
85
+ <div className={kcClsx("kcFormClass")}>
86
+ {authenticators.authenticators.map(
87
+ (authenticator, i) => (
105
88
  <div
106
- id={`kc-webauthn-authenticator-label-${i}`}
89
+ key={i}
90
+ id={`kc-webauthn-authenticator-item-${i}`}
107
91
  className={kcClsx(
108
- "kcSelectAuthListItemHeadingClass"
92
+ "kcSelectAuthListItemClass"
109
93
  )}
110
94
  >
111
- {advancedMsg(authenticator.label)}
112
- </div>
113
- {authenticator.transports !== undefined &&
114
- authenticator.transports.displayNameProperties !==
115
- undefined &&
116
- authenticator.transports.displayNameProperties
117
- .length !== 0 && (
95
+ <i
96
+ className={clsx(
97
+ (() => {
98
+ const className = kcClsx(
99
+ authenticator
100
+ .transports
101
+ .iconClass as any
102
+ );
103
+ if (
104
+ className ===
105
+ authenticator
106
+ .transports
107
+ .iconClass
108
+ ) {
109
+ return kcClsx(
110
+ "kcWebAuthnDefaultIcon"
111
+ );
112
+ }
113
+ return className;
114
+ })(),
115
+ kcClsx(
116
+ "kcSelectAuthListItemIconPropertyClass"
117
+ )
118
+ )}
119
+ />
120
+ <div
121
+ className={kcClsx(
122
+ "kcSelectAuthListItemBodyClass"
123
+ )}
124
+ >
118
125
  <div
119
- id={`kc-webauthn-authenticator-transport-${i}`}
126
+ id={`kc-webauthn-authenticator-label-${i}`}
120
127
  className={kcClsx(
121
- "kcSelectAuthListItemDescriptionClass"
128
+ "kcSelectAuthListItemHeadingClass"
122
129
  )}
123
130
  >
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
- )
131
+ {advancedMsg(
132
+ authenticator.label
138
133
  )}
139
134
  </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>
135
+ {authenticator.transports !==
136
+ undefined &&
137
+ authenticator.transports
138
+ .displayNameProperties !==
139
+ undefined &&
140
+ authenticator.transports
141
+ .displayNameProperties
142
+ .length !== 0 && (
143
+ <div
144
+ id={`kc-webauthn-authenticator-transport-${i}`}
145
+ className={kcClsx(
146
+ "kcSelectAuthListItemDescriptionClass"
147
+ )}
148
+ >
149
+ {authenticator.transports.displayNameProperties.map(
150
+ (
151
+ nameProperty,
152
+ i,
153
+ arr
154
+ ) => (
155
+ <Fragment
156
+ key={i}
157
+ >
158
+ <span
159
+ key={
160
+ i
161
+ }
162
+ >
163
+ {" "}
164
+ {advancedMsg(
165
+ nameProperty
166
+ )}{" "}
167
+ </span>
168
+ {i !==
169
+ arr.length -
170
+ 1 && (
171
+ <span>
172
+ ,{" "}
173
+ </span>
174
+ )}
175
+ </Fragment>
176
+ )
177
+ )}
178
+ </div>
179
+ )}
180
+ <div
181
+ className={kcClsx(
182
+ "kcSelectAuthListItemDescriptionClass"
183
+ )}
184
+ >
185
+ <span
186
+ id={`kc-webauthn-authenticator-createdlabel-${i}`}
187
+ >
188
+ {msg(
189
+ "passkey-createdAt-label"
190
+ )}
191
+ </span>
192
+ <span
193
+ id={`kc-webauthn-authenticator-created-${i}`}
194
+ >
195
+ {authenticator.createdAt}
196
+ </span>
197
+ </div>
198
+ </div>
199
+ <div
200
+ className={kcClsx(
201
+ "kcSelectAuthListItemFillClass"
202
+ )}
203
+ />
154
204
  </div>
155
- </div>
156
- <div className={kcClsx("kcSelectAuthListItemFillClass")} />
157
- </div>
158
- ))}
159
- </div>
160
- </>
161
- )}
162
- </>
163
- )}
205
+ )
206
+ )}
207
+ </div>
208
+ </>
209
+ )}
210
+ </>
211
+ )}
164
212
  <div id="kc-form">
165
213
  <div id="kc-form-wrapper">
166
214
  {realm.password && (
@@ -173,20 +221,27 @@ export function Page() {
173
221
  try {
174
222
  // @ts-expect-error: Ok
175
223
  event.target.login.disabled = true;
176
- } catch { /* empty */ }
224
+ } catch {
225
+ /* empty */
226
+ }
177
227
 
178
228
  return true;
179
229
  }}
180
230
  >
181
231
  {!usernameHidden && (
182
232
  <div className={kcClsx("kcFormGroupClass")}>
183
- <label htmlFor="username" className={kcClsx("kcLabelClass")}>
233
+ <label
234
+ htmlFor="username"
235
+ className={kcClsx("kcLabelClass")}
236
+ >
184
237
  {msg("passkey-autofill-select")}
185
238
  </label>
186
239
  <input
187
240
  tabIndex={1}
188
241
  id="username"
189
- aria-invalid={messagesPerField.existsError("username")}
242
+ aria-invalid={messagesPerField.existsError(
243
+ "username"
244
+ )}
190
245
  className={kcClsx("kcInputClass")}
191
246
  name="username"
192
247
  defaultValue={login.username ?? ""}
@@ -197,7 +252,9 @@ export function Page() {
197
252
  {messagesPerField.existsError("username") && (
198
253
  <span
199
254
  id="input-error-username"
200
- className={kcClsx("kcInputErrorMessageClass")}
255
+ className={kcClsx(
256
+ "kcInputErrorMessageClass"
257
+ )}
201
258
  aria-live="polite"
202
259
  >
203
260
  {messagesPerField.get("username")}
@@ -1,17 +1,17 @@
1
1
  import { Button } from "@/components/ui/button";
2
2
  import { Field, FieldError, FieldLabel } from "@/components/ui/field";
3
3
  import { Input } from "@/components/ui/input";
4
- import { Label } from '@/components/ui/label';
5
- import { PasswordWrapper } from '@/login/components/PasswordWrapper';
6
- import { useI18n } from '@/login/i18n';
7
- import { useKcContext } from '@/login/KcContext';
8
- import { useKcClsx } from '@keycloakify/login-ui/useKcClsx';
4
+ import { Label } from "@/components/ui/label";
5
+ import { PasswordWrapper } from "@/login/components/PasswordWrapper";
6
+ import { useI18n } from "@/login/i18n";
7
+ import { useKcContext } from "@/login/KcContext";
8
+ import { useKcClsx } from "@keycloakify/login-ui/useKcClsx";
9
9
  import { kcSanitize } from "keycloakify/lib/kcSanitize";
10
10
  import { Fingerprint } from "lucide-react";
11
11
  import { useState } from "react";
12
12
  import { assert } from "tsafe/assert";
13
13
  import { Template } from "../../components/Template";
14
- import { useScript } from './useScript';
14
+ import { useScript } from "./useScript";
15
15
 
16
16
  export function Page() {
17
17
  const { kcContext } = useKcContext();
@@ -44,16 +44,16 @@ export function Page() {
44
44
  >
45
45
  <Field>
46
46
  <FieldLabel htmlFor="password">{msg("password")}</FieldLabel>
47
- <PasswordWrapper
48
- passwordInputId="password"
49
- >
47
+ <PasswordWrapper passwordInputId="password">
50
48
  <Input
51
49
  tabIndex={2}
52
50
  type="password"
53
51
  id="password"
54
52
  name="password"
55
53
  autoComplete="current-password"
56
- aria-invalid={kcContext.messagesPerField.existsError("password")}
54
+ aria-invalid={kcContext.messagesPerField.existsError(
55
+ "password"
56
+ )}
57
57
  />
58
58
  </PasswordWrapper>
59
59
  {kcContext.messagesPerField.existsError("password") && (
@@ -63,7 +63,9 @@ export function Page() {
63
63
  aria-live="polite"
64
64
  dangerouslySetInnerHTML={{
65
65
  __html: kcSanitize(
66
- kcContext.messagesPerField.getFirstError("password")
66
+ kcContext.messagesPerField.getFirstError(
67
+ "password"
68
+ )
67
69
  )
68
70
  }}
69
71
  />
@@ -74,10 +76,7 @@ export function Page() {
74
76
  <div className="flex justify-end">
75
77
  {kcContext.realm.resetPasswordAllowed && (
76
78
  <span className=" underline-offset-4 hover:underline">
77
- <a
78
- tabIndex={5}
79
- href={kcContext.url.loginResetCredentialsUrl}
80
- >
79
+ <a tabIndex={5} href={kcContext.url.loginResetCredentialsUrl}>
81
80
  <Label className="text-sm font-medium cursor-pointer">
82
81
  {msg("doForgotPassword")}
83
82
  </Label>
@@ -1,4 +1,3 @@
1
-
2
1
  import { useInsertScriptTags } from "@keycloakify/login-ui/tools/useInsertScriptTags";
3
2
  import { waitForElementMountedOnDom } from "@keycloakify/login-ui/tools/waitForElementMountedOnDom";
4
3
  import { useEffect } from "react";