keycloakify 10.0.0-rc.37 → 10.0.0-rc.39

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 (307) hide show
  1. package/account/Fallback.d.ts +1 -2
  2. package/account/Fallback.js.map +1 -1
  3. package/account/KcContext/KcContext.d.ts +6 -6
  4. package/account/KcContext/getKcContextMock.d.ts +9 -9
  5. package/account/KcContext/getKcContextMock.js +3 -3
  6. package/account/KcContext/getKcContextMock.js.map +1 -1
  7. package/account/Template.d.ts +1 -2
  8. package/account/Template.js +7 -6
  9. package/account/Template.js.map +1 -1
  10. package/account/TemplateProps.d.ts +1 -3
  11. package/account/i18n/i18n.d.ts +9 -4
  12. package/account/i18n/i18n.js +132 -87
  13. package/account/i18n/i18n.js.map +1 -1
  14. package/account/i18n/index.d.ts +9 -2
  15. package/account/i18n/index.js +5 -1
  16. package/account/i18n/index.js.map +1 -1
  17. package/account/lib/kcClsx.d.ts +9 -0
  18. package/account/lib/{useGetClassName.js → kcClsx.js} +3 -3
  19. package/account/lib/kcClsx.js.map +1 -0
  20. package/account/pages/Account.d.ts +1 -2
  21. package/account/pages/Account.js +9 -7
  22. package/account/pages/Account.js.map +1 -1
  23. package/account/pages/Applications.d.ts +1 -2
  24. package/account/pages/Applications.js +7 -7
  25. package/account/pages/Applications.js.map +1 -1
  26. package/account/pages/FederatedIdentity.d.ts +1 -2
  27. package/account/pages/FederatedIdentity.js +4 -3
  28. package/account/pages/FederatedIdentity.js.map +1 -1
  29. package/account/pages/Log.d.ts +1 -2
  30. package/account/pages/Log.js +6 -5
  31. package/account/pages/Log.js.map +1 -1
  32. package/account/pages/PageProps.d.ts +2 -4
  33. package/account/pages/Password.d.ts +1 -2
  34. package/account/pages/Password.js +10 -9
  35. package/account/pages/Password.js.map +1 -1
  36. package/account/pages/Sessions.d.ts +1 -2
  37. package/account/pages/Sessions.js +6 -6
  38. package/account/pages/Sessions.js.map +1 -1
  39. package/account/pages/Totp.d.ts +1 -2
  40. package/account/pages/Totp.js +6 -5
  41. package/account/pages/Totp.js.map +1 -1
  42. package/bin/193.index.js +13 -13
  43. package/bin/{430.index.js → 214.index.js} +161 -2
  44. package/bin/3.index.js +165 -149
  45. package/bin/322.index.js +595 -0
  46. package/bin/453.index.js +3 -3
  47. package/bin/526.index.js +42 -632
  48. package/bin/538.index.js +563 -0
  49. package/bin/932.index.js +7 -7
  50. package/bin/{890.index.js → 941.index.js} +2 -159
  51. package/bin/944.index.js +621 -0
  52. package/bin/961.index.js +5 -5
  53. package/bin/97.index.js +3 -3
  54. package/bin/{314.index.js → 98.index.js} +217 -48
  55. package/bin/main.js +20 -8
  56. package/lib/getKcClsx.d.ts +11 -0
  57. package/lib/getKcClsx.js +55 -0
  58. package/lib/getKcClsx.js.map +1 -0
  59. package/login/Fallback.d.ts +2 -2
  60. package/login/Fallback.js.map +1 -1
  61. package/login/KcContext/KcContext.d.ts +6 -6
  62. package/login/KcContext/getKcContextMock.d.ts +9 -9
  63. package/login/KcContext/getKcContextMock.js +3 -3
  64. package/login/KcContext/getKcContextMock.js.map +1 -1
  65. package/login/Template.d.ts +1 -2
  66. package/login/Template.js +10 -9
  67. package/login/Template.js.map +1 -1
  68. package/login/TemplateProps.d.ts +1 -3
  69. package/login/UserProfileFormFields.d.ts +6 -5
  70. package/login/UserProfileFormFields.js +35 -36
  71. package/login/UserProfileFormFields.js.map +1 -1
  72. package/login/i18n/i18n.d.ts +9 -4
  73. package/login/i18n/i18n.js +136 -91
  74. package/login/i18n/i18n.js.map +1 -1
  75. package/login/i18n/index.d.ts +9 -2
  76. package/login/i18n/index.js +5 -1
  77. package/login/i18n/index.js.map +1 -1
  78. package/login/lib/kcClsx.d.ts +9 -0
  79. package/login/lib/{useGetClassName.js → kcClsx.js} +3 -3
  80. package/login/lib/kcClsx.js.map +1 -0
  81. package/login/lib/useUserProfileForm.d.ts +9 -6
  82. package/login/lib/useUserProfileForm.js +7 -5
  83. package/login/lib/useUserProfileForm.js.map +1 -1
  84. package/login/pages/Code.d.ts +1 -2
  85. package/login/pages/Code.js +6 -5
  86. package/login/pages/Code.js.map +1 -1
  87. package/login/pages/DeleteAccountConfirm.d.ts +1 -2
  88. package/login/pages/DeleteAccountConfirm.js +7 -7
  89. package/login/pages/DeleteAccountConfirm.js.map +1 -1
  90. package/login/pages/DeleteCredential.d.ts +1 -2
  91. package/login/pages/DeleteCredential.js +6 -6
  92. package/login/pages/DeleteCredential.js.map +1 -1
  93. package/login/pages/Error.d.ts +1 -2
  94. package/login/pages/Error.js +4 -3
  95. package/login/pages/Error.js.map +1 -1
  96. package/login/pages/FrontchannelLogout.d.ts +1 -2
  97. package/login/pages/FrontchannelLogout.js +4 -3
  98. package/login/pages/FrontchannelLogout.js.map +1 -1
  99. package/login/pages/IdpReviewUserProfile.d.ts +2 -2
  100. package/login/pages/IdpReviewUserProfile.js +6 -6
  101. package/login/pages/IdpReviewUserProfile.js.map +1 -1
  102. package/login/pages/Info.d.ts +1 -2
  103. package/login/pages/Info.js +4 -3
  104. package/login/pages/Info.js.map +1 -1
  105. package/login/pages/Login.d.ts +1 -2
  106. package/login/pages/Login.js +10 -8
  107. package/login/pages/Login.js.map +1 -1
  108. package/login/pages/LoginConfigTotp.d.ts +1 -2
  109. package/login/pages/LoginConfigTotp.js +8 -7
  110. package/login/pages/LoginConfigTotp.js.map +1 -1
  111. package/login/pages/LoginIdpLinkConfirm.d.ts +1 -2
  112. package/login/pages/LoginIdpLinkConfirm.js +6 -6
  113. package/login/pages/LoginIdpLinkConfirm.js.map +1 -1
  114. package/login/pages/LoginIdpLinkEmail.d.ts +1 -2
  115. package/login/pages/LoginIdpLinkEmail.js +4 -3
  116. package/login/pages/LoginIdpLinkEmail.js.map +1 -1
  117. package/login/pages/LoginOauth2DeviceVerifyUserCode.d.ts +1 -2
  118. package/login/pages/LoginOauth2DeviceVerifyUserCode.js +6 -6
  119. package/login/pages/LoginOauth2DeviceVerifyUserCode.js.map +1 -1
  120. package/login/pages/LoginOauthGrant.d.ts +1 -2
  121. package/login/pages/LoginOauthGrant.js +7 -7
  122. package/login/pages/LoginOauthGrant.js.map +1 -1
  123. package/login/pages/LoginOtp.d.ts +1 -2
  124. package/login/pages/LoginOtp.js +6 -6
  125. package/login/pages/LoginOtp.js.map +1 -1
  126. package/login/pages/LoginPageExpired.d.ts +1 -2
  127. package/login/pages/LoginPageExpired.js +4 -3
  128. package/login/pages/LoginPageExpired.js.map +1 -1
  129. package/login/pages/LoginPassword.d.ts +1 -2
  130. package/login/pages/LoginPassword.js +9 -7
  131. package/login/pages/LoginPassword.js.map +1 -1
  132. package/login/pages/LoginRecoveryAuthnCodeConfig.d.ts +1 -2
  133. package/login/pages/LoginRecoveryAuthnCodeConfig.js +9 -7
  134. package/login/pages/LoginRecoveryAuthnCodeConfig.js.map +1 -1
  135. package/login/pages/LoginRecoveryAuthnCodeInput.d.ts +1 -2
  136. package/login/pages/LoginRecoveryAuthnCodeInput.js +6 -6
  137. package/login/pages/LoginRecoveryAuthnCodeInput.js.map +1 -1
  138. package/login/pages/LoginResetOtp.d.ts +1 -2
  139. package/login/pages/LoginResetOtp.js +6 -6
  140. package/login/pages/LoginResetOtp.js.map +1 -1
  141. package/login/pages/LoginResetPassword.d.ts +1 -2
  142. package/login/pages/LoginResetPassword.js +7 -7
  143. package/login/pages/LoginResetPassword.js.map +1 -1
  144. package/login/pages/LoginUpdatePassword.d.ts +1 -2
  145. package/login/pages/LoginUpdatePassword.js +10 -9
  146. package/login/pages/LoginUpdatePassword.js.map +1 -1
  147. package/login/pages/LoginUpdateProfile.d.ts +2 -2
  148. package/login/pages/LoginUpdateProfile.js +7 -12
  149. package/login/pages/LoginUpdateProfile.js.map +1 -1
  150. package/login/pages/LoginUsername.d.ts +1 -2
  151. package/login/pages/LoginUsername.js +8 -7
  152. package/login/pages/LoginUsername.js.map +1 -1
  153. package/login/pages/LoginVerifyEmail.d.ts +1 -2
  154. package/login/pages/LoginVerifyEmail.js +4 -3
  155. package/login/pages/LoginVerifyEmail.js.map +1 -1
  156. package/login/pages/LoginX509Info.d.ts +1 -2
  157. package/login/pages/LoginX509Info.js +6 -6
  158. package/login/pages/LoginX509Info.js.map +1 -1
  159. package/login/pages/LogoutConfirm.d.ts +1 -2
  160. package/login/pages/LogoutConfirm.js +6 -6
  161. package/login/pages/LogoutConfirm.js.map +1 -1
  162. package/login/pages/PageProps.d.ts +2 -4
  163. package/login/pages/Register.d.ts +2 -2
  164. package/login/pages/Register.js +8 -16
  165. package/login/pages/Register.js.map +1 -1
  166. package/login/pages/SamlPostForm.d.ts +1 -2
  167. package/login/pages/SamlPostForm.js +4 -3
  168. package/login/pages/SamlPostForm.js.map +1 -1
  169. package/login/pages/SelectAuthenticator.d.ts +1 -2
  170. package/login/pages/SelectAuthenticator.js +6 -9
  171. package/login/pages/SelectAuthenticator.js.map +1 -1
  172. package/login/pages/Terms.d.ts +1 -2
  173. package/login/pages/Terms.js +6 -6
  174. package/login/pages/Terms.js.map +1 -1
  175. package/login/pages/UpdateEmail.d.ts +2 -2
  176. package/login/pages/UpdateEmail.js +8 -12
  177. package/login/pages/UpdateEmail.js.map +1 -1
  178. package/login/pages/WebauthnAuthenticate.d.ts +1 -2
  179. package/login/pages/WebauthnAuthenticate.js +13 -12
  180. package/login/pages/WebauthnAuthenticate.js.map +1 -1
  181. package/login/pages/WebauthnError.d.ts +1 -2
  182. package/login/pages/WebauthnError.js +7 -7
  183. package/login/pages/WebauthnError.js.map +1 -1
  184. package/login/pages/WebauthnRegister.d.ts +1 -2
  185. package/login/pages/WebauthnRegister.js +9 -8
  186. package/login/pages/WebauthnRegister.js.map +1 -1
  187. package/package.json +27 -22
  188. package/src/account/Fallback.tsx +1 -2
  189. package/src/account/KcContext/KcContext.ts +7 -7
  190. package/src/account/KcContext/getKcContextMock.ts +13 -24
  191. package/src/account/Template.tsx +8 -8
  192. package/src/account/TemplateProps.ts +1 -6
  193. package/src/account/i18n/i18n.tsx +204 -125
  194. package/src/account/i18n/index.ts +10 -2
  195. package/src/account/lib/{useGetClassName.ts → kcClsx.ts} +6 -2
  196. package/src/account/pages/Account.tsx +15 -21
  197. package/src/account/pages/Applications.tsx +8 -9
  198. package/src/account/pages/FederatedIdentity.tsx +5 -5
  199. package/src/account/pages/Log.tsx +8 -8
  200. package/src/account/pages/PageProps.ts +2 -4
  201. package/src/account/pages/Password.tsx +13 -16
  202. package/src/account/pages/Sessions.tsx +9 -10
  203. package/src/account/pages/Totp.tsx +19 -28
  204. package/src/bin/add-story.ts +3 -3
  205. package/src/bin/copy-keycloak-resources-to-public.ts +3 -3
  206. package/src/bin/download-keycloak-default-theme.ts +5 -5
  207. package/src/bin/eject-page.ts +3 -3
  208. package/src/bin/initialize-email-theme.ts +5 -5
  209. package/src/bin/keycloakify/buildJars/buildJar.ts +14 -14
  210. package/src/bin/keycloakify/buildJars/buildJars.ts +8 -8
  211. package/src/bin/keycloakify/buildJars/generatePom.ts +9 -9
  212. package/src/bin/keycloakify/generateFtl/generateFtl.ts +12 -12
  213. package/src/bin/keycloakify/generateSrcMainResources/bringInAccountV1.ts +7 -7
  214. package/src/bin/keycloakify/generateSrcMainResources/generateMessageProperties.ts +2 -66
  215. package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResources.ts +9 -9
  216. package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResourcesForMainTheme.ts +30 -24
  217. package/src/bin/keycloakify/generateSrcMainResources/generateSrcMainResourcesForThemeVariant.ts +8 -8
  218. package/src/bin/keycloakify/generateStartKeycloakTestingContainer.ts +9 -9
  219. package/src/bin/keycloakify/keycloakify.ts +11 -11
  220. package/src/bin/keycloakify/replacers/replaceImportsInCssCode.ts +6 -6
  221. package/src/bin/keycloakify/replacers/replaceImportsInInlineCssCode.ts +7 -7
  222. package/src/bin/keycloakify/replacers/replaceImportsInJsCode/replaceImportsInJsCode.ts +10 -10
  223. package/src/bin/keycloakify/replacers/replaceImportsInJsCode/vite.ts +13 -13
  224. package/src/bin/keycloakify/replacers/replaceImportsInJsCode/webpack.ts +11 -11
  225. package/src/bin/main.ts +17 -2
  226. package/src/bin/shared/{buildOptions.ts → buildContext.ts} +65 -51
  227. package/src/bin/shared/copyKeycloakResourcesToPublic.ts +12 -12
  228. package/src/bin/shared/downloadKeycloakDefaultTheme.ts +7 -7
  229. package/src/bin/shared/downloadKeycloakStaticResources.ts +7 -7
  230. package/src/bin/shared/generateKcGenTs.ts +61 -0
  231. package/src/bin/shared/getThemeSrcDirPath.ts +3 -3
  232. package/src/bin/start-keycloak/appBuild.ts +11 -11
  233. package/src/bin/start-keycloak/keycloakifyBuild.ts +7 -7
  234. package/src/bin/start-keycloak/start-keycloak.ts +34 -22
  235. package/src/bin/tools/escapeStringForPropertiesFile.ts +64 -0
  236. package/src/bin/tools/getNpmWorkspaceRootDirPath.ts +3 -3
  237. package/src/bin/update-kc-gen.ts +13 -0
  238. package/src/lib/getKcClsx.ts +89 -0
  239. package/src/login/Fallback.tsx +2 -2
  240. package/src/login/KcContext/KcContext.ts +7 -7
  241. package/src/login/KcContext/getKcContextMock.ts +13 -24
  242. package/src/login/Template.tsx +36 -37
  243. package/src/login/TemplateProps.ts +1 -6
  244. package/src/login/UserProfileFormFields.tsx +67 -84
  245. package/src/login/i18n/i18n.tsx +208 -129
  246. package/src/login/i18n/index.ts +10 -2
  247. package/src/login/lib/{useGetClassName.ts → kcClsx.ts} +6 -2
  248. package/src/login/lib/useUserProfileForm.tsx +29 -21
  249. package/src/login/pages/Code.tsx +10 -8
  250. package/src/login/pages/DeleteAccountConfirm.tsx +9 -10
  251. package/src/login/pages/DeleteCredential.tsx +11 -10
  252. package/src/login/pages/Error.tsx +5 -5
  253. package/src/login/pages/FrontchannelLogout.tsx +7 -5
  254. package/src/login/pages/IdpReviewUserProfile.tsx +18 -21
  255. package/src/login/pages/Info.tsx +7 -5
  256. package/src/login/pages/Login.tsx +34 -53
  257. package/src/login/pages/LoginConfigTotp.tsx +30 -38
  258. package/src/login/pages/LoginIdpLinkConfirm.tsx +10 -21
  259. package/src/login/pages/LoginIdpLinkEmail.tsx +5 -5
  260. package/src/login/pages/LoginOauth2DeviceVerifyUserCode.tsx +19 -24
  261. package/src/login/pages/LoginOauthGrant.tsx +14 -21
  262. package/src/login/pages/LoginOtp.tsx +29 -33
  263. package/src/login/pages/LoginPageExpired.tsx +5 -5
  264. package/src/login/pages/LoginPassword.tsx +23 -33
  265. package/src/login/pages/LoginRecoveryAuthnCodeConfig.tsx +21 -25
  266. package/src/login/pages/LoginRecoveryAuthnCodeInput.tsx +21 -25
  267. package/src/login/pages/LoginResetOtp.tsx +21 -25
  268. package/src/login/pages/LoginResetPassword.tsx +21 -25
  269. package/src/login/pages/LoginUpdatePassword.tsx +42 -52
  270. package/src/login/pages/LoginUpdateProfile.tsx +29 -30
  271. package/src/login/pages/LoginUsername.tsx +23 -35
  272. package/src/login/pages/LoginVerifyEmail.tsx +7 -5
  273. package/src/login/pages/LoginX509Info.tsx +27 -36
  274. package/src/login/pages/LogoutConfirm.tsx +11 -17
  275. package/src/login/pages/PageProps.ts +2 -4
  276. package/src/login/pages/Register.tsx +27 -46
  277. package/src/login/pages/SamlPostForm.tsx +5 -5
  278. package/src/login/pages/SelectAuthenticator.tsx +24 -26
  279. package/src/login/pages/Terms.tsx +9 -16
  280. package/src/login/pages/UpdateEmail.tsx +29 -33
  281. package/src/login/pages/WebauthnAuthenticate.tsx +26 -32
  282. package/src/login/pages/WebauthnError.tsx +11 -22
  283. package/src/login/pages/WebauthnRegister.tsx +20 -28
  284. package/src/tools/clsx.ts +6 -48
  285. package/src/tools/clsx_withTransform.ts +55 -0
  286. package/src/vite-plugin/vite-plugin.ts +29 -21
  287. package/tools/clsx.d.ts +3 -2
  288. package/tools/clsx.js +5 -41
  289. package/tools/clsx.js.map +1 -1
  290. package/tools/clsx_withTransform.d.ts +5 -0
  291. package/tools/clsx_withTransform.js +43 -0
  292. package/tools/clsx_withTransform.js.map +1 -0
  293. package/vite-plugin/index.js +243 -102
  294. package/vite-plugin/vite-plugin.d.ts +3 -3
  295. package/account/lib/useGetClassName.d.ts +0 -7
  296. package/account/lib/useGetClassName.js.map +0 -1
  297. package/bin/795.index.js +0 -1197
  298. package/lib/isStorybook.d.ts +0 -1
  299. package/lib/isStorybook.js +0 -3
  300. package/lib/isStorybook.js.map +0 -1
  301. package/lib/useGetClassName.d.ts +0 -10
  302. package/lib/useGetClassName.js +0 -14
  303. package/lib/useGetClassName.js.map +0 -1
  304. package/login/lib/useGetClassName.d.ts +0 -7
  305. package/login/lib/useGetClassName.js.map +0 -1
  306. package/src/lib/isStorybook.ts +0 -3
  307. package/src/lib/useGetClassName.ts +0 -27
