@dloizides/auth-web 1.14.0 → 1.17.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/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { StyleSheet, Platform, View, Text, TextInput, TouchableOpacity, ActivityIndicator, Pressable } from 'react-native';
1
+ import { StyleSheet, Platform, View, Text, TextInput, TouchableOpacity, ActivityIndicator, Pressable, ScrollView } from 'react-native';
2
2
  import { createContext, useContext, useMemo, useState, useRef, useEffect, useCallback } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useMutation } from '@tanstack/react-query';
@@ -307,6 +307,29 @@ var DEFAULT_RESET_PASSWORD_LABELS = {
307
307
  errorNetwork: "Something went wrong. Please try again."
308
308
  };
309
309
 
310
+ // src/components/labels/accountSettingsLabels.ts
311
+ var DEFAULT_ACCOUNT_SETTINGS_LABELS = {
312
+ heading: "Account settings",
313
+ changePasswordTitle: "Change password",
314
+ changePasswordDescription: "Update the password you use to sign in.",
315
+ currentPasswordLabel: "Current password",
316
+ currentPasswordPlaceholder: "Enter your current password",
317
+ newPasswordLabel: "New password",
318
+ newPasswordPlaceholder: "Enter a new password",
319
+ confirmPasswordLabel: "Confirm new password",
320
+ confirmPasswordPlaceholder: "Re-enter your new password",
321
+ submit: "Change password",
322
+ submitting: "Changing password...",
323
+ submitHint: "Submit the form to change your password",
324
+ success: "Your password has been changed.",
325
+ errorWeakNewPassword: "Your new password must be at least 8 characters and include an uppercase letter, a lowercase letter and a number.",
326
+ errorMismatch: "The new password and its confirmation do not match.",
327
+ errorCurrentRequired: "Enter your current password.",
328
+ errorInvalidCurrent: "Your current password is incorrect, or the new password does not meet the policy.",
329
+ errorUnauthorized: "Your session has expired. Sign in again to change your password.",
330
+ errorFailed: "Could not change your password. Try again later."
331
+ };
332
+
310
333
  // src/components/testIds.ts
