keycloakify 6.8.3 → 6.8.4

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 (65) hide show
  1. package/README.md +4 -0
  2. package/lib/components/IdpReviewUserProfile.js +7 -8
  3. package/lib/components/IdpReviewUserProfile.js.map +1 -1
  4. package/lib/components/Login.js +16 -17
  5. package/lib/components/Login.js.map +1 -1
  6. package/lib/components/LoginConfigTotp.js +17 -18
  7. package/lib/components/LoginConfigTotp.js.map +1 -1
  8. package/lib/components/LoginIdpLinkConfirm.js +4 -5
  9. package/lib/components/LoginIdpLinkConfirm.js.map +1 -1
  10. package/lib/components/LoginOtp.js +17 -18
  11. package/lib/components/LoginOtp.js.map +1 -1
  12. package/lib/components/LoginPassword.js +8 -9
  13. package/lib/components/LoginPassword.js.map +1 -1
  14. package/lib/components/LoginResetPassword.js +12 -13
  15. package/lib/components/LoginResetPassword.js.map +1 -1
  16. package/lib/components/LoginUpdatePassword.js +18 -19
  17. package/lib/components/LoginUpdatePassword.js.map +1 -1
  18. package/lib/components/LoginUpdateProfile.js +28 -29
  19. package/lib/components/LoginUpdateProfile.js.map +1 -1
  20. package/lib/components/LoginUsername.js +12 -13
  21. package/lib/components/LoginUsername.js.map +1 -1
  22. package/lib/components/LogoutConfirm.js +5 -6
  23. package/lib/components/LogoutConfirm.js.map +1 -1
  24. package/lib/components/Register.js +38 -39
  25. package/lib/components/Register.js.map +1 -1
  26. package/lib/components/RegisterUserProfile.js +10 -12
  27. package/lib/components/RegisterUserProfile.js.map +1 -1
  28. package/lib/components/Template.js +26 -27
  29. package/lib/components/Template.js.map +1 -1
  30. package/lib/components/Terms.js +3 -4
  31. package/lib/components/Terms.js.map +1 -1
  32. package/lib/components/UpdateUserProfile.js +8 -9
  33. package/lib/components/UpdateUserProfile.js.map +1 -1
  34. package/lib/components/WebauthnAuthenticate.js +16 -17
  35. package/lib/components/WebauthnAuthenticate.js.map +1 -1
  36. package/lib/components/shared/UserProfileCommons.js +19 -15
  37. package/lib/components/shared/UserProfileCommons.js.map +1 -1
  38. package/lib/tools/clsx.d.ts +3 -0
  39. package/lib/tools/clsx.js +6 -0
  40. package/lib/tools/clsx.js.map +1 -0
  41. package/lib/tools/useCssAndCx.d.ts +7 -1
  42. package/lib/tools/useCssAndCx.js +9 -6
  43. package/lib/tools/useCssAndCx.js.map +1 -1
  44. package/lib/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +7 -4
  46. package/src/lib/components/IdpReviewUserProfile.tsx +7 -9
  47. package/src/lib/components/Login.tsx +17 -19
  48. package/src/lib/components/LoginConfigTotp.tsx +17 -19
  49. package/src/lib/components/LoginIdpLinkConfirm.tsx +4 -6
  50. package/src/lib/components/LoginOtp.tsx +18 -20
  51. package/src/lib/components/LoginPassword.tsx +8 -10
  52. package/src/lib/components/LoginResetPassword.tsx +12 -14
  53. package/src/lib/components/LoginUpdatePassword.tsx +21 -21
  54. package/src/lib/components/LoginUpdateProfile.tsx +29 -31
  55. package/src/lib/components/LoginUsername.tsx +13 -15
  56. package/src/lib/components/LogoutConfirm.tsx +5 -7
  57. package/src/lib/components/Register.tsx +40 -40
  58. package/src/lib/components/RegisterUserProfile.tsx +10 -20
  59. package/src/lib/components/Template.tsx +26 -28
  60. package/src/lib/components/Terms.tsx +3 -5
  61. package/src/lib/components/UpdateUserProfile.tsx +9 -11
  62. package/src/lib/components/WebauthnAuthenticate.tsx +16 -18
  63. package/src/lib/components/shared/UserProfileCommons.tsx +30 -27
  64. package/src/lib/tools/clsx.ts +7 -0
  65. package/src/lib/tools/useCssAndCx.ts +9 -8
@@ -1,9 +1,9 @@
1
- import React, { useMemo, memo, useState } from "react";
1
+ import React, { memo, useState } from "react";
2
2
  import DefaultTemplate from "./Template";
