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