@atlasauth/svelte 0.12.0 → 0.14.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @atlasauth/svelte changelog
2
2
 
3
+ ## 0.14.0 — 2026-11-05
4
+
5
+ ### Added
6
+
7
+ - Sign-in offers the emailed proof when a password is on hold, even with email code sign-in off, and shows the password field with a confirmation once it is proven.
8
+
9
+ ### Also
10
+
11
+ - The existing-account notice after a sign-up reaches an account on hold (`FlowState.existingAccount`), and the `account_deleted` error reason.
12
+
13
+ ## 0.13.0 — 2026-10-30
14
+
15
+ - `<SignIn>` offers "Sign in with a passkey" and passkey autofill on the identifier field when the instance enables passkeys.
16
+
3
17
  ## 0.12.0 — 2026-10-28
4
18
 
5
19
  - `ManageCiba` component lists sign-in approvals (approve or deny) and manages the CIBA PIN; mounted in the user profile.
@@ -1,5 +1,5 @@
1
1
  import { type Readable } from 'svelte/store';
2
- import { type OrganizationAuditLogOptions, type OrganizationAuditLogState, type CaptchaController, type FlowState, type InstanceSettings, type ProviderToken, type SignOutOptions, type SignOutResult, PolicyAcceptanceController, type MfaChoices, type MfaEnrollmentController, type MfaEnrollmentState } from '@atlasauth/js';
2
+ import { type OrganizationAuditLogOptions, type OrganizationAuditLogState, type CaptchaController, type FlowState, type InstanceSettings, type ProviderToken, type SignOutOptions, type SignOutResult, PolicyAcceptanceController, type MfaChoices, type MfaEnrollmentController, type MfaEnrollmentState, type PasskeySignInController } from '@atlasauth/js';
3
3
  import { type AuthStatus } from './context';
4
4
  import { type ProtectCondition } from './protect';
5
5
  import type { AtlasOrganizationMembership, AtlasSession, AtlasUser } from './types';
@@ -142,6 +142,8 @@ export interface FlowController {
142
142
  * for this before exchanging the ticket and finishing the sign-in.
143
143
  */
144
144
  saveRecoveryCodes(): void;
145
+ /** With `holdExistingAccountNotice`: the user read `pendingExistingAccountNotice($state)`; finish the sign-up. */
146
+ continueAfterExistingAccount(): void;
145
147
  /** Resend a sign-up's emailed code / link (the earlier one stops working). Resolves whether it was sent. */
146
148
  resendSignUp(): Promise<boolean>;
147
149
  /**
@@ -174,6 +176,20 @@ export interface FlowController {
174
176
  loadPolicies(): Promise<void>;
175
177
  /** The user declined a policy a sign-in was waiting on: cancels the attempt and says why. */
176
178
  declinePolicy(title: string): void;
179
+ /**
180
+ * "Continue with Atlas" (when `settings.signInWithAtlas` is set): starts the
181
+ * SSO sign-in and sends the browser to Atlas. Resolves the server's message
182
+ * when it could not start.
183
+ */
184
+ signInWithAtlas(connectionId: string): Promise<{
185
+ error?: string;
186
+ }>;
187
+ /**
188
+ * Passkey sign-in (the "Sign in with a passkey" button and passkey autofill on
189
+ * the identifier field), offered when `settings.passkeySignIn` is on. The
190
+ * outcome goes through the same completion as every sign-in.
191
+ */
192
+ passkey: PasskeySignInController;
177
193
  /** Stop the magic-link poll loop and remove the captcha widgets — call from `onDestroy`. */
178
194
  destroy(): void;
179
195
  }
@@ -184,4 +200,6 @@ export declare function signIn(): FlowController;
184
200
  * `create(values)` posts `/v1/client/sign_ups` (the account is created there),
185
201
  * then `submit({ code })` verifies the emailed code and completes the session.
186
202
  */
