@keycloakify/svelte 0.2.0 → 0.2.2

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 (62) hide show
  1. package/keycloakify-svelte/account/Template.svelte +1 -1
  2. package/keycloakify-svelte/account/pages/Account.svelte +3 -3
  3. package/keycloakify-svelte/account/pages/Applications.svelte +8 -8
  4. package/keycloakify-svelte/account/pages/FederatedIdentity.svelte +1 -1
  5. package/keycloakify-svelte/account/pages/Log.svelte +2 -2
  6. package/keycloakify-svelte/account/pages/Password.svelte +1 -1
  7. package/keycloakify-svelte/account/pages/Sessions.svelte +2 -2
  8. package/keycloakify-svelte/account/pages/Totp.svelte +2 -2
  9. package/keycloakify-svelte/bin/292.index.js +297 -252
  10. package/keycloakify-svelte/login/Template.svelte +1 -1
  11. package/keycloakify-svelte/login/components/FieldErrors.svelte +1 -1
  12. package/keycloakify-svelte/login/components/InputFieldByType.svelte +1 -1
  13. package/keycloakify-svelte/login/components/InputTagSelects.svelte +1 -1
  14. package/keycloakify-svelte/login/components/SelectTag.svelte +1 -1
  15. package/keycloakify-svelte/login/components/UserProfileFormFields.svelte +1 -1
  16. package/keycloakify-svelte/login/pages/DeleteAccountConfirm.svelte +6 -6
  17. package/keycloakify-svelte/login/pages/FrontchannelLogout.svelte +11 -7
  18. package/keycloakify-svelte/login/pages/Login.svelte +3 -3
  19. package/keycloakify-svelte/login/pages/LoginConfigTotp.svelte +3 -3
  20. package/keycloakify-svelte/login/pages/LoginIdpLinkConfirmOverride.svelte +1 -1
  21. package/keycloakify-svelte/login/pages/LoginOauthGrant.svelte +1 -1
  22. package/keycloakify-svelte/login/pages/LoginOtp.svelte +1 -1
  23. package/keycloakify-svelte/login/pages/LoginPageExpired.svelte +3 -5
  24. package/keycloakify-svelte/login/pages/LoginPasskeysConditionalAuthenticate.svelte +6 -6
  25. package/keycloakify-svelte/login/pages/LoginRecoveryAuthnCodeConfig.svelte +1 -1
  26. package/keycloakify-svelte/login/pages/LoginResetOtp.svelte +1 -1
  27. package/keycloakify-svelte/login/pages/LoginUsername.svelte +2 -2
  28. package/keycloakify-svelte/login/pages/Register.svelte +19 -3
  29. package/keycloakify-svelte/login/pages/SelectAuthenticator.svelte +1 -1
  30. package/keycloakify-svelte/login/pages/WebauthnAuthenticate.svelte +4 -4
  31. package/package.json +21 -21
  32. package/src/account/Template.svelte +1 -1
  33. package/src/account/pages/Account.svelte +3 -3
  34. package/src/account/pages/Applications.svelte +8 -8
  35. package/src/account/pages/FederatedIdentity.svelte +1 -1
  36. package/src/account/pages/Log.svelte +2 -2
  37. package/src/account/pages/Password.svelte +1 -1
  38. package/src/account/pages/Sessions.svelte +2 -2
  39. package/src/account/pages/Totp.svelte +2 -2
  40. package/src/login/Template.svelte +1 -1
  41. package/src/login/components/FieldErrors.svelte +1 -1
  42. package/src/login/components/InputFieldByType.svelte +1 -1
  43. package/src/login/components/InputTagSelects.svelte +1 -1
  44. package/src/login/components/SelectTag.svelte +1 -1
  45. package/src/login/components/UserProfileFormFields.svelte +1 -1
  46. package/src/login/pages/DeleteAccountConfirm.svelte +6 -6
  47. package/src/login/pages/FrontchannelLogout.svelte +11 -7
  48. package/src/login/pages/Login.svelte +3 -3
  49. package/src/login/pages/LoginConfigTotp.svelte +3 -3
  50. package/src/login/pages/LoginIdpLinkConfirmOverride.svelte +1 -1
  51. package/src/login/pages/LoginOauthGrant.svelte +1 -1
  52. package/src/login/pages/LoginOtp.svelte +1 -1
  53. package/src/login/pages/LoginPageExpired.svelte +3 -5
  54. package/src/login/pages/LoginPasskeysConditionalAuthenticate.svelte +6 -6
  55. package/src/login/pages/LoginRecoveryAuthnCodeConfig.svelte +1 -1
  56. package/src/login/pages/LoginResetOtp.svelte +1 -1
  57. package/src/login/pages/LoginUsername.svelte +2 -2
  58. package/src/login/pages/Register.svelte +19 -3
  59. package/src/login/pages/SelectAuthenticator.svelte +1 -1
  60. package/src/login/pages/WebauthnAuthenticate.svelte +4 -4
  61. package/stories/account/KcPage.svelte +1 -0
  62. package/stories/login/KcPage.svelte +1 -0