@@ -1,20 +1,19 @@
1
- import { clsx } from "keycloakify/tools/clsx";
2
1
  import { Markdown } from "keycloakify/tools/Markdown";
3
- import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
2
+ import { getKcClsx } from "keycloakify/login/lib/kcClsx";
4
3
  import { useTermsMarkdown } from "keycloakify/login/lib/useDownloadTerms";
5
4
  import type { PageProps } from "keycloakify/login/pages/PageProps";
6
5
  import type { KcContext } from "../KcContext";
7
- import type { I18n } from "../i18n";
6
+ import { useI18n } from "../i18n";
8
7
 
9
- export default function Terms(props: PageProps<Extract<KcContext, { pageId: "terms.ftl" }>, I18n>) {
10
- const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;
8
+ export default function Terms(props: PageProps<Extract<KcContext, { pageId: "terms.ftl" }>>) {
9
+ const { kcContext, doUseDefaultCss, Template, classes } = props;
11
10
 
12
- const { getClassName } = useGetClassName({
11
+ const { kcClsx } = getKcClsx({
13
12
  doUseDefaultCss,
14
13
  classes
15
14
  });
16
15
 
17
- const { msg, msgStr } = i18n;
16
+ const { msg, msgStr } = useI18n({ kcContext });
18
17
 
19
18
  const { locale, url } = kcContext;
20
19
 
@@ -25,26 +24,20 @@ export default function Terms(props: PageProps<Extract<KcContext, { pageId: "ter
25
24
  }
26
25
 
27
26
  return (
28
- <Template {...{ kcContext, i18n, doUseDefaultCss, classes }} displayMessage={false} headerNode={msg("termsTitle")}>
27
+ <Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} displayMessage={false} headerNode={msg("termsTitle")}>
29
28
  <div id="kc-terms-text" lang={termsLanguageTag !== locale?.currentLanguageTag ? termsLanguageTag : undefined}>
30
29
  <Markdown>{termsMarkdown}</Markdown>
31
30
  </div>
32
31
  <form className="form-actions" action={url.loginAction} method="POST">
33
32
  <input
34
- className={clsx(
35
- getClassName("kcButtonClass"),
36
- getClassName("kcButtonClass"),
37
- getClassName("kcButtonClass"),
38
- getClassName("kcButtonPrimaryClass"),
39
- getClassName("kcButtonLargeClass")
40
- )}
33
+ className={kcClsx("kcButtonClass", "kcButtonClass", "kcButtonClass", "kcButtonPrimaryClass", "kcButtonLargeClass")}
41
34
  name="accept"
42
35
  id="kc-accept"
43
36
  type="submit"
44
37
  value={msgStr("doAccept")}
45
38
  />
46
39
  <input
47
- className={clsx(getClassName("kcButtonClass"), getClassName("kcButtonDefaultClass"), getClassName("kcButtonLargeClass"))}
40
+ className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
48
41
  name="cancel"
49
42
  id="kc-decline"
50
43
  type="submit"
@@ -1,24 +1,25 @@
1
1
  import { useState } from "react";
2
- import { clsx } from "keycloakify/tools/clsx";
3
2
  import type { LazyOrNot } from "keycloakify/tools/LazyOrNot";
4
- import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
3
+ import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
5
4
  import type { UserProfileFormFieldsProps } from "keycloakify/login/UserProfileFormFields";
6
5
  import type { PageProps } from "keycloakify/login/pages/PageProps";
7
6
  import type { KcContext } from "../KcContext";
8
- import type { I18n } from "../i18n";
7
+ import { useI18n, type I18n } from "../i18n";
9
8
 
10
- type UpdateEmailProps = PageProps<Extract<KcContext, { pageId: "update-email.ftl" }>, I18n> & {
9
+ type UpdateEmailProps = PageProps<Extract<KcContext, { pageId: "update-email.ftl" }>> & {
11
10
  UserProfileFormFields: LazyOrNot<(props: UserProfileFormFieldsProps) => JSX.Element>;
11
+ doMakeUserConfirmPassword: boolean;
12
12
  };
13
13
 
14
14
  export default function UpdateEmail(props: UpdateEmailProps) {
15
- const { kcContext, i18n, doUseDefaultCss, Template, classes, UserProfileFormFields } = props;
15
+ const { kcContext, doUseDefaultCss, Template, classes, UserProfileFormFields, doMakeUserConfirmPassword } = props;
16
16
 
17
- const { getClassName } = useGetClassName({
17
+ const { kcClsx } = getKcClsx({
18
18
  doUseDefaultCss,
19
19
  classes
20
20
  });
21
21
 
22
+ const i18n = useI18n({ kcContext });
22
23
  const { msg, msgStr } = i18n;
23
24
 
24
25
  const [isFormSubmittable, setIsFormSubmittable] = useState(false);
@@ -27,48 +28,43 @@ export default function UpdateEmail(props: UpdateEmailProps) {
27
28
 
28
29
  return (
29
30
  <Template
30
- {...{ kcContext, i18n, doUseDefaultCss, classes }}
31
+ kcContext={kcContext}
32
+ doUseDefaultCss={doUseDefaultCss}
33
+ classes={classes}
31
34
  displayMessage={messagesPerField.exists("global")}
32
35
  displayRequiredFields
33
36
  headerNode={msg("updateEmailTitle")}
34
37
  >
35
- <form id="kc-update-email-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
38
+ <form id="kc-update-email-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
36
39
  <UserProfileFormFields
37
- {...{
38
- kcContext,
39
- i18n,
40
- getClassName,
41
- messagesPerField
42
- }}
40
+ kcContext={kcContext}
41
+ kcClsx={kcClsx}
43
42
  onIsFormSubmittableValueChange={setIsFormSubmittable}
43
+ doMakeUserConfirmPassword={doMakeUserConfirmPassword}
44
44
  />
45
45
 
46
- <div className={getClassName("kcFormGroupClass")}>
47
- <div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
48
- <div className={getClassName("kcFormOptionsWrapperClass")} />
46
+ <div className={kcClsx("kcFormGroupClass")}>
47
+ <div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
48
+ <div className={kcClsx("kcFormOptionsWrapperClass")} />
49
49
  </div>
50
50
 
51
- <LogoutOtherSessions {...{ getClassName, i18n }} />
51
+ <LogoutOtherSessions kcClsx={kcClsx} i18n={i18n} />
52
52
 
53
- <div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
53
+ <div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
54
54
  <input
55
55
  disabled={!isFormSubmittable}
56
- className={clsx(
57
- getClassName("kcButtonClass"),
58
- getClassName("kcButtonPrimaryClass"),
59
- isAppInitiatedAction && getClassName("kcButtonBlockClass"),
60
- getClassName("kcButtonLargeClass")
56
+ className={kcClsx(
57
+ "kcButtonClass",
58
+ "kcButtonPrimaryClass",
59
+ isAppInitiatedAction && "kcButtonBlockClass",
60
+ "kcButtonLargeClass"
61
61
  )}
62
62
  type="submit"
63
63
  value={msgStr("doSubmit")}
64
64
  />
65
65
  {isAppInitiatedAction && (
66
66
  <button
67
- className={clsx(
68
- getClassName("kcButtonClass"),
69
- getClassName("kcButtonDefaultClass"),
70
- getClassName("kcButtonLargeClass")
71
- )}
67
+ className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonLargeClass")}
72
68
  type="submit"
73
69
  name="cancel-aia"
74
70
  value="true"
@@ -83,14 +79,14 @@ export default function UpdateEmail(props: UpdateEmailProps) {
83
79
  );
84
80
  }
85
81
 
86
- function LogoutOtherSessions(props: { getClassName: ReturnType<typeof useGetClassName>["getClassName"]; i18n: I18n }) {
87
- const { getClassName, i18n } = props;
82
+ function LogoutOtherSessions(props: { kcClsx: KcClsx; i18n: I18n }) {
83
+ const { kcClsx, i18n } = props;
88
84
 
89
85
  const { msg } = i18n;
90
86
 
91
87
  return (
92
- <div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
93
- <div className={getClassName("kcFormOptionsWrapperClass")}>
88
+ <div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
89
+ <div className={kcClsx("kcFormOptionsWrapperClass")}>
94
90
  <div className="checkbox">
95
91
  <label>
96
92
  <input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
@@ -2,15 +2,15 @@ import { useEffect, Fragment } from "react";
2
2
  import { assert } from "tsafe/assert";
3
3
  import { clsx } from "keycloakify/tools/clsx";
4
4
  import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
5
- import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
5
+ import { getKcClsx } from "keycloakify/login/lib/kcClsx";
6
6
  import type { PageProps } from "keycloakify/login/pages/PageProps";
7
7
  import type { KcContext } from "../KcContext";
8
- import type { I18n } from "../i18n";
8
+ import { useI18n } from "../i18n";
9
9
 
10
- export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext, { pageId: "webauthn-authenticate.ftl" }>, I18n>) {
11
- const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;
10
+ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext, { pageId: "webauthn-authenticate.ftl" }>>) {
11
+ const { kcContext, doUseDefaultCss, Template, classes } = props;
12
12
 
13
- const { getClassName } = useGetClassName({ doUseDefaultCss, classes });
13
+ const { kcClsx } = getKcClsx({ doUseDefaultCss, classes });
14
14
 
15
15
  const {
16
16
  url,
@@ -26,7 +26,7 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
26
26
  shouldDisplayAuthenticators
27
27
  } = kcContext;
28
28
 
29
- const { msg, msgStr, advancedMsg } = i18n;
29
+ const { msg, msgStr, advancedMsg } = useI18n({ kcContext });
30
30
 
31
31
  const { insertScriptTags } = useInsertScriptTags({
32
32
  componentOrHookName: "WebauthnAuthenticate",
@@ -136,7 +136,9 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
136
136
 
137
137
  return (
138
138
  <Template
139
- {...{ kcContext, i18n, doUseDefaultCss, classes }}
139
+ kcContext={kcContext}
140
+ doUseDefaultCss={doUseDefaultCss}
141
+ classes={classes}
140
142
  displayMessage={!messagesPerField.existsError("username")}
141
143
  displayInfo={realm.password && realm.registrationAllowed && !registrationDisabled}
142
144
  infoNode={
@@ -151,7 +153,7 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
151
153
  }
152
154
  headerNode={msg("webauthn-login-title")}
153
155
  >
154
- <div id="kc-form-webauthn" className={getClassName("kcFormClass")}>
156
+ <div id="kc-form-webauthn" className={kcClsx("kcFormClass")}>
155
157
  <form id="webauth" action={url.loginAction} method="post">
156
158
  <input type="hidden" id="clientDataJSON" name="clientDataJSON" />
157
159
  <input type="hidden" id="authenticatorData" name="authenticatorData" />
@@ -160,10 +162,10 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
160
162
  <input type="hidden" id="userHandle" name="userHandle" />
161
163
  <input type="hidden" id="error" name="error" />
162
164
  </form>
163
- <div className={clsx(getClassName("kcFormGroupClass"), "no-bottom-margin")}>
165
+ <div className={clsx(kcClsx("kcFormGroupClass"), "no-bottom-margin")}>
164
166
  {authenticators && (
165
167
  <>
166
- <form id="authn_select" className={getClassName("kcFormClass")}>
168
+ <form id="authn_select" className={kcClsx("kcFormClass")}>
167
169
  {authenticators.authenticators.map(authenticator => (
168
170
  <input type="hidden" name="authn_use_chk" value={authenticator.credentialId} />
169
171
  ))}
@@ -172,36 +174,33 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
172
174
  {shouldDisplayAuthenticators && (
173
175
  <>
174
176
  {authenticators.authenticators.length > 1 && (
175
- <p className={getClassName("kcSelectAuthListItemTitle")}>{msg("webauthn-available-authenticators")}</p>
177
+ <p className={kcClsx("kcSelectAuthListItemTitle")}>{msg("webauthn-available-authenticators")}</p>
176
178
  )}
177
- <div className={getClassName("kcFormOptionsClass")}>
179
+ <div className={kcClsx("kcFormOptionsClass")}>
178
180
  {authenticators.authenticators.map((authenticator, i) => (
179
- <div key={i} id="kc-webauthn-authenticator" className={getClassName("kcSelectAuthListItemClass")}>
180
- <div className={getClassName("kcSelectAuthListItemIconClass")}>
181
+ <div key={i} id="kc-webauthn-authenticator" className={kcClsx("kcSelectAuthListItemClass")}>
182
+ <div className={kcClsx("kcSelectAuthListItemIconClass")}>
181
183
  <i
182
184
  className={clsx(
183
185
  (() => {
184
- const className = getClassName(authenticator.transports.iconClass as any);
186
+ const className = kcClsx(authenticator.transports.iconClass as any);
185
187
  if (className === authenticator.transports.iconClass) {
186
- return getClassName("kcWebAuthnDefaultIcon");
188
+ return kcClsx("kcWebAuthnDefaultIcon");
187
189
  }
188
190
  return className;
189
191
  })(),
190
- getClassName("kcSelectAuthListItemIconPropertyClass")
192
+ kcClsx("kcSelectAuthListItemIconPropertyClass")
191
193
  )}
192
194
  />
193
195
  </div>
194
- <div className={getClassName("kcSelectAuthListItemArrowIconClass")}>
195
- <div
196
- id="kc-webauthn-authenticator-label"
197
- className={getClassName("kcSelectAuthListItemHeadingClass")}
198
- >
196
+ <div className={kcClsx("kcSelectAuthListItemArrowIconClass")}>
197
+ <div id="kc-webauthn-authenticator-label" className={kcClsx("kcSelectAuthListItemHeadingClass")}>
199
198
  {advancedMsg(authenticator.label)}
200
199
  </div>
201
200
  {authenticator.transports.displayNameProperties?.length && (
202
201
  <div
203
202
  id="kc-webauthn-authenticator-transport"
204
- className={getClassName("kcSelectAuthListItemDescriptionClass")}
203
+ className={kcClsx("kcSelectAuthListItemDescriptionClass")}
205
204
  >
206
205
  {authenticator.transports.displayNameProperties
207
206
  .map((nameProperty, i, arr) => ({
@@ -216,11 +215,11 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
216
215
  ))}
217
216
  </div>
218
217
  )}
219
- <div className={getClassName("kcSelectAuthListItemDescriptionClass")}>
218
+ <div className={kcClsx("kcSelectAuthListItemDescriptionClass")}>
220
219
  <span id="kc-webauthn-authenticator-created-label">{msg("webauthn-createdAt-label")}</span>
221
220
  <span id="kc-webauthn-authenticator-created">{authenticator.createdAt}</span>
222
221
  </div>
223
- <div className={getClassName("kcSelectAuthListItemFillClass")} />
222
+ <div className={kcClsx("kcSelectAuthListItemFillClass")} />
224
223
  </div>
225
224
  </div>
226
225
  ))}
@@ -230,7 +229,7 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
230
229
  </>
231
230
  )}
232
231
 
233
- <div id="kc-form-buttons" className={getClassName("kcFormButtonsClass")}>
232
+ <div id="kc-form-buttons" className={kcClsx("kcFormButtonsClass")}>
234
233
  <input
235
234
  id="authenticateWebAuthnButton"
236
235
  type="button"
@@ -241,12 +240,7 @@ export default function WebauthnAuthenticate(props: PageProps<Extract<KcContext,
241
240
  }}
242
241
  autoFocus
243
242
  value={msgStr("webauthn-doAuthenticate")}
244
- className={clsx(
245
- getClassName("kcButtonClass"),
246
- getClassName("kcButtonPrimaryClass"),
247
- getClassName("kcButtonBlockClass"),
248
- getClassName("kcButtonLargeClass")
249
- )}
243
+ className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
250
244
  />
251
245
  </div>
252
246
  </div>
@@ -1,24 +1,23 @@
1
- import { clsx } from "keycloakify/tools/clsx";
2
- import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
1
+ import { getKcClsx } from "keycloakify/login/lib/kcClsx";
3
2
  import type { PageProps } from "keycloakify/login/pages/PageProps";
4
3
  import type { KcContext } from "../KcContext";
5
- import type { I18n } from "../i18n";
4
+ import { useI18n } from "../i18n";
6
5
 
7
- export default function WebauthnError(props: PageProps<Extract<KcContext, { pageId: "webauthn-error.ftl" }>, I18n>) {
8
- const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;
6
+ export default function WebauthnError(props: PageProps<Extract<KcContext, { pageId: "webauthn-error.ftl" }>>) {
7
+ const { kcContext, doUseDefaultCss, Template, classes } = props;
9
8
 
10
9
  const { url, isAppInitiatedAction } = kcContext;
11
10
 
12
- const { msg, msgStr } = i18n;
11
+ const { msg, msgStr } = useI18n({ kcContext });
13
12
 
14
- const { getClassName } = useGetClassName({
13
+ const { kcClsx } = getKcClsx({
15
14
  doUseDefaultCss,
16
15
  classes
17
16
  });
18
17
 
19
18
  return (
20
- <Template {...{ kcContext, i18n, doUseDefaultCss, classes }} displayMessage headerNode={msg("webauthn-error-title")}>
21
- <form id="kc-error-credential-form" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
19
+ <Template kcContext={kcContext} doUseDefaultCss={doUseDefaultCss} classes={classes} displayMessage headerNode={msg("webauthn-error-title")}>
20
+ <form id="kc-error-credential-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
22
21
  <input type="hidden" id="executionValue" name="authenticationExecution" />
23
22
  <input type="hidden" id="isSetRetry" name="isSetRetry" />
24
23
  </form>
@@ -33,26 +32,16 @@ export default function WebauthnError(props: PageProps<Extract<KcContext, { page
33
32
  document.getElementById("kc-error-credential-form").submit();
34
33
  }}
35
34
  type="button"
36
- className={clsx(
37
- getClassName("kcButtonClass"),
38
- getClassName("kcButtonPrimaryClass"),
39
- getClassName("kcButtonBlockClass"),
40
- getClassName("kcButtonLargeClass")
41
- )}
35
+ className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
42
36
  name="try-again"
43
37
  id="kc-try-again"
44
38
  value={msgStr("doTryAgain")}
45
39
  />
46
40
  {isAppInitiatedAction && (
47
- <form action={url.loginAction} className={getClassName("kcFormClass")} id="kc-webauthn-settings-form" method="post">
41
+ <form action={url.loginAction} className={kcClsx("kcFormClass")} id="kc-webauthn-settings-form" method="post">
48
42
  <button
49
43
  type="submit"
50
- className={clsx(
51
- getClassName("kcButtonClass"),
52
- getClassName("kcButtonDefaultClass"),
53
- getClassName("kcButtonBlockClass"),
54
- getClassName("kcButtonLargeClass")
55
- )}
44
+ className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonBlockClass", "kcButtonLargeClass")}
56
45
  id="cancelWebAuthnAIA"
57
46
  name="cancel-aia"
58
47
  value="true"
@@ -1,16 +1,15 @@
1
1
  import { useEffect } from "react";
2
2
  import { assert } from "tsafe/assert";
3
- import { clsx } from "keycloakify/tools/clsx";
4
- import { useGetClassName } from "keycloakify/login/lib/useGetClassName";
3
+ import { getKcClsx, type KcClsx } from "keycloakify/login/lib/kcClsx";
5
4
  import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
6
5
  import type { PageProps } from "keycloakify/login/pages/PageProps";
7
6
  import type { KcContext } from "../KcContext";
8
- import type { I18n } from "../i18n";
7
+ import { useI18n, type I18n } from "../i18n";
9
8
 
10
- export default function WebauthnRegister(props: PageProps<Extract<KcContext, { pageId: "webauthn-register.ftl" }>, I18n>) {
11
- const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;
9
+ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { pageId: "webauthn-register.ftl" }>>) {
10
+ const { kcContext, doUseDefaultCss, Template, classes } = props;
12
11
 
13
- const { getClassName } = useGetClassName({ doUseDefaultCss, classes });
12
+ const { kcClsx } = getKcClsx({ doUseDefaultCss, classes });
14
13
 
15
14
  const {
16
15
  url,
@@ -30,6 +29,7 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
30
29
  isAppInitiatedAction
31
30
  } = kcContext;
32
31
 
32
+ const i18n = useI18n({ kcContext });
33
33
  const { msg, msgStr } = i18n;
34
34
 
35
35
  const { insertScriptTags } = useInsertScriptTags({
@@ -206,33 +206,30 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
206
206
 
207
207
  return (
208
208
  <Template
209
- {...{ kcContext, i18n, doUseDefaultCss, classes }}
209
+ kcContext={kcContext}
210
+ doUseDefaultCss={doUseDefaultCss}
211
+ classes={classes}
210
212
  headerNode={
211
213
  <>
212
- <span className={getClassName("kcWebAuthnKeyIcon")} />
214
+ <span className={kcClsx("kcWebAuthnKeyIcon")} />
213
215
  {msg("webauthn-registration-title")}
214
216
  </>
215
217
  }
216
218
  >
217
- <form id="register" className={getClassName("kcFormClass")} action={url.loginAction} method="post">
218
- <div className={getClassName("kcFormGroupClass")}>
219
+ <form id="register" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
220
+ <div className={kcClsx("kcFormGroupClass")}>
219
221
  <input type="hidden" id="clientDataJSON" name="clientDataJSON" />
220
222
  <input type="hidden" id="attestationObject" name="attestationObject" />
221
223
  <input type="hidden" id="publicKeyCredentialId" name="publicKeyCredentialId" />
222
224
  <input type="hidden" id="authenticatorLabel" name="authenticatorLabel" />
223
225
  <input type="hidden" id="transports" name="transports" />
224
226
  <input type="hidden" id="error" name="error" />
225
- <LogoutOtherSessions {...{ i18n, getClassName }} />
227
+ <LogoutOtherSessions kcClsx={kcClsx} i18n={i18n} />
226
228
  </div>
227
229
  </form>
228
230
  <input
229
231
  type="submit"
230
- className={clsx(
231
- getClassName("kcButtonClass"),
232
- getClassName("kcButtonPrimaryClass"),
233
- getClassName("kcButtonBlockClass"),
234
- getClassName("kcButtonLargeClass")
235
- )}
232
+ className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
236
233
  id="registerWebAuthn"
237
234
  value={msgStr("doRegisterSecurityKey")}
238
235
  onClick={() => {
@@ -243,15 +240,10 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
243
240
  />
244
241
 
245
242
  {!isSetRetry && isAppInitiatedAction && (
246
- <form action={url.loginAction} className={getClassName("kcFormClass")} id="kc-webauthn-settings-form" method="post">
243
+ <form action={url.loginAction} className={kcClsx("kcFormClass")} id="kc-webauthn-settings-form" method="post">
247
244
  <button
248
245
  type="submit"
249
- className={clsx(
250
- getClassName("kcButtonClass"),
251
- getClassName("kcButtonDefaultClass"),
252
- getClassName("kcButtonBlockClass"),
253
- getClassName("kcButtonLargeClass")
254
- )}
246
+ className={kcClsx("kcButtonClass", "kcButtonDefaultClass", "kcButtonBlockClass", "kcButtonLargeClass")}
255
247
  id="cancelWebAuthnAIA"
256
248
  name="cancel-aia"
257
249
  value="true"
@@ -264,14 +256,14 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
264
256
  );
265
257
  }
266
258
 
267
- function LogoutOtherSessions(props: { i18n: I18n; getClassName: ReturnType<typeof useGetClassName>["getClassName"] }) {
268
- const { getClassName, i18n } = props;
259
+ function LogoutOtherSessions(props: { kcClsx: KcClsx; i18n: I18n }) {
260
+ const { kcClsx, i18n } = props;
269
261
 
270
262
  const { msg } = i18n;
271
263
 
272
264
  return (
273
- <div id="kc-form-options" className={getClassName("kcFormOptionsClass")}>
274
- <div className={getClassName("kcFormOptionsWrapperClass")}>
265
+ <div id="kc-form-options" className={kcClsx("kcFormOptionsClass")}>
266
+ <div className={kcClsx("kcFormOptionsWrapperClass")}>
275
267
  <div className="checkbox">
276
268
  <label>
277
269
  <input type="checkbox" id="logout-sessions" name="logout-sessions" value="on" defaultChecked={true} />
package/src/tools/clsx.ts CHANGED
@@ -1,50 +1,8 @@
1
- import { assert } from "tsafe/assert";
2
- import { typeGuard } from "tsafe/typeGuard";
1
+ import { id } from "tsafe";
2
+ import { clsx_withTransform, type CxArg as CxArg_generic } from "./clsx_withTransform";
3
3
 
4
- export type CxArg =
5
- | undefined
6
- | null
7
- | string
8
- | boolean
9
- | Partial<Record<string, boolean | null | undefined>>
10
- | readonly CxArg[];
4
+ export type CxArg = CxArg_generic<string>;
11
5
 
12
- export const clsx = (...args: CxArg[]): string => {
13
- const len = args.length;
14
- let i = 0;
15
- let cls = "";
16
- for (; i < len; i++) {
17
- const arg = args[i];
18
- if (arg == null) continue;
19
-
20
- let toAdd;
21
- switch (typeof arg) {
22
- case "boolean":
23
- break;
24
- case "object": {
25
- if (Array.isArray(arg)) {
26
- toAdd = clsx(...arg);
27
- } else {
28
- assert(!typeGuard<{ length: number }>(arg, false));
29
-
30
- toAdd = "";
31
- for (const k in arg) {
32
- if (arg[k as string] && k) {
33
- toAdd && (toAdd += " ");
34
- toAdd += k;
35
- }
36
- }
37
- }
38
- break;
39
- }
40
- default: {
41
- toAdd = arg;
42
- }
43
- }
44
- if (toAdd) {
45
- cls && (cls += " ");
46
- cls += toAdd;
47
- }
48
- }
49
- return cls;
50
- };
6
+ export function clsx(...args: CxArg[]): string {
7
+ return clsx_withTransform({ args, transform: id });
8
+ }
@@ -0,0 +1,55 @@
1
+ import { assert } from "tsafe/assert";
2
+ import { typeGuard } from "tsafe/typeGuard";
3
+
4
+ export type CxArg<ClassName extends string = string> =
5
+ | undefined
6
+ | null
7
+ | ClassName
8
+ | boolean
9
+ | Partial<Record<ClassName, boolean | null | undefined>>
10
+ | readonly CxArg<ClassName>[];
11
+
12
+ export function clsx_withTransform(params: {
13
+ args: CxArg[];
14
+ transform: (arg: string) => string;
15
+ }): string {
16
+ const { args, transform } = params;
17
+
18
+ const len = args.length;
19
+ let i = 0;
20
+ let cls = "";
21
+ for (; i < len; i++) {
22
+ const arg = args[i];
23
+ if (arg == null) continue;
24
+
25
+ let toAdd;
26
+ switch (typeof arg) {
27
+ case "boolean":
28
+ break;
29
+ case "object": {
30
+ if (Array.isArray(arg)) {
31
+ toAdd = clsx_withTransform({ args: arg, transform });
32
+ } else {
33
+ assert(!typeGuard<{ length: number }>(arg, false));
34
+
35
+ toAdd = "";
36
+ for (const k in arg) {
37
+ if (arg[k] && k) {
38
+ toAdd && (toAdd += " ");
39
+ toAdd += transform(k);
40
+ }
41
+ }
42
+ }
43
+ break;
44
+ }
45
+ default: {
46
+ toAdd = transform(arg);
47
+ }
48
+ }
49
+ if (toAdd) {
50
+ cls && (cls += " ");
51
+ cls += toAdd;
52
+ }
53
+ }
54
+ return cls;
55
+ }