187
- export declare function signUp(): FlowController;
203
+ export declare function signUp(options?: {
204
+ holdExistingAccountNotice?: boolean;
205
+ }): FlowController;
package/dist/accessors.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { derived, get, readable, writable } from 'svelte/store';
2
- import { FapiClient, advanceWithCaptcha, atlasCaptchaLabels, createCaptchaController, createPasskeySignUp, createSignUp, finishPasskeySignUp, fetchInstanceSettings, fetchLastSignInMethod, flowNeedsCaptcha, signInCaptchaOptions, flowFromPending, pollAttempt, prepareFactor, shouldKeepPolling, createOrganizationAuditLog, createMfaEnrollment, acknowledgeRecoveryCodes, pendingRecoveryCodes, mfaChoicesFrom, prepareSecondFactorCode, resendSignUpVerification, PolicyAcceptanceController, loadPolicies as loadPolicyList, initialFlow as emptyFlow, } from '@atlasauth/js';
2
+ import { FapiClient, advanceWithCaptcha, atlasCaptchaLabels, attemptPasswordHoldProof, preparePasswordHoldProof, createCaptchaController, createPasskeySignInController, createPasskeySignUp, createSignUp, finishPasskeySignUp, fetchInstanceSettings, fetchLastSignInMethod, startSignInWithAtlas, flowNeedsCaptcha, signInCaptchaOptions, flowFromPending, pollAttempt, prepareFactor, shouldKeepPolling, createOrganizationAuditLog, createMfaEnrollment, acknowledgeExistingAccount, acknowledgeRecoveryCodes, pendingExistingAccountNotice, pendingRecoveryCodes, mfaChoicesFrom, prepareSecondFactorCode, resendSignUpVerification, PolicyAcceptanceController, loadPolicies as loadPolicyList, initialFlow as emptyFlow, } from '@atlasauth/js';
3
3
  import { useAtlas } from './context';
4
4
  import { translate } from './i18n';
5
5
  import { evaluate } from './protect';