@@ -92,7 +92,7 @@
92
92
  id="language-switch1"
93
93
  class={kcClsx('kcLocaleListClass')}
94
94
  >
95
- {#each enabledLanguages as enabledLanguage, i}
95
+ {#each enabledLanguages as enabledLanguage, i (enabledLanguage.languageTag)}
96
96
  {@const { label, href } = enabledLanguage}
97
97
  <li
98
98
  class={kcClsx('kcLocaleListItemClass')}
@@ -20,7 +20,7 @@
20
20
  class={kcClsx('kcInputErrorMessageClass')}
21
21
  aria-live="polite"
22
22
  >
23
- {#each _displayableErrors as displayableError, i}
23
+ {#each _displayableErrors as displayableError, i (i)}
24
24
  {@const { errorMessage } = displayableError}
25
25
  {@render errorMessage()}
26
26
  {#if _displayableErrors.length - 1 !== i}<br />{/if}
@@ -36,7 +36,7 @@
36
36
  {:else}
37
37
  <!-- default -->
38
38
  {#if valueOrValues instanceof Array}
39
- {#each valueOrValues as _, i}
39
+ {#each valueOrValues as _, i (i)}
40
40
  <InputTag
41
41
  {...props}
42
42
  bind:displayableErrors
@@ -62,7 +62,7 @@
62
62
  })();
63
63
  </script>
64
64
 
65
- {#each options as option}
65
+ {#each options as option (option)}
66
66
  <div class={classDiv}>
67
67
  <input
68
68
  type={inputType}
@@ -66,7 +66,7 @@
66
66
  })}
67
67
  >
68
68
  {#if !isMultiple}<option value=""></option>{/if}
69
- {#each options as option}
69
+ {#each options as option (option)}
70
70
  <option value={option}>
71
71
  {@render inputLabel($i18n, attribute, option)()}
72
72
  </option>
@@ -41,7 +41,7 @@
41
41
  );
42
42
  </script>
43
43
 
44
- {#each $formFieldStates as formFieldState, i}
44
+ {#each $formFieldStates as formFieldState, i (i)}
45
45
  {@const { attribute, valueOrValues } = formFieldState}
46
46
  <GroupLabel
47
47
  {attribute}
@@ -39,17 +39,17 @@
39
39
  >
40
40
  <div
41
41
  class="alert alert-warning"
42
- style:margin-top={'0'}
43
- style:margin-bottom={'30px'}
42
+ style:margin-top="0"
43
+ style:margin-bottom="30px"
44
44
  >
45
45
  <span class="pficon pficon-warning-triangle-o"></span>
46
46
  {@render msg('irreversibleAction')()}
47
47
  </div>
48
48
  <p>{@render msg('deletingImplies')()}</p>
49
49
  <ul
50
- style:color={'#72767b'}
51
- style:list-style={'disc'}
52
- style:list-style-position={'inside'}
50
+ style:color="#72767b"
51
+ style:list-style="disc"
52
+ style:list-style-position="inside"
53
53
  >
54
54
  <li>{@render msg('loggingOutImmediately')()}</li>
55
55
  <li>{@render msg('errasingData')()}</li>
@@ -64,7 +64,7 @@
64
64
  {#if triggered_from_aia}
65
65
  <button
66
66
  class={kcClsx('kcButtonClass', 'kcButtonDefaultClass', 'kcButtonLargeClass')}
67
- style:margin-left={'calc(100% - 220px)'}
67
+ style:margin-left="calc(100% - 220px)"
68
68
  type="submit"
69
69
  name="cancel-aia"
70
70
  value="true"
@@ -1,6 +1,5 @@
1
1
  <script lang="ts">
2
2
  import type { PageProps } from './PageProps';
3
- import { onMount } from 'svelte';
4
3
  import type { KcContext } from '../KcContext';
5
4
  import type { I18n } from '../i18n';
6
5
 
@@ -15,11 +14,15 @@
15
14
  const { logout } = kcContext;
16
15
 
17
16
  const { msg, msgStr } = $i18n;
18
-
19
- onMount(() => {
20
- if (logout.logoutRedirectUri) {
21
- window.location.replace(logout.logoutRedirectUri);
17
+ let iframeLoadCount = $state(0);
18
+ $effect(() => {
19
+ if (!kcContext.logout.logoutRedirectUri) {
20
+ return;
21
+ }
22
+ if (iframeLoadCount !== kcContext.logout.clients.length) {
23
+ return;
22
24
  }
25
+ window.location.replace(kcContext.logout.logoutRedirectUri);
23
26
  });
24
27
  </script>
25
28
 
@@ -35,13 +38,14 @@
35
38
  {/snippet}
36
39
  <p>{@render msg('frontchannel-logout.message')()}</p>
37
40
  <ul>
38
- {#each logout.clients as client}
41
+ {#each logout.clients as client (client.name)}
39
42
  <li>
40
43
  {client.name}
41
44
  <!-- svelte-ignore a11y_missing_attribute -->
42
45
  <iframe
43
46
  src={client.frontChannelLogoutUrl}
44
- style:display={'none'}
47
+ style:display="none"
48
+ onload={() => iframeLoadCount++}
45
49
  ></iframe>
46
50
  </li>{/each}
47
51
  </ul>
@@ -42,7 +42,7 @@
42
42
  <div id="kc-registration-container">
43
43
  <div id="kc-registration">
44
44
  <span>
45
- {@render msg('noAccount')()}{' '}
45
+ {@render msg('noAccount')()}&nbsp;
46
46
  <a
47
47
  tabindex={8}
48
48
  href={url.registrationUrl}
@@ -63,7 +63,7 @@
63
63
  <hr />
64
64
  <h2>{@render msg('identity-provider-login-label')()}</h2>
65
65
  <ul class={kcClsx('kcFormSocialAccountListClass', providers.length > 3 && 'kcFormSocialAccountListGridClass')}>
66
- {#each providers as p}
66
+ {#each providers as p (p.providerId)}
67
67
  <li>
68
68
  <a
69
69
  id={`social-${p.alias}`}
@@ -178,7 +178,7 @@
178
178
  name="rememberMe"
179
179
  type="checkbox"
180
180
  checked={!!login.rememberMe}
181
- />{' '}
181
+ />&nbsp;
182
182
  {@render msg('rememberMe')()}
183
183
  </label>
184
184
  </div>
@@ -39,7 +39,7 @@
39
39
  <p>{@render msg('loginTotpStep1')()}</p>
40
40
 
41
41
  <ul id="kc-totp-supported-apps">
42
- {#each totp.supportedApplications as app}
42
+ {#each totp.supportedApplications as app (app)}
43
43
  <li>{@render advancedMsg(app)()}</li>
44
44
  {/each}
45
45
  </ul>
@@ -119,7 +119,7 @@
119
119
  class={kcClsx('kcLabelClass')}
120
120
  >
121
121
  {@render msg('authenticatorCode')()}
122
- </label>{' '}
122
+ </label>&nbsp;
123
123
  <span class="required">*</span>
124
124
  </div>
125
125
  <div class={kcClsx('kcInputWrapperClass')}>
@@ -160,7 +160,7 @@
160
160
  class={kcClsx('kcLabelClass')}
161
161
  >
162
162
  {@render msg('loginTotpDeviceName')()}
163
- </label>{' '}
163
+ </label>&nbsp;
164
164
  {#if totp.otpCredentials.length >= 1}<span class="required">*</span>{/if}
165
165
  </div>
166
166
  <div class={kcClsx('kcInputWrapperClass')}>
@@ -37,7 +37,7 @@
37
37
  action={url.loginAction}
38
38
  method="post"
39
39
  >
40
- {@render msg('pageExpiredMsg1')()}{' '}
40
+ {@render msg('pageExpiredMsg1')()}&nbsp;
41
41
  <a
42
42
  id="loginRestartLink"
43
43
  href={url.loginRestartFlowUrl}
@@ -48,7 +48,7 @@
48
48
  >
49
49
  <h3>{@render msg('oauthGrantRequest')()}</h3>
50
50
  <ul>
51
- {#each oauth.clientScopesRequested as clientScope}
51
+ {#each oauth.clientScopesRequested as clientScope, i (i)}
52
52
  <li>
53
53
  <span>
54
54
  {@render advancedMsg(clientScope.consentScreenText)()}
@@ -42,7 +42,7 @@
42
42
  {#if otpLogin.userOtpCredentials.length > 1}
43
43
  <div class={kcClsx('kcFormGroupClass')}>
44
44
  <div class={kcClsx('kcInputWrapperClass')}>
45
- {#each otpLogin.userOtpCredentials as otpCredential, index}
45
+ {#each otpLogin.userOtpCredentials as otpCredential, index (otpCredential.id)}
46
46
  <input
47
47
  id={`kc-otp-credential-${index}`}
48
48
  class={kcClsx('kcLoginOTPListInputClass')}
@@ -36,15 +36,13 @@
36
36
  href={url.loginRestartFlowUrl}
37
37
  >
38
38
  {@render msg('doClickHere')()}
39
- </a>{' '}
40
- .<br />
41
- {@render msg('pageExpiredMsg2')()}{' '}
39
+ </a>&nbsp;.<br />
40
+ {@render msg('pageExpiredMsg2')()}&nbsp;
42
41
  <a
43
42
  id="loginContinueLink"
44
43
  href={url.loginAction}
45
44
  >
46
45
  {@render msg('doClickHere')()}
47
- </a>{' '}
48
- .
46
+ </a>&nbsp;.
49
47
  </p>
50
48
  </Template>
@@ -101,14 +101,14 @@
101
101
  <div
102
102
  class={kcClsx('kcFormGroupClass')}
103
103
  no-bottom-margin={true}
104
- style:margin-bottom={'0'}
104
+ style:margin-bottom="0"
105
105
  >
106
106
  {#if authenticators !== undefined && Object.keys(authenticators).length !== 0}
107
107
  <form
108
108
  id="authn_select"
109
109
  class={kcClsx('kcFormClass')}
110
110
  >
111
- {#each authenticators.authenticators as authenticator}
111
+ {#each authenticators.authenticators as authenticator (authenticator.credentialId)}
112
112
  <input
113
113
  type="hidden"
114
114
  name="authn_use_chk"
@@ -122,7 +122,7 @@
122
122
  <p class={kcClsx('kcSelectAuthListItemTitle')}>{msg('passkey-available-authenticators')}</p>
123
123
  {/if}
124
124
  <div class={kcClsx('kcFormClass')}>
125
- {#each authenticators.authenticators as authenticator, i}
125
+ {#each authenticators.authenticators as authenticator, i (authenticator.credentialId)}
126
126
  <div
127
127
  id={`kc-webauthn-authenticator-item-${i}`}
128
128
  class={kcClsx('kcSelectAuthListItemClass')}
@@ -151,7 +151,7 @@
151
151
  id={`kc-webauthn-authenticator-transport-${i}`}
152
152
  class={kcClsx('kcSelectAuthListItemDescriptionClass')}
153
153
  >
154
- {#each authenticator.transports.displayNameProperties as nameProperty, i}
154
+ {#each authenticator.transports.displayNameProperties as nameProperty, i (nameProperty)}
155
155
  <span> {advancedMsg(nameProperty)} </span>
156
156
  {#if i !== authenticator.transports.displayNameProperties.length - 1}
157
157
  <span>, </span>{/if}
@@ -176,7 +176,7 @@
176
176
  id="kc-form-login"
177
177
  action={url.loginAction}
178
178
  method="post"
179
- style:display={'none'}
179
+ style:display="none"
180
180
  onsubmit={(event) => {
181
181
  try {
182
182
  event.currentTarget.login.disabled = true;
@@ -223,7 +223,7 @@
223
223
  <div
224
224
  id="kc-form-passkey-button"
225
225
  class={kcClsx('kcFormButtonsClass')}
226
- style:display={'none'}
226
+ style:display="none"
227
227
  >
228
228
  <!-- svelte-ignore a11y_autofocus -->
229
229
  <input
@@ -61,7 +61,7 @@
61
61
  id={olRecoveryCodesListId}
62
62
  class={kcClsx('kcRecoveryCodesList')}
63
63
  >
64
- {#each recoveryAuthnCodesConfigBean.generatedRecoveryAuthnCodesList as code, index}
64
+ {#each recoveryAuthnCodesConfigBean.generatedRecoveryAuthnCodesList as code, index (code)}
65
65
  <li>
66
66
  <span>{index + 1}:</span>
67
67
  {code.slice(0, 4)}-{code.slice(4, 8)}-{code.slice(8)}
@@ -41,7 +41,7 @@
41
41
  <div class={kcClsx('kcInputWrapperClass')}>
42
42
  <div class={kcClsx('kcInfoAreaWrapperClass')}>
43
43
  <p id="kc-otp-reset-form-description">{msg('otp-reset-description')}</p>
44
- {#each configuredOtpCredentials.userOtpCredentials as otpCredential, index}
44
+ {#each configuredOtpCredentials.userOtpCredentials as otpCredential, index (otpCredential.id)}
45
45
  <input
46
46
  id={`kc-otp-credential-${index}`}
47
47
  class={kcClsx('kcLoginOTPListInputClass')}
@@ -64,7 +64,7 @@
64
64
  social.providers.length > 3 && 'kcFormSocialAccountListGridClass',
65
65
  )}
66
66
  >
67
- {#each social.providers as p}
67
+ {#each social.providers as p (p.providerId)}
68
68
  <li>
69
69
  <a
70
70
  id={`social-${p.alias}`}
@@ -153,7 +153,7 @@
153
153
  name="rememberMe"
154
154
  type="checkbox"
155
155
  checked={!!login.rememberMe}
156
- />{' '}
156
+ />&nbsp;
157
157
  {@render msg('rememberMe')()}
158
158
  </label>
159
159
  </div>
@@ -36,6 +36,23 @@
36
36
 
37
37
  const [isFormSubmittable, setIsFormSubmittable] = useState(false);
38
38
  const [areTermsAccepted, setAreTermsAccepted] = useState(false);
39
+ let htmlFormElement: HTMLFormElement | null = $state(null);
40
+
41
+ $effect(() => {
42
+ if (htmlFormElement === null) {
43
+ return;
44
+ }
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ (window as any)['onSubmitRecaptcha'] = () => {
47
+ // @ts-expect-error; form not null
48
+ htmlFormElement.requestSubmit();
49
+ };
50
+
51
+ return () => {
52
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ delete (window as any)['onSubmitRecaptcha'];
54
+ };
55
+ });
39
56
  </script>
40
57
 
41
58
  <Template
@@ -58,6 +75,7 @@
58
75
  class={kcClsx('kcFormClass')}
59
76
  action={url.registrationAction}
60
77
  method="post"
78
+ bind:this={htmlFormElement}
61
79
  >
62
80
  <UserProfileFormFields
63
81
  {kcContext}
@@ -109,9 +127,7 @@
109
127
  'g-recaptcha',
110
128
  )}
111
129
  data-sitekey={recaptchaSiteKey}
112
- data-callback={() => {
113
- (document.getElementById('kc-register-form') as HTMLFormElement).requestSubmit();
114
- }}
130
+ data-callback="onSubmitRecaptcha"
115
131
  data-action={recaptchaAction}
116
132
  type="submit"
117
133
  >
@@ -34,7 +34,7 @@
34
34
  method="post"
35
35
  >
36
36
  <div class={kcClsx('kcSelectAuthListClass')}>
37
- {#each auth.authenticationSelections as authenticationSelection}
37
+ {#each auth.authenticationSelections as authenticationSelection (authenticationSelection.authExecId)}
38
38
  <button
39
39
  class={kcClsx('kcSelectAuthListItemClass')}
40
40
  type="submit"
@@ -43,7 +43,7 @@
43
43
  {#snippet infoNode()}
44
44
  <div id="kc-registration">
45
45
  <span>
46
- {@render msg('noAccount')()}{' '}
46
+ {@render msg('noAccount')()}&nbsp;
47
47
  <a
48
48
  tabindex={6}
49
49
  href={url.registrationUrl}
@@ -99,7 +99,7 @@
99
99
  id="authn_select"
100
100
  class={kcClsx('kcFormClass')}
101
101
  >
102
- {#each authenticators.authenticators as authenticator}
102
+ {#each authenticators.authenticators as authenticator (authenticator.credentialId)}
103
103
  <input
104
104
  type="hidden"
105
105
  name="authn_use_chk"
@@ -113,7 +113,7 @@
113
113
  <p class={kcClsx('kcSelectAuthListItemTitle')}>{@render msg('webauthn-available-authenticators')()}</p>
114
114
  {/if}
115
115
  <div class={kcClsx('kcFormOptionsClass')}>
116
- {#each authenticators.authenticators as authenticator, i}
116
+ {#each authenticators.authenticators as authenticator, i (authenticator.credentialId)}
117
117
  <div
118
118
  id={`kc-webauthn-authenticator-item-${i}`}
119
119
  class={kcClsx('kcSelectAuthListItemClass')}
@@ -144,7 +144,7 @@
144
144
  id={`kc-webauthn-authenticator-transport-${i}`}
145
145
  class={kcClsx('kcSelectAuthListItemDescriptionClass')}
146
146
  >
147
- {#each authenticator.transports.displayNameProperties as displayNameProperty, i}
147
+ {#each authenticator.transports.displayNameProperties as displayNameProperty, i (displayNameProperty)}
148
148
  {@const hasNext = i !== authenticator.transports.displayNameProperties.length - 1}
149
149
  {@render advancedMsg(displayNameProperty)()}
150
150
  {#if hasNext}<span>, </span>{/if}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keycloakify/svelte",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Svelte Components for Keycloakify",
5
5
  "keywords": [
6
6
  "keycloak",
@@ -432,38 +432,38 @@
432
432
  "release": "sh scripts/release.sh"
433
433
  },
434
434
  "peerDependencies": {
435
- "keycloakify": "^11.9.0",
435
+ "keycloakify": "^11.9.2",
436
436
  "svelte": "^5.0.0"
437
437
  },
438
438
  "devDependencies": {
439
- "@sveltejs/adapter-auto": "^6.0.1",
440
- "@sveltejs/kit": "^2.22.5",
441
- "@sveltejs/package": "^2.3.12",
442
- "@sveltejs/vite-plugin-svelte": "^6.0.0",
439
+ "@sveltejs/adapter-auto": "^6.1.0",
440
+ "@sveltejs/kit": "^2.29.1",
441
+ "@sveltejs/package": "^2.4.1",
442
+ "@sveltejs/vite-plugin-svelte": "^6.1.2",
443
443
  "@types/eslint": "^9.6.1",
444
444
  "@types/node": "^22.15.18",
445
445
  "@vercel/ncc": "^0.38.3",
446
- "conventional-changelog-cli": "^5.0.0",
447
- "cz-conventional-changelog": "^3.3.0",
448
446
  "cli-select": "^1.1.2",
449
- "eslint": "^9.31.0",
450
- "eslint-config-prettier": "^10.1.5",
451
- "eslint-plugin-prettier": "^5.5.1",
452
- "eslint-plugin-svelte": "^3.10.1",
447
+ "conventional-changelog": "^7.1.1",
448
+ "conventional-changelog-angular": "^8.0.0",
449
+ "eslint": "^9.33.0",
450
+ "eslint-config-prettier": "^10.1.8",
451
+ "eslint-plugin-prettier": "^5.5.4",
452
+ "eslint-plugin-svelte": "^3.11.0",
453
453
  "eslint-plugin-unused-imports": "^4.1.4",
454
454
  "globals": "^16.3.0",
455
- "keycloakify": "^11.9.0",
456
- "npm-check-updates": "^18.0.1",
455
+ "keycloakify": "^11.9.2",
456
+ "npm-check-updates": "^18.0.2",
457
457
  "prettier": "^3.6.2",
458
458
  "prettier-plugin-svelte": "^3.4.0",
459
- "publint": "0.2.12",
460
- "svelte": "^5.35.6",
461
- "svelte-check": "^4.2.2",
462
- "tsx": "^4.20.3",
459
+ "publint": "^0.3.12",
460
+ "svelte": "^5.38.1",
461
+ "svelte-check": "^4.3.1",
462
+ "tsx": "^4.20.4",
463
463
  "typescript": "~5.8.3",
464
- "typescript-eslint": "^8.36.0",
465
- "vite": "^7.0.4",
466
- "zod": "^4.0.5"
464
+ "typescript-eslint": "^8.39.1",
465
+ "vite": "^7.1.2",
466
+ "zod": "^4.0.17"
467
467
  },
468
468
  "bin": {
469
469
  "_keycloakify-custom-handler": "keycloakify-svelte/bin/index.js"
@@ -62,7 +62,7 @@
62
62
  {currentLanguage.label}
63
63
  </a>
64
64
  <ul>
65
- {#each enabledLanguages as { label, href }}
65
+ {#each enabledLanguages as { label, href, languageTag } (languageTag)}
66
66
  <li class="kc-dropdown-item">
67
67
  <a {href}>{label}</a>
68
68
  </li>
@@ -91,7 +91,7 @@
91
91
  class="control-label"
92
92
  >
93
93
  {@render msg('email')()}
94
- </label>{' '}
94
+ </label>&nbsp;
95
95
  <span class="required">*</span>
96
96
  </div>
97
97
 
@@ -115,7 +115,7 @@
115
115
  class="control-label"
116
116
  >
117
117
  {@render msg('firstName')()}
118
- </label>{' '}
118
+ </label>&nbsp;
119
119
  <span class="required">*</span>
120
120
  </div>
121
121
 
@@ -137,7 +137,7 @@
137
137
  class="control-label"
138
138
  >
139
139
  {@render msg('lastName')()}
140
- </label>{' '}
140
+ </label>&nbsp;
141
141
  <span class="required">*</span>
142
142
  </div>
143
143
 
@@ -76,7 +76,7 @@
76
76
  </thead>
77
77
 
78
78
  <tbody>
79
- {#each applications as application}
79
+ {#each applications as application, i (i)}
80
80
  <tr>
81
81
  <td>
82
82
  {#if application.effectiveUrl}
@@ -97,22 +97,22 @@
97
97
 
98
98
  <td>
99
99
  {#if !isArrayWithEmptyObject(application.realmRolesAvailable)}
100
- {#each application.realmRolesAvailable as role, index}
100
+ {#each application.realmRolesAvailable as role, index (role.name)}
101
101
  <span>
102
102
  {@render (role.description ? advancedMsg(role.description) : advancedMsg(role.name))()}
103
103
  {#if index < application.realmRolesAvailable.length - 1},&nbsp;{/if}
104
104
  </span>
105
105
  {/each}
106
106
  {#if application.resourceRolesAvailable}
107
- {#each Object.keys(application.resourceRolesAvailable) as resource}
107
+ {#each Object.keys(application.resourceRolesAvailable) as resource (resource)}
108
108
  <span>
109
109
  {#if !isArrayWithEmptyObject(application.realmRolesAvailable)},&nbsp;{/if}
110
- {#each application.resourceRolesAvailable[resource] as clientRole}
110
+ {#each application.resourceRolesAvailable[resource] as clientRole (clientRole.roleName)}
111
111
  <span>
112
112
  {@render (clientRole.roleDescription
113
113
  ? advancedMsg(clientRole.roleDescription)
114
- : advancedMsg(clientRole.roleName))()}{' '}
115
- {@render msg('inResource')()}{' '}
114
+ : advancedMsg(clientRole.roleName))()}&nbsp:
115
+ {@render msg('inResource')()}&nbsp:
116
116
  <strong>
117
117
  {#if clientRole.clientName}
118
118
  {@render advancedMsg(clientRole.clientName)()}
@@ -131,7 +131,7 @@
131
131
 
132
132
  <td>
133
133
  {#if application.client.consentRequired}
134
- {#each application.clientScopesGranted as claim}
134
+ {#each application.clientScopesGranted as claim (claim)}
135
135
  <span>
136
136
  {@render advancedMsg(claim)()}
137
137
  {#if claim !== application.clientScopesGranted[application.clientScopesGranted.length - 1]},&nbsp;{/if}
@@ -143,7 +143,7 @@
143
143
  </td>
144
144
 
145
145
  <td>
146
- {#each application.additionalGrants as grant}
146
+ {#each application.additionalGrants as grant (grant)}
147
147
  <span>
148
148
  {@render advancedMsg(grant)()}
149
149
  {#if grant !== application.additionalGrants[application.additionalGrants.length - 1]},&nbsp;{/if}
@@ -29,7 +29,7 @@
29
29
  </div>
30
30
  </div>
31
31
  <div id="federated-identities">
32
- {#each federatedIdentity.identities as identity}
32
+ {#each federatedIdentity.identities as identity (identity.providerId)}
33
33
  <div class="row margin-bottom">
34
34
  <div class="col-sm-2 col-md-2">
35
35
  <label
@@ -46,14 +46,14 @@
46
46
  </thead>
47
47
 
48
48
  <tbody>
49
- {#each log.events as event}
49
+ {#each log.events as event (event.event)}
50
50
  <tr>
51
51
  <td>{event.date ? new Date(event.date).toLocaleString() : ''}</td>
52
52
  <td>{event.event}</td>
53
53
  <td>{event.ipAddress}</td>
54
54
  <td>{event.client || ''}</td>
55
55
  <td>
56
- {#each event.details as detail, detailIndex}
56
+ {#each event.details as detail, detailIndex (detail.key)}
57
57
  <span>
58
58
  {`${detail.key} = ${detail.value}`}
59
59
  {#if detailIndex < event.details.length - 1},&nbsp;{/if}
@@ -108,7 +108,7 @@
108
108
  value={account.username ?? ''}
109
109
  autocomplete="username"
110
110
  readonly
111
- style:display={'none'}
111
+ style:display="none"
112
112
  />
113
113
 
114
114
  {#if password.passwordSet}
@@ -48,14 +48,14 @@
48
48
 
49
49
  <!-- svelte-ignore a11y_no_redundant_roles -->
50
50
  <tbody role="rowgroup">
51
- {#each sessions.sessions as session}
51
+ {#each sessions.sessions as session (session.id)}
52
52
  <tr>
53
53
  <td>{session.ipAddress}</td>
54
54
  <td>{session?.started}</td>
55
55
  <td>{session?.lastAccess}</td>
56
56
  <td>{session?.expires}</td>
57
57
  <td>
58
- {#each session.clients as client}
58
+ {#each session.clients as client (client)}
59
59
  <div>
60
60
  {client}
61
61
  <br />