3
3
  import type { TemplateProps } from "./Template";
4
4
  import type { KcProps } from "./KcProps";
5
5
  import type { KcContextBase } from "../getKcContext/KcContextBase";
6
- import { useCssAndCx } from "../tools/useCssAndCx";
6
+ import { clsx } from "../tools/clsx";
7
7
  import type { I18n } from "../i18n";
8
8
  import { UserProfileFormFields } from "./shared/UserProfileCommons";
9
9
 
@@ -15,22 +15,12 @@ export type RegisterUserProfileProps = KcProps & {
15
15
  };
16
16
 
17
17
  const RegisterUserProfile = memo((props: RegisterUserProfileProps) => {
18
- const { kcContext, i18n, doFetchDefaultThemeResources = true, Template = DefaultTemplate, ...kcProps_ } = props;
18
+ const { kcContext, i18n, doFetchDefaultThemeResources = true, Template = DefaultTemplate, ...kcProps } = props;
19
19
 
20
20
  const { url, messagesPerField, recaptchaRequired, recaptchaSiteKey } = kcContext;
21
21
 
22
22
  const { msg, msgStr } = i18n;
23
23
 
24
- const { cx, css } = useCssAndCx();
25
-
26
- const kcProps = useMemo(
27
- () => ({
28
- ...kcProps_,
29
- "kcFormGroupClass": cx(kcProps_.kcFormGroupClass, css({ "marginBottom": 20 }))
30
- }),
31
- [cx, css]
32
- );
33
-
34
24
  const [isFomSubmittable, setIsFomSubmittable] = useState(false);
35
25
 
36
26
  return (
@@ -40,27 +30,27 @@ const RegisterUserProfile = memo((props: RegisterUserProfileProps) => {
40
30
  displayRequiredFields={true}
41
31
  headerNode={msg("registerTitle")}
42
32
  formNode={
43
- <form id="kc-register-form" className={cx(kcProps.kcFormClass)} action={url.registrationAction} method="post">
33
+ <form id="kc-register-form" className={clsx(kcProps.kcFormClass)} action={url.registrationAction} method="post">
44
34
  <UserProfileFormFields kcContext={kcContext} onIsFormSubmittableValueChange={setIsFomSubmittable} i18n={i18n} {...kcProps} />
45
35
  {recaptchaRequired && (
46
36
  <div className="form-group">
47
- <div className={cx(kcProps.kcInputWrapperClass)}>
37
+ <div className={clsx(kcProps.kcInputWrapperClass)}>
48
38
  <div className="g-recaptcha" data-size="compact" data-sitekey={recaptchaSiteKey} />
49
39
  </div>
50
40
  </div>
51
41
  )}
52
- <div className={cx(kcProps.kcFormGroupClass)}>
53
- <div id="kc-form-options" className={cx(kcProps.kcFormOptionsClass)}>
54
- <div className={cx(kcProps.kcFormOptionsWrapperClass)}>
42
+ <div className={clsx(kcProps.kcFormGroupClass)} style={{ "marginBottom": 30 }}>
43
+ <div id="kc-form-options" className={clsx(kcProps.kcFormOptionsClass)}>
44
+ <div className={clsx(kcProps.kcFormOptionsWrapperClass)}>
55
45
  <span>
56
46
  <a href={url.loginUrl}>{msg("backToLogin")}</a>
57
47
  </span>
58
48
  </div>
59
49
  </div>
60
50
 
61
- <div id="kc-form-buttons" className={cx(kcProps.kcFormButtonsClass)}>
51
+ <div id="kc-form-buttons" className={clsx(kcProps.kcFormButtonsClass)}>
62
52
  <input
63
- className={cx(
53
+ className={clsx(
64
54
  kcProps.kcButtonClass,
65
55
  kcProps.kcButtonPrimaryClass,
66
56
  kcProps.kcButtonBlockClass,
@@ -7,7 +7,7 @@ import { headInsert } from "../tools/headInsert";
7
7
  import { pathJoin } from "../../bin/tools/pathJoin";
8
8
  import { useConstCallback } from "powerhooks/useConstCallback";
9
9
  import type { KcTemplateProps } from "./KcProps";
10
- import { useCssAndCx } from "../tools/useCssAndCx";
10
+ import { clsx } from "../tools/clsx";
11
11
  import type { I18n } from "../i18n";
12
12
 
13
13
  export type TemplateProps = {
@@ -42,8 +42,6 @@ const Template = memo((props: TemplateProps) => {
42
42
  doFetchDefaultThemeResources
43
43
  } = props;
44
44
 
45
- const { cx } = useCssAndCx();
46
-
47
45
  const { msg, changeLocale, labelBySupportedLanguageTag, currentLanguageTag } = i18n;
48
46
 
49
47
  const onChangeLanguageClickFactory = useCallbackFactory(([kcLanguageTag]: [string]) => changeLocale(kcLanguageTag));
@@ -96,7 +94,7 @@ const Template = memo((props: TemplateProps) => {
96
94
  if (props.kcHtmlClass !== undefined) {
97
95
  const htmlClassList = document.getElementsByTagName("html")[0].classList;
98
96
 
99
- const tokens = cx(props.kcHtmlClass).split(" ");
97
+ const tokens = clsx(props.kcHtmlClass).split(" ");
100
98
 
101
99
  htmlClassList.add(...tokens);
102
100
 
@@ -115,18 +113,18 @@ const Template = memo((props: TemplateProps) => {
115
113
  }
116
114
 
117
115
  return (
118
- <div className={cx(props.kcLoginClass)}>
119
- <div id="kc-header" className={cx(props.kcHeaderClass)}>
120
- <div id="kc-header-wrapper" className={cx(props.kcHeaderWrapperClass)}>
116
+ <div className={clsx(props.kcLoginClass)}>
117
+ <div id="kc-header" className={clsx(props.kcHeaderClass)}>
118
+ <div id="kc-header-wrapper" className={clsx(props.kcHeaderWrapperClass)}>
121
119
  {msg("loginTitleHtml", realm.displayNameHtml)}
122
120
  </div>
123
121
  </div>
124
122
 
125
- <div className={cx(props.kcFormCardClass, displayWide && props.kcFormCardAccountClass)}>
126
- <header className={cx(props.kcFormHeaderClass)}>
123
+ <div className={clsx(props.kcFormCardClass, displayWide && props.kcFormCardAccountClass)}>
124
+ <header className={clsx(props.kcFormHeaderClass)}>
127
125
  {realm.internationalizationEnabled && (assert(locale !== undefined), true) && locale.supported.length > 1 && (
128
126
  <div id="kc-locale">
129
- <div id="kc-locale-wrapper" className={cx(props.kcLocaleWrapperClass)}>
127
+ <div id="kc-locale-wrapper" className={clsx(props.kcLocaleWrapperClass)}>
130
128
  <div className="kc-dropdown" id="kc-locale-dropdown">
131
129
  <a href="#" id="kc-current-locale-link">
132
130
  {labelBySupportedLanguageTag[currentLanguageTag]}
@@ -146,8 +144,8 @@ const Template = memo((props: TemplateProps) => {
146
144
  )}
147
145
  {!(auth !== undefined && auth.showUsername && !auth.showResetCredentials) ? (
148
146
  displayRequiredFields ? (
149
- <div className={cx(props.kcContentWrapperClass)}>
150
- <div className={cx(props.kcLabelWrapperClass, "subtitle")}>
147
+ <div className={clsx(props.kcContentWrapperClass)}>
148
+ <div className={clsx(props.kcLabelWrapperClass, "subtitle")}>
151
149
  <span className="subtitle">
152
150
  <span className="required">*</span>
153
151
  {msg("requiredFields")}
@@ -161,20 +159,20 @@ const Template = memo((props: TemplateProps) => {
161
159
  <h1 id="kc-page-title">{headerNode}</h1>
162
160
  )
163
161
  ) : displayRequiredFields ? (
164
- <div className={cx(props.kcContentWrapperClass)}>
165
- <div className={cx(props.kcLabelWrapperClass, "subtitle")}>
162
+ <div className={clsx(props.kcContentWrapperClass)}>
163
+ <div className={clsx(props.kcLabelWrapperClass, "subtitle")}>
166
164
  <span className="subtitle">
167
165
  <span className="required">*</span> {msg("requiredFields")}
168
166
  </span>
169
167
  </div>
170
168
  <div className="col-md-10">
171
169
  {showUsernameNode}
172
- <div className={cx(props.kcFormGroupClass)}>
170
+ <div className={clsx(props.kcFormGroupClass)}>
173
171
  <div id="kc-username">
174
172
  <label id="kc-attempted-username">{auth?.attemptedUsername}</label>
175
173
  <a id="reset-login" href={url.loginRestartFlowUrl}>
176
174
  <div className="kc-login-tooltip">
177
- <i className={cx(props.kcResetFlowIcon)}></i>
175
+ <i className={clsx(props.kcResetFlowIcon)}></i>
178
176
  <span className="kc-tooltip-text">{msg("restartLoginTooltip")}</span>
179
177
  </div>
180
178
  </a>
@@ -185,12 +183,12 @@ const Template = memo((props: TemplateProps) => {
185
183
  ) : (
186
184
  <>
187
185
  {showUsernameNode}
188
- <div className={cx(props.kcFormGroupClass)}>
186
+ <div className={clsx(props.kcFormGroupClass)}>
189
187
  <div id="kc-username">
190
188
  <label id="kc-attempted-username">{auth?.attemptedUsername}</label>
191
189
  <a id="reset-login" href={url.loginRestartFlowUrl}>
192
190
  <div className="kc-login-tooltip">
193
- <i className={cx(props.kcResetFlowIcon)}></i>
191
+ <i className={clsx(props.kcResetFlowIcon)}></i>
194
192
  <span className="kc-tooltip-text">{msg("restartLoginTooltip")}</span>
195
193
  </div>
196
194
  </a>
@@ -203,11 +201,11 @@ const Template = memo((props: TemplateProps) => {
203
201
  <div id="kc-content-wrapper">
204
202
  {/* App-initiated actions should not see warning messages about the need to complete the action during login. */}
205
203
  {displayMessage && message !== undefined && (message.type !== "warning" || !isAppInitiatedAction) && (
206
- <div className={cx("alert", `alert-${message.type}`)}>
207
- {message.type === "success" && <span className={cx(props.kcFeedbackSuccessIcon)}></span>}
208
- {message.type === "warning" && <span className={cx(props.kcFeedbackWarningIcon)}></span>}
209
- {message.type === "error" && <span className={cx(props.kcFeedbackErrorIcon)}></span>}
210
- {message.type === "info" && <span className={cx(props.kcFeedbackInfoIcon)}></span>}
204
+ <div className={clsx("alert", `alert-${message.type}`)}>
205
+ {message.type === "success" && <span className={clsx(props.kcFeedbackSuccessIcon)}></span>}
206
+ {message.type === "warning" && <span className={clsx(props.kcFeedbackWarningIcon)}></span>}
207
+ {message.type === "error" && <span className={clsx(props.kcFeedbackErrorIcon)}></span>}
208
+ {message.type === "info" && <span className={clsx(props.kcFeedbackInfoIcon)}></span>}
211
209
  <span
212
210
  className="kc-feedback-text"
213
211
  dangerouslySetInnerHTML={{
@@ -222,10 +220,10 @@ const Template = memo((props: TemplateProps) => {
222
220
  id="kc-select-try-another-way-form"
223
221
  action={url.loginAction}
224
222
  method="post"
225
- className={cx(displayWide && props.kcContentWrapperClass)}
223
+ className={clsx(displayWide && props.kcContentWrapperClass)}
226
224
  >
227
- <div className={cx(displayWide && [props.kcFormSocialAccountContentClass, props.kcFormSocialAccountClass])}>
228
- <div className={cx(props.kcFormGroupClass)}>
225
+ <div className={clsx(displayWide && [props.kcFormSocialAccountContentClass, props.kcFormSocialAccountClass])}>
226
+ <div className={clsx(props.kcFormGroupClass)}>
229
227
  <input type="hidden" name="tryAnotherWay" value="on" />
230
228
  <a href="#" id="try-another-way" onClick={onTryAnotherWayClick}>
231
229
  {msg("doTryAnotherWay")}
@@ -235,8 +233,8 @@ const Template = memo((props: TemplateProps) => {
235
233
  </form>
236
234
  )}
237
235
  {displayInfo && (
238
- <div id="kc-info" className={cx(props.kcSignUpClass)}>
239
- <div id="kc-info-wrapper" className={cx(props.kcInfoAreaWrapperClass)}>
236
+ <div id="kc-info" className={clsx(props.kcSignUpClass)}>
237
+ <div id="kc-info-wrapper" className={clsx(props.kcInfoAreaWrapperClass)}>
240
238
  {infoNode}
241
239
  </div>
242
240
  </div>
@@ -3,7 +3,7 @@ import DefaultTemplate from "./Template";
3
3
  import type { TemplateProps } from "./Template";
4
4
  import type { KcProps } from "./KcProps";
5
5
  import type { KcContextBase } from "../getKcContext/KcContextBase";
6
- import { useCssAndCx } from "../tools/useCssAndCx";
6
+ import { clsx } from "../tools/clsx";
7
7
  import { Evt } from "evt";
8
8
  import { useRerenderOnStateChange } from "evt/hooks";
9
9
  import { assert } from "tsafe/assert";
@@ -70,8 +70,6 @@ const Terms = memo((props: TermsProps) => {
70
70
 
71
71
  useRerenderOnStateChange(evtTermMarkdown);
72
72
 
73
- const { cx } = useCssAndCx();
74
-
75
73
  const { url } = kcContext;
76
74
 
77
75
  if (evtTermMarkdown.state === undefined) {
@@ -88,7 +86,7 @@ const Terms = memo((props: TermsProps) => {
88
86
  <div id="kc-terms-text">{evtTermMarkdown.state && <Markdown>{evtTermMarkdown.state}</Markdown>}</div>
89
87
  <form className="form-actions" action={url.loginAction} method="POST">
90
88
  <input
91
- className={cx(
89
+ className={clsx(
92
90
  kcProps.kcButtonClass,
93
91
  kcProps.kcButtonClass,
94
92
  kcProps.kcButtonClass,
@@ -101,7 +99,7 @@ const Terms = memo((props: TermsProps) => {
101
99
  value={msgStr("doAccept")}
102
100
  />
103
101
  <input
104
- className={cx(kcProps.kcButtonClass, kcProps.kcButtonDefaultClass, kcProps.kcButtonLargeClass)}
102
+ className={clsx(kcProps.kcButtonClass, kcProps.kcButtonDefaultClass, kcProps.kcButtonLargeClass)}
105
103
  name="cancel"
106
104
  id="kc-decline"
107
105
  type="submit"
@@ -3,7 +3,7 @@ import DefaultTemplate from "./Template";
3
3
  import type { TemplateProps } from "./Template";
4
4
  import type { KcProps } from "./KcProps";
5
5
  import type { KcContextBase } from "../getKcContext/KcContextBase";
6
- import { useCssAndCx } from "../tools/useCssAndCx";
6
+ import { clsx } from "../tools/clsx";
7
7
  import type { I18n } from "../i18n";
8
8
  import { UserProfileFormFields } from "./shared/UserProfileCommons";
9
9
 
@@ -17,8 +17,6 @@ export type UpdateUserProfileProps = KcProps & {
17
17
  const UpdateUserProfile = memo((props: UpdateUserProfileProps) => {
18
18
  const { kcContext, i18n, doFetchDefaultThemeResources = true, Template = DefaultTemplate, ...kcProps } = props;
19
19
 
20
- const { cx } = useCssAndCx();
21
-
22
20
  const { msg, msgStr } = i18n;
23
21
 
24
22
  const { url, isAppInitiatedAction } = kcContext;
@@ -30,24 +28,24 @@ const UpdateUserProfile = memo((props: UpdateUserProfileProps) => {
30
28
  {...{ kcContext, i18n, doFetchDefaultThemeResources, ...kcProps }}
31
29
  headerNode={msg("loginProfileTitle")}
32
30
  formNode={
33
- <form id="kc-update-profile-form" className={cx(kcProps.kcFormClass)} action={url.loginAction} method="post">
31
+ <form id="kc-update-profile-form" className={clsx(kcProps.kcFormClass)} action={url.loginAction} method="post">
34
32
  <UserProfileFormFields kcContext={kcContext} onIsFormSubmittableValueChange={setIsFomSubmittable} i18n={i18n} {...kcProps} />
35
33
 
36
- <div className={cx(kcProps.kcFormGroupClass)}>
37
- <div id="kc-form-options" className={cx(kcProps.kcFormOptionsClass)}>
38
- <div className={cx(kcProps.kcFormOptionsWrapperClass)}></div>
34
+ <div className={clsx(kcProps.kcFormGroupClass)}>
35
+ <div id="kc-form-options" className={clsx(kcProps.kcFormOptionsClass)}>
36
+ <div className={clsx(kcProps.kcFormOptionsWrapperClass)}></div>
39
37
  </div>
40
38
 
41
- <div id="kc-form-buttons" className={cx(kcProps.kcFormButtonsClass)}>
39
+ <div id="kc-form-buttons" className={clsx(kcProps.kcFormButtonsClass)}>
42
40
  {isAppInitiatedAction ? (
43
41
  <>
44
42
  <input
45
- className={cx(kcProps.kcButtonClass, kcProps.kcButtonPrimaryClass, kcProps.kcButtonLargeClass)}
43
+ className={clsx(kcProps.kcButtonClass, kcProps.kcButtonPrimaryClass, kcProps.kcButtonLargeClass)}
46
44
  type="submit"
47
45
  value={msgStr("doSubmit")}
48
46
  />
49
47
  <button
50
- className={cx(kcProps.kcButtonClass, kcProps.kcButtonDefaultClass, kcProps.kcButtonLargeClass)}
48
+ className={clsx(kcProps.kcButtonClass, kcProps.kcButtonDefaultClass, kcProps.kcButtonLargeClass)}
51
49
  type="submit"
52
50
  name="cancel-aia"
53
51
  value="true"
@@ -58,7 +56,7 @@ const UpdateUserProfile = memo((props: UpdateUserProfileProps) => {
58
56
  </>
59
57
  ) : (
60
58
  <input
61
- className={cx(
59
+ className={clsx(
62
60
  kcProps.kcButtonClass,
63
61
  kcProps.kcButtonPrimaryClass,
64
62
  kcProps.kcButtonBlockClass,
@@ -3,7 +3,7 @@ import DefaultTemplate from "./Template";
3
3
  import type { TemplateProps } from "./Template";
4
4
  import type { KcProps } from "./KcProps";
5
5
  import type { KcContextBase } from "../getKcContext/KcContextBase";
6
- import { useCssAndCx } from "../tools/useCssAndCx";
6
+ import { clsx } from "../tools/clsx";
7
7
  import type { I18n, MessageKeyBase } from "../i18n";
8
8
  import { base64url } from "rfc4648";
9
9
  import { useConstCallback } from "powerhooks/useConstCallback";
@@ -26,8 +26,6 @@ const WebauthnAuthenticate = memo((props: WebauthnAuthenticateProps) => {
26
26
  const createTimeout = Number(kcContext.createTimeout);
27
27
  const isUserIdentified = kcContext.isUserIdentified == "true";
28
28
 
29
- const { cx } = useCssAndCx();
30
-
31
29
  const webAuthnAuthenticate = useConstCallback(async () => {
32
30
  if (!isUserIdentified) {
33
31
  return;
@@ -102,7 +100,7 @@ const WebauthnAuthenticate = memo((props: WebauthnAuthenticateProps) => {
102
100
  {...{ kcContext, i18n, doFetchDefaultThemeResources, ...kcProps }}
103
101
  headerNode={msg("webauthn-login-title")}
104
102
  formNode={
105
- <div id="kc-form-webauthn" className={cx(kcProps.kcFormClass)}>
103
+ <div id="kc-form-webauthn" className={clsx(kcProps.kcFormClass)}>
106
104
  <form id="webauth" action={url.loginAction} ref={webAuthForm} method="post">
107
105
  <input type="hidden" id="clientDataJSON" name="clientDataJSON" value={clientDataJSON} />
108
106
  <input type="hidden" id="authenticatorData" name="authenticatorData" value={authenticatorData} />
@@ -111,10 +109,10 @@ const WebauthnAuthenticate = memo((props: WebauthnAuthenticateProps) => {
111
109
  <input type="hidden" id="userHandle" name="userHandle" value={userHandle} />
112
110
  <input type="hidden" id="error" name="error" value={error} />
113
111
  </form>
114
- <div className={cx(kcProps.kcFormGroupClass)}>
112
+ <div className={clsx(kcProps.kcFormGroupClass)}>
115
113
  {authenticators &&
116
114
  (() => (
117
- <form id="authn_select" className={cx(kcProps.kcFormClass)}>
115
+ <form id="authn_select" className={clsx(kcProps.kcFormClass)}>
118
116
  {authenticators.authenticators.map(authenticator => (
119
117
  <input
120
118
  type="hidden"
@@ -130,23 +128,23 @@ const WebauthnAuthenticate = memo((props: WebauthnAuthenticateProps) => {
130
128
  (() => (
131
129
  <>
132
130
  {authenticators.authenticators.length > 1 && (
133
- <p className={cx(kcProps.kcSelectAuthListItemTitle)}>{msg("webauthn-available-authenticators")}</p>
131
+ <p className={clsx(kcProps.kcSelectAuthListItemTitle)}>{msg("webauthn-available-authenticators")}</p>
134
132
  )}
135
- <div className={cx(kcProps.kcFormClass)}>
133
+ <div className={clsx(kcProps.kcFormClass)}>
136
134
  {authenticators.authenticators.map(authenticator => (
137
- <div id="kc-webauthn-authenticator" className={cx(kcProps.kcSelectAuthListItemClass)}>
138
- <div className={cx(kcProps.kcSelectAuthListItemIconClass)}>
135
+ <div id="kc-webauthn-authenticator" className={clsx(kcProps.kcSelectAuthListItemClass)}>
136
+ <div className={clsx(kcProps.kcSelectAuthListItemIconClass)}>
139
137
  <i
140
- className={cx(
138
+ className={clsx(
141
139
  kcProps[authenticator.transports.iconClass] ?? kcProps.kcWebAuthnDefaultIcon,
142
140
  kcProps.kcSelectAuthListItemIconPropertyClass
143
141
  )}
144
142
  />
145
143
  </div>
146
- <div className={cx(kcProps.kcSelectAuthListItemBodyClass)}>
144
+ <div className={clsx(kcProps.kcSelectAuthListItemBodyClass)}>
147
145
  <div
148
146
  id="kc-webauthn-authenticator-label"
149
- className={cx(kcProps.kcSelectAuthListItemHeadingClass)}
147
+ className={clsx(kcProps.kcSelectAuthListItemHeadingClass)}
150
148
  >
151
149
  {authenticator.label}
152
150
  </div>
@@ -154,7 +152,7 @@ const WebauthnAuthenticate = memo((props: WebauthnAuthenticateProps) => {
154
152
  {authenticator.transports && authenticator.transports.displayNameProperties.length && (
155
153
  <div
156
154
  id="kc-webauthn-authenticator-transport"
157
- className={cx(kcProps.kcSelectAuthListItemDescriptionClass)}
155
+ className={clsx(kcProps.kcSelectAuthListItemDescriptionClass)}
158
156
  >
159
157
  {authenticator.transports.displayNameProperties.map(
160
158
  (transport: MessageKeyBase, index: number) => (
@@ -169,25 +167,25 @@ const WebauthnAuthenticate = memo((props: WebauthnAuthenticateProps) => {
169
167
  </div>
170
168
  )}
171
169
 
172
- <div className={cx(kcProps.kcSelectAuthListItemDescriptionClass)}>
170
+ <div className={clsx(kcProps.kcSelectAuthListItemDescriptionClass)}>
173
171
  <span id="kc-webauthn-authenticator-created-label">{msg("webauthn-createdAt-label")}</span>
174
172
  <span id="kc-webauthn-authenticator-created">{authenticator.createdAt}</span>
175
173
  </div>
176
174
  </div>
177
- <div className={cx(kcProps.kcSelectAuthListItemFillClass)} />
175
+ <div className={clsx(kcProps.kcSelectAuthListItemFillClass)} />
178
176
  </div>
179
177
  ))}
180
178
  </div>
181
179
  </>
182
180
  ))()}
183
- <div id="kc-form-buttons" className={cx(kcProps.kcFormButtonsClass)}>
181
+ <div id="kc-form-buttons" className={clsx(kcProps.kcFormButtonsClass)}>
184
182
  <input
185
183
  id="authenticateWebAuthnButton"
186
184
  type="button"
187
185
  onClick={webAuthnAuthenticate}
188
186
  autoFocus={true}
189
187
  value={msgStr("webauthn-doAuthenticate")}
190
- className={cx(
188
+ className={clsx(
191
189
  kcProps.kcButtonClass,
192
190
  kcProps.kcButtonPrimaryClass,
193
191
  kcProps.kcButtonBlockClass,
@@ -1,7 +1,7 @@
1
1
  import React, { memo, useEffect, Fragment } from "react";
2
2
  import type { KcProps } from "../KcProps";
3
3
  import type { Attribute } from "../../getKcContext/KcContextBase";
4
- import { useCssAndCx } from "../../tools/useCssAndCx";
4
+ import { clsx } from "../../tools/clsx";
5
5
  import type { ReactComponent } from "../../tools/ReactComponent";
6
6
  import { useCallbackFactory } from "powerhooks/useCallbackFactory";
7
7
  import { useFormValidationSlice } from "../../useFormValidationSlice";
@@ -18,8 +18,6 @@ export type UserProfileFormFieldsProps = {
18
18
 
19
19
  export const UserProfileFormFields = memo(
20
20
  ({ kcContext, onIsFormSubmittableValueChange, i18n, BeforeField, AfterField, ...props }: UserProfileFormFieldsProps) => {
21
- const { cx, css } = useCssAndCx();
22
-
23
21
  const { advancedMsg } = i18n;
24
22
 
25
23
  const {
@@ -67,20 +65,20 @@ export const UserProfileFormFields = memo(
67
65
 
68
66
  const { value, displayableErrors } = fieldStateByAttributeName[attribute.name];
69
67
 
70
- const formGroupClassName = cx(props.kcFormGroupClass, displayableErrors.length !== 0 && props.kcFormGroupErrorClass);
68
+ const formGroupClassName = clsx(props.kcFormGroupClass, displayableErrors.length !== 0 && props.kcFormGroupErrorClass);
71
69
 
72
70
  return (
73
71
  <Fragment key={i}>
74
72
  {group !== currentGroup && (currentGroup = group) !== "" && (
75
73
  <div className={formGroupClassName}>
76
- <div className={cx(props.kcContentWrapperClass)}>
77
- <label id={`header-${group}`} className={cx(props.kcFormGroupHeader)}>
74
+ <div className={clsx(props.kcContentWrapperClass)}>
75
+ <label id={`header-${group}`} className={clsx(props.kcFormGroupHeader)}>
78
76
  {advancedMsg(groupDisplayHeader) || currentGroup}
79
77
  </label>
80
78
  </div>
81
79
  {groupDisplayDescription !== "" && (
82
- <div className={cx(props.kcLabelWrapperClass)}>
83
- <label id={`description-${group}`} className={`${cx(props.kcLabelClass)}`}>
80
+ <div className={clsx(props.kcLabelWrapperClass)}>
81
+ <label id={`description-${group}`} className={`${clsx(props.kcLabelClass)}`}>
84
82
  {advancedMsg(groupDisplayDescription)}
85
83
  </label>
86
84
  </div>
@@ -91,13 +89,13 @@ export const UserProfileFormFields = memo(
91
89
  {BeforeField && <BeforeField attribute={attribute} />}
92
90
 
93
91
  <div className={formGroupClassName}>
94
- <div className={cx(props.kcLabelWrapperClass)}>
95
- <label htmlFor={attribute.name} className={cx(props.kcLabelClass)}>
92
+ <div className={clsx(props.kcLabelWrapperClass)}>
93
+ <label htmlFor={attribute.name} className={clsx(props.kcLabelClass)}>
96
94
  {advancedMsg(attribute.displayName ?? "")}
97
95
  </label>
98
96
  {attribute.required && <>*</>}
99
97
  </div>
100
- <div className={cx(props.kcInputWrapperClass)}>
98
+ <div className={clsx(props.kcInputWrapperClass)}>
101
99
  {(() => {
102
100
  const { options } = attribute.validators;
103
101
 
@@ -134,7 +132,7 @@ export const UserProfileFormFields = memo(
134
132
  name={attribute.name}
135
133
  value={value}
136
134
  onChange={onChangeFactory(attribute.name)}
137
- className={cx(props.kcInputClass)}
135
+ className={clsx(props.kcInputClass)}
138
136
  aria-invalid={displayableErrors.length !== 0}
139
137
  disabled={attribute.readOnly}
140
138
  autoComplete={attribute.autocomplete}
@@ -142,21 +140,26 @@ export const UserProfileFormFields = memo(
142
140
  />
143
141
  );
144
142
  })()}
145
- {displayableErrors.length !== 0 && (
146
- <span
147
- id={`input-error-${attribute.name}`}
148
- className={cx(
149
- props.kcInputErrorMessageClass,
150
- css({
151
- "position": displayableErrors.length === 1 ? "absolute" : undefined,
152
- "& > span": { "display": "block" }
153
- })
154
- )}
155
- aria-live="polite"
156
- >
157
- {displayableErrors.map(({ errorMessage }) => errorMessage)}
158
- </span>
159
- )}
143
+ {displayableErrors.length !== 0 &&
144
+ (() => {
145
+ const divId = `input-error-${attribute.name}`;
146
+
147
+ return (
148
+ <>
149
+ <style>{`#${divId} > span: { display: block; }`}</style>
150
+ <span
151
+ id={divId}
152
+ className={clsx(props.kcInputErrorMessageClass)}
153
+ style={{
154
+ "position": displayableErrors.length === 1 ? "absolute" : undefined
155
+ }}
156
+ aria-live="polite"
157
+ >
158
+ {displayableErrors.map(({ errorMessage }) => errorMessage)}
159
+ </span>
160
+ </>
161
+ );
162
+ })()}
160
163
  </div>
161
164
  </div>
162
165
 
@@ -0,0 +1,7 @@
1
+ import { classnames } from "tss-react/tools/classnames";
2
+ import type { Cx } from "tss-react";
3
+
4
+ /** Drop in replacement for https://www.npmjs.com/package/clsx */
5
+ export const clsx: Cx = (...args) => {
6
+ return classnames(args);
7
+ };
@@ -1,11 +1,12 @@
1
- import { createMakeStyles } from "tss-react";
2
-
3
- const { useStyles } = createMakeStyles({
4
- "useTheme": () => ({})
5
- });
1
+ import { clsx as cx } from "./clsx";
6
2
 
3
+ /**
4
+ * @deprecated: Use clsx instead.
5
+ * import { clsx } from "keycloakify/lib/tools/clsx";
6
+ * You can use clsx as cx.
7
+ * If you where using the css() function you can import
8
+ * it from @emotion/css: https://emotion.sh/docs/@emotion/css
9
+ */
7
10
  export function useCssAndCx() {
8
- const { css, cx } = useStyles();
9
-
10
- return { css, cx };
11
+ return { cx };
11
12
  }