@@ -89,7 +89,7 @@ export function getToken() {
89
89
  export function signOut(options) {
90
90
  return useAtlas().signOut(options);
91
91
  }
92
- function createFlow() {
92
+ function createFlow(options = {}) {
93
93
  const atlas = useAtlas();
94
94
  const client = new FapiClient({
95
95
  publishableKey: atlas.publishableKey,
@@ -176,6 +176,10 @@ function createFlow() {
176
176
  });
177
177
  exchanged = res.ok;
178
178
  }
179
+ if (exchanged && options.holdExistingAccountNotice && pendingExistingAccountNotice(next)) {
180
+ state.set({ ...next, ticket: null, busy: false });
181
+ return;
182
+ }
179
183
  const kept = exchanged && (await atlas.reload());
180
184
  state.set({ ...next, busy: false, sessionKept: kept });
181
185
  return;
@@ -183,9 +187,23 @@ function createFlow() {
183
187
  state.set(next);
184
188
  maybeStartPolling();
185
189
  }
190
+ // What lifts a password hold on this instance: the emailed code, or a link where it verifies by link only.
191
+ const holdProof = () => get(settings)?.account.emailVerification === 'link' ? 'email_link' : 'email_code';
186
192
  function submit(values) {
187
193
  void (async () => {
188
194
  state.update((current) => ({ ...current, busy: true, errors: [] }));
195
+ const { attempt, passwordHold, prepared } = get(state);
196
+ // A code that lifts a password hold goes to its own attempt, not this sign-in.
197
+ // `values.code`: "Use your password instead" leaves `prepared` set.
198
+ if (attempt?.status === 'needs_first_factor' &&
199
+ passwordHold &&
200
+ !passwordHold.released &&
201
+ prepared === 'email_code' &&
202
+ holdProof() === 'email_code' &&
203
+ values.code !== undefined) {
204
+ state.set(await attemptPasswordHoldProof(client, get(state), values.code));
205
+ return;
206
+ }
189
207
  const out = await advanceWithCaptcha(client, get(state), values, { captcha, identifier, t });
190
208
  identifier = out.identifier;
191
209
  await finish(out.state);
@@ -242,6 +260,9 @@ function createFlow() {
242
260
  function saveRecoveryCodes() {
243
261
  void finish(acknowledgeRecoveryCodes(get(state)));
244
262
  }
263
+ function continueAfterExistingAccount() {
264
+ void finish(acknowledgeExistingAccount(get(state)));
265
+ }
245
266
  async function resendSignUp() {
246
267
  state.update((current) => ({ ...current, busy: true, errors: [] }));
247
268
  const next = await resendSignUpVerification(client, get(state));
@@ -256,12 +277,24 @@ function createFlow() {
256
277
  }
257
278
  async function prepare(strategy) {
258
279
  state.update((current) => ({ ...current, busy: true, errors: [] }));
259
- const next = await prepareFactor(client, get(state), strategy);
280
+ const hold = get(state).passwordHold;
281
+ const proof = holdProof();
282
+ const next = hold && !hold.released && strategy === proof
283
+ ? await preparePasswordHoldProof(client, get(state), proof)
284
+ : await prepareFactor(client, get(state), strategy);
260
285
  state.set({ ...next, busy: false });
261
286
  maybeStartPolling();
262
287
  return next.errors.length === 0;
263
288
  }
289
+ const passkey = createPasskeySignInController({
290
+ client,
291
+ onStart: () => state.set({ ...get(state), busy: true, errors: [] }),
292
+ onResult: finish,
293
+ captcha: () => captcha,
294
+ cancelledMessage: () => t('signIn.passkeyCancelled'),
295
+ });
264
296
  function destroy() {
297
+ passkey.stopAutofill();
265
298
  stopPolling();
266
299
  unsubscribeCaptcha();
267
300
  unsubscribeEnrollment();
@@ -269,6 +302,16 @@ function createFlow() {
269
302
  captcha.destroy();
270
303
  signUpCaptcha.destroy();
271
304
  }
305
+ async function signInWithAtlas(connectionId) {
306
+ if (typeof window === 'undefined')
307
+ return {};
308
+ const started = await startSignInWithAtlas(client, connectionId, window.location.href);
309
+ if ('url' in started) {
310
+ window.location.assign(started.url);
311
+ return {};
312
+ }
313
+ return { error: started.error };
314
+ }
272
315
  return {
273
316
  state: { subscribe: state.subscribe },
274
317
  submit,
@@ -281,6 +324,7 @@ function createFlow() {
281
324
  enrollment,
282
325
  enrollmentState: { subscribe: enrollmentState.subscribe },
283
326
  saveRecoveryCodes,
327
+ continueAfterExistingAccount,
284
328
  resendSignUp,
285
329
  prepare,
286
330
  settings: { subscribe: settings.subscribe },
@@ -290,6 +334,8 @@ function createFlow() {
290
334
  policies,
291
335
  loadPolicies,
292
336
  declinePolicy,
337
+ signInWithAtlas,
338
+ passkey,
293
339
  destroy,
294
340
  };
295
341
  }
@@ -302,6 +348,6 @@ export function signIn() {
302
348
  * `create(values)` posts `/v1/client/sign_ups` (the account is created there),
303
349
  * then `submit({ code })` verifies the emailed code and completes the session.
304
350
  */
305
- export function signUp() {
306
- return createFlow();
351
+ export function signUp(options = {}) {
352
+ return createFlow(options);
307
353
  }
@@ -28,6 +28,7 @@ export let enrollmentState = null;
28
28
  export let emailVerification = "code";
29
29
  export let onResend = null;
30
30
  export let onPolicyDecline = null;
31
+ export let passwordHold = null;
31
32
  const atlas = useAtlas();
32
33
  const cls = (key, base) => classFor(key, atlas.appearance, base);
33
34
  const t = (key, vars) => translate(atlas.catalog, key, vars);
@@ -36,10 +37,22 @@ let values = {};
36
37
  $: step = attempt ? nextStep(attempt) : { kind: "collect_identifier" };
37
38
  const strategyName = (s) => typeof s === "string" ? s : String(s?.strategy ?? "");
38
39
  $: offered = step.kind === "collect_first_factor" ? offeredFirstFactors(step.strategies.map(strategyName), emailDelivery) : [];
39
- $: emailOptions = onPrepare ? offered.filter((s) => s === "email_code" || s === "email_link") : [];
40
+ let holdOption = null;
41
+ $: holdOption = passwordHold && !passwordHold.released && emailDelivery?.available !== false ? emailVerification === "link" ? "email_link" : "email_code" : null;
42
+ let emailOptions = [];
43
+ $: {
44
+ const listed = offered.filter((s) => s === "email_code" || s === "email_link");
45
+ emailOptions = !onPrepare ? [] : holdOption && !listed.includes(holdOption) ? [...listed, holdOption] : listed;
46
+ }
47
+ $: provedSignUp = step.kind === "collect_first_factor" && attempt?.object === "sign_up_attempt" && !(attempt.supported_first_factors ?? []).includes("passkey");
40
48
  $: plan = planFirstFactor(offered);
41
49
  $: showPassword = offered.includes("password") || emailOptions.length === 0;
42
50
  let prepared = null;
51
+ $: released = passwordHold?.released === true;
52
+ $: if (released) {
53
+ prepared = null;
54
+ values = {};
55
+ }
43
56
  $: sent = prepared && prepared.attemptId === (attempt?.id ?? null) ? prepared.strategy : null;
44
57
  async function prepare(strategy) {
45
58
  if (!onPrepare) return;
@@ -52,7 +65,7 @@ $: if (step.kind === "collect_first_factor" && onPrepare && plan.autoSend && att
52
65
  void prepare(plan.autoSend);
53
66
  }
54
67
  $: sending = step.kind === "collect_first_factor" && sent === null && !!onPrepare && !plan.password && emailOptions.length > 0;
55
- $: identifier = attempt?.identifier ?? "";
68
+ $: identifier = passwordHold?.email ?? attempt?.identifier ?? "";
56
69
  let emailed = null;
57
70
  $: emailedNow = emailed && emailed.attemptId === (attempt?.id ?? null) ? emailed : null;
58
71
  async function emailSecondFactor() {
@@ -85,8 +98,9 @@ function usePassword() {
85
98
  $: fields = (() => {
86
99
  switch (step.kind) {
87
100
  case "collect_identifier":
88
- return [{ name: "identifier", labelKey: "signIn.identifierLabel", type: "email" }];
101
+ return [{ name: "identifier", labelKey: "signIn.identifierLabel", type: "email", autocomplete: "username webauthn" }];
89
102
  case "collect_first_factor":
103
+ if (provedSignUp) return [];
90
104
  if (sent === "email_code") {
91
105
  return [{ name: "code", labelKey: "signIn.emailCodeLabel", type: "text" }];
92
106
  }
@@ -185,6 +199,9 @@ function handleSubmit(event) {
185
199
  {#if sending}
186
200
  <p class="atlas-text" aria-live="polite">{t('signIn.sending')}</p>
187
201
  {/if}
202
+ {#if provedSignUp || (step.kind === 'collect_first_factor' && released && sent === null)}
203
+ <p class="atlas-text" data-atlas-password-released="">{t('signIn.passwordHoldReleased')}</p>
204
+ {/if}
188
205
  {#if linkOnly}
189
206
  <p class="atlas-text" data-atlas-link-sent aria-live="polite">{t('signUp.linkSentTo', { email: identifier })}</p>
190
207
  {#if onResend}
@@ -288,6 +305,7 @@ function handleSubmit(event) {
288
305
  class={cls('formFieldInput', 'atlas-input')}
289
306
  type={f.type}
290
307
  name={f.name}
308
+ autocomplete={f.autocomplete}
291
309
  value={values[f.name] ?? ''}
292
310
  on:input={(e) => (values[f.name] = e.currentTarget.value)}
293
311
  />
@@ -1,5 +1,5 @@
1
1
  import { SvelteComponent } from "svelte";
2
- import { type AttemptView, type CaptchaController, type EmailDelivery, type FieldError, type MfaEnrollmentController, type MfaEnrollmentState } from '@atlasauth/js';
2
+ import { type AttemptView, type CaptchaController, type EmailDelivery, type FieldError, type FlowState, type MfaEnrollmentController, type MfaEnrollmentState } from '@atlasauth/js';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  /**
@@ -55,6 +55,7 @@ declare const __propDef: {
55
55
  */ emailVerification?: string;
56
56
  onResend?: (() => Promise<boolean>) | null;
57
57
  /** The user declined a policy the sign-in was waiting on (`needs_policy_acceptance`): cancel the attempt. */ onPolicyDecline?: ((title: string) => void) | null;
58
+ /** `FlowState.passwordHold`: offers the emailed proof, whichever factors the instance signs in with. */ passwordHold?: FlowState["passwordHold"];
58
59
  };
59
60
  events: {
60
61
  [evt: string]: CustomEvent<any>;
@@ -1,5 +1,5 @@
1
- <script>import { onDestroy } from "svelte";
2
- import { lastUsedMethodLabel, pendingRecoveryCodes, signUp as hostedSignUp } from "@atlasauth/js";
1
+ <script>import { onDestroy, onMount } from "svelte";
2
+ import { lastUsedMethodLabel, passkeysSupported, pendingRecoveryCodes, signUp as hostedSignUp } from "@atlasauth/js";
3
3
  import { signIn } from "../accessors";
4
4
  import { useAtlas } from "../context";
5
5
  import { classFor } from "../appearance";
@@ -34,6 +34,24 @@ $: recoveryCodes = pendingRecoveryCodes($flowState);
34
34
  $: lastLabel = !$flowState.attempt ? lastUsedMethodLabel($lastMethod, t) : null;
35
35
  const drawn = (..._deps) => flow.captcha.needed ? flow.captcha : null;
36
36
  $: captcha = drawn($settings, $flowState);
37
+ $: atlasConnection = !$flowState.attempt ? $settings?.signInWithAtlas?.connectionId ?? null : null;
38
+ let atlasError = null;
39
+ async function continueWithAtlas() {
40
+ if (!atlasConnection) return;
41
+ atlasError = null;
42
+ atlasError = (await flow.signInWithAtlas(atlasConnection)).error ?? null;
43
+ }
44
+ let supported = false;
45
+ onMount(() => {
46
+ supported = passkeysSupported();
47
+ });
48
+ $: passkeyOffered = supported && !$flowState.attempt && $settings?.passkeySignIn === true;
49
+ $: if (passkeyOffered) flow.passkey.armAutofill();
50
+ else flow.passkey.stopAutofill();
51
+ function submitIdentifier(values) {
52
+ flow.passkey.stopAutofill();
53
+ flow.submit(values);
54
+ }
37
55
  </script>
38
56
 
39
57
  {#if lastLabel}
@@ -42,6 +60,20 @@ $: captcha = drawn($settings, $flowState);
42
60
  </p>
43
61
  {/if}
44
62
 
63
+ {#if atlasConnection && !recoveryCodes}
64
+ <button
65
+ type="button"
66
+ class={classFor('socialButton', atlas.appearance, 'atlas-social-button')}
67
+ data-atlas-provider="atlas"
68
+ on:click={continueWithAtlas}
69
+ >
70
+ {t('signIn.continueWithAtlas')}
71
+ </button>
72
+ {#if atlasError}
73
+ <p class={classFor('formFieldError', atlas.appearance, 'atlas-error')} role="alert">{atlasError}</p>
74
+ {/if}
75
+ {/if}
76
+
45
77
  {#if recoveryCodes}
46
78
  <RecoveryCodes codes={recoveryCodes} busy={$flowState.busy} onSaved={flow.saveRecoveryCodes} />
47
79
  {:else}
@@ -51,8 +83,10 @@ $: captcha = drawn($settings, $flowState);
51
83
  errors={$flowState.errors}
52
84
  sessionKept={$flowState.sessionKept}
53
85
  titleKey="signIn.title"
54
- onSubmit={flow.submit}
86
+ onSubmit={submitIdentifier}
55
87
  onPrepare={flow.prepare}
88
+ passwordHold={$flowState.passwordHold ?? null}
89
+ emailVerification={$settings?.account.emailVerification ?? 'code'}
56
90
  onEmailSecondFactor={$settings?.account.emailSecondFactor ? flow.sendEmailSecondFactor : null}
57
91
  onSmsSecondFactor={$settings && flow.mfaChoices().sms ? flow.sendSmsSecondFactor : null}
58
92
  enrollment={flow.enrollment}
@@ -63,6 +97,18 @@ $: captcha = drawn($settings, $flowState);
63
97
  />
64
98
  {/if}
65
99
 
100
+ {#if passkeyOffered && !recoveryCodes}
101
+ <button
102
+ type="button"
103
+ class={classFor('socialButton', atlas.appearance, 'atlas-social-button atlas-passkey-button')}
104
+ data-atlas-passkey-sign-in=""
105
+ disabled={$flowState.busy}
106
+ on:click={() => flow.passkey.signIn()}
107
+ >
108
+ {t('signIn.passkeyButton')}
109
+ </button>
110
+ {/if}
111
+
66
112
  {#if promptHref}
67
113
  <p class={classFor('footerAction', atlas.appearance, 'atlas-footer')} data-atlas-sign-up-prompt="">
68
114
  {t('signIn.noAccount')} <a class="atlas-link" href={promptHref}>{t('signIn.signUpLink')}</a>
@@ -1,11 +1,18 @@
1
1
  <script>import { onDestroy, onMount } from "svelte";
2
- import { awaitingPasskey, passkeysSupported } from "@atlasauth/js";
2
+ import { awaitingPasskey, existingAccountResetUrl, passkeysSupported, pendingExistingAccountNotice } from "@atlasauth/js";
3
3
  import { signUp } from "../accessors";
4
+ import { classFor } from "../appearance";
5
+ import { useAtlas } from "../context";
6
+ import { translate } from "../i18n";
4
7
  import AttemptFlow from "./AttemptFlow.svelte";
5
8
  import PasskeySignUpStep from "./PasskeySignUpStep.svelte";
6
9
  import SignUpForm from "./SignUpForm.svelte";
7
10
  export let afterUrl = void 0;
8
- const flow = signUp();
11
+ export let resetPasswordUrl = void 0;
12
+ const atlas = useAtlas();
13
+ const cls = (key, base) => classFor(key, atlas.appearance, base);
14
+ const t = (key) => translate(atlas.catalog, key);
15
+ const flow = signUp({ holdExistingAccountNotice: true });
9
16
  const flowState = flow.state;
10
17
  const settings = flow.settings;
11
18
  onDestroy(() => flow.destroy());
@@ -23,7 +30,19 @@ function switchMode() {
23
30
  }
24
31
  </script>
25
32
 
26
- {#if $flowState.attempt && awaitingPasskey($flowState.attempt)}
33
+ {#if pendingExistingAccountNotice($flowState)}
34
+ {@const resetHref = existingAccountResetUrl({ url: resetPasswordUrl, frontendApi: atlas.frontendApi, redirectUrl: afterUrl })}
35
+ <div class={cls('card', 'atlas-card')} data-atlas-existing-account="">
36
+ <h1 class={cls('headerTitle', 'atlas-title')}>{t('signUp.title')}</h1>
37
+ <p class="atlas-text">{t('signUp.existingAccount')}</p>
38
+ {#if resetHref}
39
+ <p class="atlas-text"><a class="atlas-link" href={resetHref}>{t('signIn.forgotPassword')}</a></p>
40
+ {/if}
41
+ <button class={cls('formButtonPrimary', 'atlas-button')} type="button" disabled={$flowState.busy} on:click={() => flow.continueAfterExistingAccount()}>
42
+ {t('signUp.submit')}
43
+ </button>
44
+ </div>
45
+ {:else if $flowState.attempt && awaitingPasskey($flowState.attempt)}
27
46
  <PasskeySignUpStep busy={$flowState.busy} errors={$flowState.errors} onCreate={flow.createPasskey} />
28
47
  {:else if $flowState.attempt}
29
48
  <AttemptFlow
@@ -8,6 +8,7 @@ declare const __propDef: {
8
8
  * `/v1/client/sign_ups`; from there the flow is server-driven exactly like
9
9
  * `<SignIn/>` (the emailed-code step, then the ticket exchange).
10
10
  */ afterUrl?: string | undefined;
11
+ /** Where the existing-account notice's "Forgot password?" goes. Default: the hosted sign-in page; `null` hides it. */ resetPasswordUrl?: string | null | undefined;
11
12
  };
12
13
  events: {
13
14
  [evt: string]: CustomEvent<any>;
package/dist/i18n.js CHANGED
@@ -22,6 +22,7 @@ export const EN_US = {
22
22
  'signIn.signUpLink': 'Sign up',
23
23
  'signIn.orDivider': 'or',
24
24
  'signIn.socialButton': 'Continue with {provider}',
25
+ 'signIn.continueWithAtlas': 'Continue with Atlas',
25
26
  'signIn.emailCodeLabel': 'Verification code',
26
27
  'signIn.emailCodeOption': 'Email me a code',
27
28
  'signIn.emailLinkOption': 'Email me a sign-in link',
@@ -32,6 +33,10 @@ export const EN_US = {
32
33
  'signIn.resendCode': 'Resend code',
33
34
  'signIn.resendLink': 'Resend link',
34
35
  'signIn.passwordOption': 'Use your password instead',
36
+ 'signIn.passwordHoldReleased': 'Your email is verified. Enter your password to sign in.',
37
+ 'signUp.existingAccount': 'You already had an account. Your existing password still applies.',
38
+ 'signIn.passkeyButton': 'Sign in with a passkey',
39
+ 'signIn.passkeyCancelled': "Passkey sign-in didn't finish. Try again, or use another way to sign in.",
35
40
  'signIn.signedIn': 'You\'re signed in.',
36
41
  'signIn.sessionNotKept': 'You signed in, but this browser didn\'t keep the session. If it blocks third-party cookies, allow cookies for this site and try again.',
37
42
  'signIn.checkOtherTab': 'You can close this tab — you are signed in where you started.',
@@ -184,6 +189,9 @@ export const EN_US = {
184
189
  'error.email_delivery_unavailable': "This app can't send email right now. Try another sign-in method or contact the app owner.",
185
190
  'error.strategy_disabled': 'This sign-in method is not available for this app.',
186
191
  'error.sign_up_restricted': 'Sign-up on this app is by invitation only.',
192
+ 'error.sign_up_denied': 'Sign-up is not available for this account.',
193
+ 'error.password_not_yet_usable': 'Verify your email address before signing in with this password.',
194
+ 'error.account_deleted': 'The account for this address was deleted, so it can’t be used to sign up again.',
187
195
  'error.waitlisted': "You're on the waitlist. We'll email you when a place opens up.",
188
196
  'error.identifier_not_allowed': 'This email or phone number is not allowed on this app.',
189
197
  'error.disposable_email_blocked': 'Sign-up with a disposable or temporary email address is not allowed.',
@@ -192,6 +200,7 @@ export const EN_US = {
192
200
  'error.sign_ups_disabled': 'Sign-ups are temporarily disabled.',
193
201
  'error.high_risk_blocked': 'This sign-in was blocked because it looked unusual.',
194
202
  'error.sms_region_blocked': 'Text messages are not available for this phone number.',
203
+ 'error.github_team_required': 'Your GitHub account is not a member of a GitHub organization or team allowed to sign in here.',
195
204
  };
196
205
  /**
197
206
  * Look up a key and interpolate `{placeholders}`.
package/dist/version.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import type { AtlasSdkInfo } from '@atlasauth/js';
2
2
  /** This package's version, sent as `X-Atlas-SDK` (kept in step with package.json by a test). */
3
- export declare const ATLAS_SVELTE_VERSION = "0.11.0";
3
+ export declare const ATLAS_SVELTE_VERSION = "0.14.0";
4
4
  export declare const ATLAS_SVELTE_SDK: AtlasSdkInfo;
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /** This package's version, sent as `X-Atlas-SDK` (kept in step with package.json by a test). */
2
- export const ATLAS_SVELTE_VERSION = '0.11.0';
2
+ export const ATLAS_SVELTE_VERSION = '0.14.0';
3
3
  export const ATLAS_SVELTE_SDK = { name: '@atlasauth/svelte', version: ATLAS_SVELTE_VERSION };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlasauth/svelte",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "type": "module",
5
5
  "svelte": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -23,9 +23,9 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@atlasauth/design": "0.3.0",
26
- "@atlasauth/js": "0.26.1",
26
+ "@atlasauth/js": "0.32.0",
27
27
  "@atlasauth/authz": "0.3.0",
28
- "@atlasauth/backend": "0.27.0"
28
+ "@atlasauth/backend": "0.38.0"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "svelte": ">=4",