311
334
  var AuthTestIds = {
312
335
  loginForm: "auth-login-form",
@@ -380,8 +403,19 @@ var AuthTestIds = {
380
403
  preferredMethodSettingsError: "auth-preferred-method-settings-error",
381
404
  // Preferred-method login-screen hint
382
405
  preferredMethodHint: "auth-preferred-method-hint",
406
+ // Account-settings screen shell + in-app change-password form
407
+ accountSettings: "auth-account-settings",
408
+ accountSettingsChangePassword: "auth-account-settings-change-password",
409
+ changePasswordCurrentInput: "auth-change-password-current",
410
+ changePasswordNewInput: "auth-change-password-new",
411
+ changePasswordConfirmInput: "auth-change-password-confirm",
412
+ changePasswordSubmit: "auth-change-password-submit",
413
+ changePasswordError: "auth-change-password-error",
414
+ changePasswordSuccess: "auth-change-password-success",
383
415
  // Public-demo credentials panel
384
416
  demoCredentialsHint: "auth-demo-credentials-hint",
417
+ // Per-account heading, present only when >1 account is published (multi-account).
418
+ demoCredentialsAccountLabel: "auth-demo-credentials-account-label",
385
419
  demoCredentialsUsername: "auth-demo-credentials-username",
386
420
  demoCredentialsPassword: "auth-demo-credentials-password",
387
421
  demoCredentialsUseButton: "auth-demo-credentials-use",
@@ -3201,6 +3235,307 @@ function PreferredMethodSettingsCard({
3201
3235
  }
3202
3236
  );
3203
3237
  }
3238
+
3239
+ // src/password/ChangePasswordErrorKey.ts
3240
+ var ChangePasswordErrorKey = /* @__PURE__ */ ((ChangePasswordErrorKey2) => {
3241
+ ChangePasswordErrorKey2["WeakNewPassword"] = "weak_new_password";
3242
+ ChangePasswordErrorKey2["Mismatch"] = "mismatch";
3243
+ ChangePasswordErrorKey2["CurrentRequired"] = "current_required";
3244
+ ChangePasswordErrorKey2["InvalidCurrent"] = "invalid_current";
3245
+ ChangePasswordErrorKey2["Unauthorized"] = "unauthorized";
3246
+ ChangePasswordErrorKey2["Failed"] = "failed";
3247
+ return ChangePasswordErrorKey2;
3248
+ })(ChangePasswordErrorKey || {});
3249
+ function errorKeyForStatus(status) {
3250
+ if (status === "invalidCurrent") {
3251
+ return "invalid_current" /* InvalidCurrent */;
3252
+ }
3253
+ if (status === "unauthorized") {
3254
+ return "unauthorized" /* Unauthorized */;
3255
+ }
3256
+ return "failed" /* Failed */;
3257
+ }
3258
+ function useChangePassword({
3259
+ client,
3260
+ onChanged
3261
+ }) {
3262
+ const [currentPassword, setCurrentValue] = useState("");
3263
+ const [newPassword, setNewValue] = useState("");
3264
+ const [confirmPassword, setConfirmValue] = useState("");
3265
+ const [submitting, setSubmitting] = useState(false);
3266
+ const [succeeded, setSucceeded] = useState(false);
3267
+ const [errorKey, setErrorKey] = useState(null);
3268
+ const clearStatus = useCallback(() => {
3269
+ setErrorKey(null);
3270
+ setSucceeded(false);
3271
+ }, []);
3272
+ const setCurrentPassword = useCallback((value) => {
3273
+ setCurrentValue(value);
3274
+ clearStatus();
3275
+ }, [clearStatus]);
3276
+ const setNewPassword = useCallback((value) => {
3277
+ setNewValue(value);
3278
+ clearStatus();
3279
+ }, [clearStatus]);
3280
+ const setConfirmPassword = useCallback((value) => {
3281
+ setConfirmValue(value);
3282
+ clearStatus();
3283
+ }, [clearStatus]);
3284
+ const reset = useCallback(() => {
3285
+ setCurrentValue("");
3286
+ setNewValue("");
3287
+ setConfirmValue("");
3288
+ setSubmitting(false);
3289
+ setSucceeded(false);
3290
+ setErrorKey(null);
3291
+ }, []);
3292
+ const submit = useCallback(() => {
3293
+ if (currentPassword === "") {
3294
+ setErrorKey("current_required" /* CurrentRequired */);
3295
+ return;
3296
+ }
3297
+ if (newPassword !== confirmPassword) {
3298
+ setErrorKey("mismatch" /* Mismatch */);
3299
+ return;
3300
+ }
3301
+ if (!isPasswordValid(newPassword)) {
3302
+ setErrorKey("weak_new_password" /* WeakNewPassword */);
3303
+ return;
3304
+ }
3305
+ setErrorKey(null);
3306
+ setSucceeded(false);
3307
+ setSubmitting(true);
3308
+ client.changePassword({ currentPassword, newPassword }).then((result) => {
3309
+ if (result.status === "success") {
3310
+ setCurrentValue("");
3311
+ setNewValue("");
3312
+ setConfirmValue("");
3313
+ setSucceeded(true);
3314
+ onChanged?.();
3315
+ return;
3316
+ }
3317
+ setErrorKey(errorKeyForStatus(result.status));
3318
+ }).catch(() => {
3319
+ setErrorKey("failed" /* Failed */);
3320
+ }).finally(() => {
3321
+ setSubmitting(false);
3322
+ });
3323
+ }, [client, currentPassword, newPassword, confirmPassword, onChanged]);
3324
+ return {
3325
+ currentPassword,
3326
+ newPassword,
3327
+ confirmPassword,
3328
+ setCurrentPassword,
3329
+ setNewPassword,
3330
+ setConfirmPassword,
3331
+ submitting,
3332
+ succeeded,
3333
+ errorKey,
3334
+ submit,
3335
+ reset
3336
+ };
3337
+ }
3338
+ function errorMessage2(errorKey, labels) {
3339
+ switch (errorKey) {
3340
+ case "weak_new_password" /* WeakNewPassword */:
3341
+ return labels.errorWeakNewPassword;
3342
+ case "mismatch" /* Mismatch */:
3343
+ return labels.errorMismatch;
3344
+ case "current_required" /* CurrentRequired */:
3345
+ return labels.errorCurrentRequired;
3346
+ case "invalid_current" /* InvalidCurrent */:
3347
+ return labels.errorInvalidCurrent;
3348
+ case "unauthorized" /* Unauthorized */:
3349
+ return labels.errorUnauthorized;
3350
+ case "failed" /* Failed */:
3351
+ return labels.errorFailed;
3352
+ default:
3353
+ return null;
3354
+ }
3355
+ }
3356
+ function ChangePasswordCard({
3357
+ client,
3358
+ theme: themeProp,
3359
+ labels: labelsProp,
3360
+ testIdPrefix,
3361
+ onChanged
3362
+ }) {
3363
+ const theme = useAuthTheme(themeProp);
3364
+ const styles3 = useAuthStyles(theme);
3365
+ const labels = useMemo(
3366
+ () => ({ ...DEFAULT_ACCOUNT_SETTINGS_LABELS, ...labelsProp }),
3367
+ [labelsProp]
3368
+ );
3369
+ const form = useChangePassword({ client, onChanged });
3370
+ const message = errorMessage2(form.errorKey, labels);
3371
+ return /* @__PURE__ */ jsxs(
3372
+ View,
3373
+ {
3374
+ style: styles3.card,
3375
+ testID: withTestIdPrefix(AuthTestIds.accountSettingsChangePassword, testIdPrefix),
3376
+ children: [
3377
+ /* @__PURE__ */ jsx(Text, { style: styles3.title, children: labels.changePasswordTitle }),
3378
+ /* @__PURE__ */ jsx(Text, { style: styles3.subtitle, children: labels.changePasswordDescription }),
3379
+ /* @__PURE__ */ jsxs(View, { style: styles3.fieldGroup, children: [
3380
+ /* @__PURE__ */ jsx(Text, { style: styles3.label, children: labels.currentPasswordLabel }),
3381
+ /* @__PURE__ */ jsx(
3382
+ TextInput,
3383
+ {
3384
+ accessibilityLabel: labels.currentPasswordLabel,
3385
+ autoComplete: "current-password",
3386
+ placeholder: labels.currentPasswordPlaceholder,
3387
+ placeholderTextColor: theme.colors.textSecondary,
3388
+ secureTextEntry: true,
3389
+ style: styles3.input,
3390
+ testID: withTestIdPrefix(AuthTestIds.changePasswordCurrentInput, testIdPrefix),
3391
+ value: form.currentPassword,
3392
+ onChangeText: form.setCurrentPassword
3393
+ }
3394
+ )
3395
+ ] }),
3396
+ /* @__PURE__ */ jsxs(View, { style: styles3.fieldGroup, children: [
3397
+ /* @__PURE__ */ jsx(Text, { style: styles3.label, children: labels.newPasswordLabel }),
3398
+ /* @__PURE__ */ jsx(
3399
+ TextInput,
3400
+ {
3401
+ accessibilityLabel: labels.newPasswordLabel,
3402
+ autoComplete: "new-password",
3403
+ placeholder: labels.newPasswordPlaceholder,
3404
+ placeholderTextColor: theme.colors.textSecondary,
3405
+ secureTextEntry: true,
3406
+ style: styles3.input,
3407
+ testID: withTestIdPrefix(AuthTestIds.changePasswordNewInput, testIdPrefix),
3408
+ value: form.newPassword,
3409
+ onChangeText: form.setNewPassword
3410
+ }
3411
+ )
3412
+ ] }),
3413
+ /* @__PURE__ */ jsxs(View, { style: styles3.fieldGroup, children: [
3414
+ /* @__PURE__ */ jsx(Text, { style: styles3.label, children: labels.confirmPasswordLabel }),
3415
+ /* @__PURE__ */ jsx(
3416
+ TextInput,
3417
+ {
3418
+ accessibilityLabel: labels.confirmPasswordLabel,
3419
+ autoComplete: "new-password",
3420
+ placeholder: labels.confirmPasswordPlaceholder,
3421
+ placeholderTextColor: theme.colors.textSecondary,
3422
+ secureTextEntry: true,
3423
+ style: styles3.input,
3424
+ testID: withTestIdPrefix(AuthTestIds.changePasswordConfirmInput, testIdPrefix),
3425
+ value: form.confirmPassword,
3426
+ onChangeText: form.setConfirmPassword
3427
+ }
3428
+ )
3429
+ ] }),
3430
+ message !== null ? /* @__PURE__ */ jsx(
3431
+ Text,
3432
+ {
3433
+ style: styles3.errorText,
3434
+ testID: withTestIdPrefix(AuthTestIds.changePasswordError, testIdPrefix),
3435
+ children: message
3436
+ }
3437
+ ) : null,
3438
+ form.succeeded ? /* @__PURE__ */ jsx(
3439
+ Text,
3440
+ {
3441
+ style: styles3.successText,
3442
+ testID: withTestIdPrefix(AuthTestIds.changePasswordSuccess, testIdPrefix),
3443
+ children: labels.success
3444
+ }
3445
+ ) : null,
3446
+ /* @__PURE__ */ jsx(
3447
+ TouchableOpacity,
3448
+ {
3449
+ accessibilityHint: labels.submitHint,
3450
+ accessibilityLabel: form.submitting ? labels.submitting : labels.submit,
3451
+ accessibilityRole: "button",
3452
+ disabled: form.submitting,
3453
+ style: form.submitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton,
3454
+ testID: withTestIdPrefix(AuthTestIds.changePasswordSubmit, testIdPrefix),
3455
+ onPress: form.submit,
3456
+ children: form.submitting ? /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsx(Text, { style: styles3.primaryButtonText, children: labels.submit })
3457
+ }
3458
+ )
3459
+ ]
3460
+ }
3461
+ );
3462
+ }
3463
+ var GAP = 16;
3464
+ var layout = StyleSheet.create({
3465
+ content: {
3466
+ width: "100%",
3467
+ alignItems: "center",
3468
+ rowGap: GAP
3469
+ }
3470
+ });
3471
+ function AccountSettingsScreen({
3472
+ changePassword,
3473
+ devicePin,
3474
+ passkeys,
3475
+ preferredMethod,
3476
+ theme: themeProp,
3477
+ labels: labelsProp,
3478
+ testIdPrefix
3479
+ }) {
3480
+ const theme = useAuthTheme(themeProp);
3481
+ const styles3 = useAuthStyles(theme);
3482
+ const labels = useMemo(
3483
+ () => ({ ...DEFAULT_ACCOUNT_SETTINGS_LABELS, ...labelsProp }),
3484
+ [labelsProp]
3485
+ );
3486
+ return /* @__PURE__ */ jsx(
3487
+ ScrollView,
3488
+ {
3489
+ contentContainerStyle: styles3.screen,
3490
+ testID: withTestIdPrefix(AuthTestIds.accountSettings, testIdPrefix),
3491
+ children: /* @__PURE__ */ jsxs(View, { style: layout.content, children: [
3492
+ /* @__PURE__ */ jsx(Text, { style: styles3.title, children: labels.heading }),
3493
+ /* @__PURE__ */ jsx(
3494
+ ChangePasswordCard,
3495
+ {
3496
+ client: changePassword.client,
3497
+ labels: labelsProp,
3498
+ testIdPrefix,
3499
+ theme,
3500
+ onChanged: changePassword.onChanged
3501
+ }
3502
+ ),
3503
+ devicePin !== void 0 ? /* @__PURE__ */ jsx(
3504
+ DevicePinSettingsCard,
3505
+ {
3506
+ client: devicePin.client,
3507
+ enrollLabels: devicePin.enrollLabels,
3508
+ initialHasPin: devicePin.initialHasPin,
3509
+ labels: devicePin.labels,
3510
+ testIdPrefix,
3511
+ theme,
3512
+ onChanged: devicePin.onChanged
3513
+ }
3514
+ ) : null,
3515
+ passkeys !== void 0 ? /* @__PURE__ */ jsx(
3516
+ PasskeySettingsCard,
3517
+ {
3518
+ labels: passkeys.labels,
3519
+ returnUrl: passkeys.returnUrl,
3520
+ testIdPrefix,
3521
+ theme
3522
+ }
3523
+ ) : null,
3524
+ preferredMethod !== void 0 ? /* @__PURE__ */ jsx(
3525
+ PreferredMethodSettingsCard,
3526
+ {
3527
+ availableMethods: preferredMethod.availableMethods,
3528
+ client: preferredMethod.client,
3529
+ labels: preferredMethod.labels,
3530
+ testIdPrefix,
3531
+ theme,
3532
+ onChanged: preferredMethod.onChanged
3533
+ }
3534
+ ) : null
3535
+ ] })
3536
+ }
3537
+ );
3538
+ }
3204
3539
  function hintFor(method, labels) {
3205
3540
  if (method === "password") {
3206
3541
  return labels.password;
@@ -3237,9 +3572,21 @@ function DemoCredentialsBody({
3237
3572
  styles: styles3,
3238
3573
  authStyles,
3239
3574
  testIdPrefix,
3575
+ accountLabel,
3576
+ testIdIndex,
3240
3577
  onUse
3241
3578
  }) {
3579
+ const testId = (base) => withTestIdPrefix(testIdIndex === void 0 ? base : `${base}-${testIdIndex}`, testIdPrefix);
3580
+ const hasLabel = typeof accountLabel === "string" && accountLabel.length > 0;
3242
3581
  return /* @__PURE__ */ jsxs(View, { children: [
3582
+ hasLabel ? /* @__PURE__ */ jsx(
3583
+ Text,
3584
+ {
3585
+ style: styles3.accountLabel,
3586
+ testID: testId(AuthTestIds.demoCredentialsAccountLabel),
3587
+ children: accountLabel
3588
+ }
3589
+ ) : null,
3243
3590
  /* @__PURE__ */ jsxs(View, { style: styles3.row, children: [
3244
3591
  /* @__PURE__ */ jsx(Text, { style: styles3.rowLabel, children: labels.usernameLabel }),
3245
3592
  /* @__PURE__ */ jsx(
@@ -3247,7 +3594,7 @@ function DemoCredentialsBody({
3247
3594
  {
3248
3595
  selectable: true,
3249
3596
  style: styles3.rowValue,
3250
- testID: withTestIdPrefix(AuthTestIds.demoCredentialsUsername, testIdPrefix),
3597
+ testID: testId(AuthTestIds.demoCredentialsUsername),
3251
3598
  children: credentials.username
3252
3599
  }
3253
3600
  )
@@ -3259,7 +3606,7 @@ function DemoCredentialsBody({
3259
3606
  {
3260
3607
  selectable: true,
3261
3608
  style: styles3.rowValue,
3262
- testID: withTestIdPrefix(AuthTestIds.demoCredentialsPassword, testIdPrefix),
3609
+ testID: testId(AuthTestIds.demoCredentialsPassword),
3263
3610
  children: credentials.password
3264
3611
  }
3265
3612
  )
@@ -3271,7 +3618,7 @@ function DemoCredentialsBody({
3271
3618
  accessibilityLabel: labels.useCredentials,
3272
3619
  accessibilityRole: "button",
3273
3620
  style: [authStyles.secondaryButton, styles3.useButton],
3274
- testID: withTestIdPrefix(AuthTestIds.demoCredentialsUseButton, testIdPrefix),
3621
+ testID: testId(AuthTestIds.demoCredentialsUseButton),
3275
3622
  onPress: onUse,
3276
3623
  children: /* @__PURE__ */ jsx(Text, { style: authStyles.secondaryButtonText, children: labels.useCredentials })
3277
3624
  }
@@ -3324,6 +3671,15 @@ function useDemoCredentialsStyles(theme) {
3324
3671
  marginBottom: spacing.sm,
3325
3672
  color: colors.textSecondary
3326
3673
  },
3674
+ accountLabel: {
3675
+ fontSize: typography.caption,
3676
+ fontWeight: "700",
3677
+ color: colors.text,
3678
+ // Separates one account block from the previous one; the first block sits
3679
+ // under the panel description / disclosure divider, which already spaces it.
3680
+ marginTop: spacing.sm,
3681
+ marginBottom: spacing.xs / HALF
3682
+ },
3327
3683
  row: {
3328
3684
  flexDirection: "row",
3329
3685
  alignItems: "center",
@@ -3399,8 +3755,39 @@ function resolveDemoCredentials(credentials) {
3399
3755
  }
3400
3756
  return { username, password };
3401
3757
  }
3758
+
3759
+ // src/demo/resolveDemoAccounts.ts
3760
+ function resolveAccount(account) {
3761
+ if (account === void 0 || account === null) {
3762
+ return null;
3763
+ }
3764
+ const pair = resolveDemoCredentials(account);
3765
+ if (pair === null) {
3766
+ return null;
3767
+ }
3768
+ const label = typeof account.label === "string" ? account.label : "";
3769
+ return { label, username: pair.username, password: pair.password };
3770
+ }
3771
+ function resolveAccountList(accounts) {
3772
+ if (!Array.isArray(accounts)) {
3773
+ return [];
3774
+ }
3775
+ return accounts.map(resolveAccount).filter((account) => account !== null);
3776
+ }
3777
+ function resolveDemoAccounts(credentials) {
3778
+ if (credentials === void 0 || credentials === null) {
3779
+ return [];
3780
+ }
3781
+ const fromList = resolveAccountList(credentials.publishedAccounts);
3782
+ if (fromList.length > 0) {
3783
+ return fromList;
3784
+ }
3785
+ const single = resolveDemoCredentials(credentials);
3786
+ return single === null ? [] : [{ label: "", username: single.username, password: single.password }];
3787
+ }
3402
3788
  function DemoCredentialsHint({
3403
3789
  credentials,
3790
+ accounts,
3404
3791
  variant = "disclosure" /* Disclosure */,
3405
3792
  theme: themeProp,
3406
3793
  labels: labelsProp,
@@ -3415,29 +3802,35 @@ function DemoCredentialsHint({
3415
3802
  () => ({ ...DEFAULT_DEMO_CREDENTIALS_HINT_LABELS, ...labelsProp }),
3416
3803
  [labelsProp]
3417
3804
  );
3418
- const resolved = useMemo(() => resolveDemoCredentials(credentials), [credentials]);
3419
- const handleUse = useCallback(() => {
3420
- if (resolved !== null && onUse !== void 0) {
3421
- onUse(resolved);
3422
- }
3423
- }, [resolved, onUse]);
3805
+ const resolvedAccounts = useMemo(
3806
+ () => accounts !== void 0 && accounts.length > 0 ? resolveAccountList(accounts) : resolveDemoAccounts(credentials),
3807
+ [accounts, credentials]
3808
+ );
3809
+ const makeUse = useCallback(
3810
+ (account) => onUse === void 0 ? void 0 : () => onUse({ username: account.username, password: account.password }),
3811
+ [onUse]
3812
+ );
3424
3813
  const handleToggle = useCallback(() => {
3425
3814
  setExpanded((current) => !current);
3426
3815
  }, []);
3427
- if (resolved === null) {
3816
+ if (resolvedAccounts.length === 0) {
3428
3817
  return null;
3429
3818
  }
3430
- const body = /* @__PURE__ */ jsx(
3819
+ const isSingle = resolvedAccounts.length === 1;
3820
+ const body = resolvedAccounts.map((account, index) => /* @__PURE__ */ jsx(
3431
3821
  DemoCredentialsBody,
3432
3822
  {
3823
+ accountLabel: isSingle ? void 0 : account.label,
3433
3824
  authStyles,
3434
- credentials: resolved,
3825
+ credentials: { username: account.username, password: account.password },
3435
3826
  labels,
3436
3827
  styles: styles3,
3828
+ testIdIndex: isSingle ? void 0 : index,
3437
3829
  testIdPrefix,
3438
- onUse: onUse === void 0 ? void 0 : handleUse
3439
- }
3440
- );
3830
+ onUse: makeUse(account)
3831
+ },
3832
+ `${account.username}-${String(index)}`
3833
+ ));
3441
3834
  if (variant === "panel" /* Panel */) {
3442
3835
  return /* @__PURE__ */ jsxs(
3443
3836
  View,
@@ -3593,7 +3986,11 @@ function useDemoCredentials({
3593
3986
  credentials,
3594
3987
  prefillOnMount = false
3595
3988
  } = {}) {
3596
- const resolved = useMemo(() => resolveDemoCredentials(credentials), [credentials]);
3989
+ const accounts = useMemo(() => resolveDemoAccounts(credentials), [credentials]);
3990
+ const resolved = useMemo(() => {
3991
+ const first = accounts[0];
3992
+ return first === void 0 ? null : { username: first.username, password: first.password };
3993
+ }, [accounts]);
3597
3994
  const [filled, setFilled] = useState(
3598
3995
  prefillOnMount ? resolved : null
3599
3996
  );
@@ -3625,11 +4022,12 @@ function useDemoCredentials({
3625
4022
  prefillIntent
3626
4023
  },
3627
4024
  // `credentials` is passed through unresolved on purpose: the hint applies
3628
- // `resolveDemoCredentials` itself, so it fails closed even when it is used
3629
- // standalone, without this hook.
3630
- hintProps: { credentials, onUse: handleUse }
4025
+ // `resolveDemoAccounts` itself, so it fails closed even when it is used
4026
+ // standalone, without this hook. `accounts` is the already-resolved list the
4027
+ // hint prefers — one labelled row per entry.
4028
+ hintProps: { credentials, accounts, onUse: handleUse }
3631
4029
  }),
3632
- [filled, prefillNonce, prefillIntent, credentials, handleUse]
4030
+ [filled, prefillNonce, prefillIntent, credentials, accounts, handleUse]
3633
4031
  );
3634
4032
  }
3635
4033
  async function lazyFetchHttpClient(request) {
@@ -3717,7 +4115,57 @@ async function performBffLogout(options) {
3717
4115
  }
3718
4116
  runGuarded(onRedirect, onError);
3719
4117
  }
4118
+ var CHANGE_PASSWORD_ENDPOINT = "/bff/account/change-password";
4119
+ var CSRF_HEADER2 = "X-BFF-Csrf";
4120
+ var CSRF_HEADER_VALUE2 = "1";
4121
+ var JSON_CONTENT_TYPE2 = "application/json";
4122
+ var HTTP_NO_CONTENT = 204;
4123
+ var HTTP_OK = 200;
4124
+ var HTTP_BAD_REQUEST2 = 400;
4125
+ var HTTP_UNAUTHORIZED = 401;
4126
+ async function lazyFetchHttpClient2(request) {
4127
+ const fetchImpl = typeof fetch === "function" ? fetch.bind(globalThis) : void 0;
4128
+ if (fetchImpl === void 0) {
4129
+ throw new Error("createBffChangePasswordClient: fetch is not available in this environment");
4130
+ }
4131
+ return createFetchHttpClient(fetchImpl)(request);
4132
+ }
4133
+ function resultFromStatus(status) {
4134
+ if (status === HTTP_NO_CONTENT || status === HTTP_OK) {
4135
+ return { status: "success" };
4136
+ }
4137
+ if (status === HTTP_BAD_REQUEST2) {
4138
+ return { status: "invalidCurrent" };
4139
+ }
4140
+ if (status === HTTP_UNAUTHORIZED) {
4141
+ return { status: "unauthorized" };
4142
+ }
4143
+ return { status: "error" };
4144
+ }
4145
+ function createBffChangePasswordClient(options = {}) {
4146
+ const http = options.http ?? lazyFetchHttpClient2;
4147
+ const baseUrl = options.baseUrl ?? "";
4148
+ const url = `${baseUrl}${CHANGE_PASSWORD_ENDPOINT}`;
4149
+ return {
4150
+ changePassword: async (request) => {
4151
+ try {
4152
+ const response = await http({
4153
+ url,
4154
+ method: "POST",
4155
+ headers: { "Content-Type": JSON_CONTENT_TYPE2, [CSRF_HEADER2]: CSRF_HEADER_VALUE2 },
4156
+ body: JSON.stringify({
4157
+ currentPassword: request.currentPassword,
4158
+ newPassword: request.newPassword
4159
+ })
4160
+ });
4161
+ return resultFromStatus(response.status);
4162
+ } catch {
4163
+ return { status: "error" };
4164
+ }
4165
+ }
4166
+ };
4167
+ }
3720
4168
 
3721
- export { AuthScreen, AuthTestIds, AuthThemeProvider, BffAuthStatus, DEFAULT_AUTH_CARD_MAX_WIDTH, DEFAULT_DEMO_CREDENTIALS_HINT_LABELS, DEFAULT_DEVICE_PIN_ENROLL_LABELS, DEFAULT_DEVICE_PIN_SETTINGS_LABELS, DEFAULT_DEVICE_PIN_UNLOCK_LABELS, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PASSKEY_LOGIN_LABELS, DEFAULT_PASSKEY_SETTINGS_LABELS, DEFAULT_PIN_LABELS, DEFAULT_PREFERRED_METHOD_HINT_LABELS, DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, DemoCredentialsHint, DemoCredentialsHintVariant, DevicePinEnrollErrorKey, DevicePinEnrollForm, DevicePinErrorKey, DevicePinInput, DevicePinLengthPicker, DevicePinOffer, DevicePinSettingsCard, DevicePinUnlockScreen, ForgotPasswordFields, ForgotPasswordForm, LoginForm, OtpForm, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PasskeyCeremonyMode, PasskeyCeremonyStatus, PasskeyLoginButton, PasskeySettingsCard, PasswordPolicyError, PinForm, PreferredMethodHint, PreferredMethodSettingsCard, PrefillIntent, ResetPasswordError, ResetPasswordForm, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, performBffLogout, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolveAccessibleRoutes, resolveDemoCredentials, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useDemoCredentials, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePasskeyCeremony, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
4169
+ export { AccountSettingsScreen, AuthScreen, AuthTestIds, AuthThemeProvider, BffAuthStatus, CHANGE_PASSWORD_ENDPOINT, ChangePasswordCard, ChangePasswordErrorKey, DEFAULT_ACCOUNT_SETTINGS_LABELS, DEFAULT_AUTH_CARD_MAX_WIDTH, DEFAULT_DEMO_CREDENTIALS_HINT_LABELS, DEFAULT_DEVICE_PIN_ENROLL_LABELS, DEFAULT_DEVICE_PIN_SETTINGS_LABELS, DEFAULT_DEVICE_PIN_UNLOCK_LABELS, DEFAULT_FORGOT_PASSWORD_FIELDS_LABELS, DEFAULT_FORGOT_PASSWORD_LABELS, DEFAULT_LOGIN_LABELS, DEFAULT_OTP_LABELS, DEFAULT_PASSKEY_LOGIN_LABELS, DEFAULT_PASSKEY_SETTINGS_LABELS, DEFAULT_PIN_LABELS, DEFAULT_PREFERRED_METHOD_HINT_LABELS, DEFAULT_PREFERRED_METHOD_SETTINGS_LABELS, DEFAULT_RESET_PASSWORD_LABELS, DEVICE_PIN_ALLOWED_DIGITS, DEVICE_PIN_DEFAULT_DIGITS, DemoCredentialsHint, DemoCredentialsHintVariant, DevicePinEnrollErrorKey, DevicePinEnrollForm, DevicePinErrorKey, DevicePinInput, DevicePinLengthPicker, DevicePinOffer, DevicePinSettingsCard, DevicePinUnlockScreen, ForgotPasswordFields, ForgotPasswordForm, LoginForm, OtpForm, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PasskeyCeremonyMode, PasskeyCeremonyStatus, PasskeyLoginButton, PasskeySettingsCard, PasswordPolicyError, PinForm, PreferredMethodHint, PreferredMethodSettingsCard, PrefillIntent, ResetPasswordError, ResetPasswordForm, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createBffChangePasswordClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, performBffLogout, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolveAccessibleRoutes, resolveAccountList, resolveDemoAccounts, resolveDemoCredentials, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useChangePassword, useDemoCredentials, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePasskeyCeremony, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
3722
4170
  //# sourceMappingURL=index.mjs.map
3723
4171
  //# sourceMappingURL=index.mjs.map