@dloizides/auth-web 1.18.0 → 1.18.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.
package/dist/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
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
+ import { Button } from '@dloizides/ui-buttons';
4
5
  import { useMutation } from '@tanstack/react-query';
5
6
  import { BffAuthClient, createFetchHttpClient } from '@dloizides/auth-client';
6
7
  export { BffAuthClient, createFetchHttpClient } from '@dloizides/auth-client';
@@ -636,6 +637,21 @@ function useLoginSubmit({
636
637
  }, [runLogin]);
637
638
  return { errorText, handleSubmit };
638
639
  }
640
+ function isKeyRepeat(event) {
641
+ const native = event?.nativeEvent;
642
+ return native?.repeat === true;
643
+ }
644
+ function useSubmitOnEnter(submit) {
645
+ return useCallback(
646
+ (event) => {
647
+ if (isKeyRepeat(event)) {
648
+ return;
649
+ }
650
+ submit();
651
+ },
652
+ [submit]
653
+ );
654
+ }
639
655
  var BffAuthStatus = /* @__PURE__ */ ((BffAuthStatus2) => {
640
656
  BffAuthStatus2["Loading"] = "loading";
641
657
  BffAuthStatus2["Authenticated"] = "authenticated";
@@ -774,7 +790,7 @@ function LoginForm({
774
790
  missingFieldsLabel: labels.missingFields,
775
791
  invalidCredentialsLabel: labels.invalidCredentials
776
792
  });
777
- const submitButtonStyle = isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
793
+ const handleSubmitEditing = useSubmitOnEnter(handleSubmit);
778
794
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [
779
795
  /* @__PURE__ */ jsx(Text, { style: styles3.title, children: labels.title }),
780
796
  /* @__PURE__ */ jsx(Text, { style: styles3.subtitle, children: labels.subtitle }),
@@ -790,10 +806,12 @@ function LoginForm({
790
806
  editable: !isSubmitting,
791
807
  placeholder: labels.usernamePlaceholder,
792
808
  placeholderTextColor: theme.colors.textSecondary,
809
+ returnKeyType: "go",
793
810
  style: styles3.input,
794
811
  testID: withTestIdPrefix(AuthTestIds.loginUsernameInput, testIdPrefix),
795
812
  value: username,
796
- onChangeText: setUsername
813
+ onChangeText: setUsername,
814
+ onSubmitEditing: handleSubmitEditing
797
815
  }
798
816
  )
799
817
  ] }),
@@ -810,10 +828,12 @@ function LoginForm({
810
828
  editable: !isSubmitting,
811
829
  placeholder: labels.passwordPlaceholder,
812
830
  placeholderTextColor: theme.colors.textSecondary,
831
+ returnKeyType: "go",
813
832
  style: styles3.input,
814
833
  testID: withTestIdPrefix(AuthTestIds.loginPasswordInput, testIdPrefix),
815
834
  value: password,
816
- onChangeText: setPassword
835
+ onChangeText: setPassword,
836
+ onSubmitEditing: handleSubmitEditing
817
837
  }
818
838
  )
819
839
  ] }),
@@ -838,19 +858,18 @@ function LoginForm({
838
858
  children: /* @__PURE__ */ jsx(Text, { style: styles3.linkText, children: labels.forgotPassword })
839
859
  }
840
860
  ) : null,
841
- /* @__PURE__ */ jsx(
842
- TouchableOpacity,
861
+ /* @__PURE__ */ jsx(View, { style: styles3.fieldGroup, children: /* @__PURE__ */ jsx(
862
+ Button,
843
863
  {
864
+ fullWidth: true,
844
865
  accessibilityHint: labels.submit,
845
866
  accessibilityLabel: isSubmitting ? labels.submitting : labels.submit,
846
- accessibilityRole: "button",
847
- disabled: isSubmitting,
848
- style: submitButtonStyle,
867
+ label: labels.submit,
868
+ loading: isSubmitting,
849
869
  testID: withTestIdPrefix(AuthTestIds.loginSubmitButton, testIdPrefix),
850
- onPress: handleSubmit,
851
- children: isSubmitting ? /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsx(Text, { style: styles3.primaryButtonText, children: labels.submit })
870
+ onPress: handleSubmit
852
871
  }
853
- ),
872
+ ) }),
854
873
  onSignUp !== void 0 ? /* @__PURE__ */ jsx(
855
874
  TouchableOpacity,
856
875
  {
@@ -4094,6 +4113,7 @@ function RegisterFormFields({
4094
4113
  theme,
4095
4114
  styles: styles3,
4096
4115
  onChange,
4116
+ onSubmitEditing,
4097
4117
  testIdPrefix
4098
4118
  }) {
4099
4119
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -4113,11 +4133,13 @@ function RegisterFormFields({
4113
4133
  keyboardType: config.keyboardType ?? "default",
4114
4134
  placeholder: copy.placeholder,
4115
4135
  placeholderTextColor: theme.colors.textSecondary,
4136
+ returnKeyType: "go",
4116
4137
  secureTextEntry: config.secure === true,
4117
4138
  style: styles3.input,
4118
4139
  testID: withTestIdPrefix(config.testId, testIdPrefix),
4119
4140
  value: values[config.key],
4120
- onChangeText: (text) => onChange(config.key, text)
4141
+ onChangeText: (text) => onChange(config.key, text),
4142
+ onSubmitEditing
4121
4143
  }
4122
4144
  )
4123
4145
  ] }, config.key);
@@ -4126,6 +4148,7 @@ function RegisterFormFields({
4126
4148
  TextInput,
4127
4149
  {
4128
4150
  accessibilityElementsHidden: true,
4151
+ accessibilityRole: "none",
4129
4152
  autoComplete: "off",
4130
4153
  focusable: false,
4131
4154
  importantForAccessibility: "no-hide-descendants",
@@ -4154,9 +4177,21 @@ var RegisterErrorCode = /* @__PURE__ */ ((RegisterErrorCode2) => {
4154
4177
  return RegisterErrorCode2;
4155
4178
  })(RegisterErrorCode || {});
4156
4179
 
4180
+ // src/hooks/routeRegisterOutcome.ts
4181
+ function routeRegisterOutcome(outcome, handlers) {
4182
+ if (outcome.ok) {
4183
+ handlers.onSuccess(outcome.result);
4184
+ return;
4185
+ }
4186
+ if (outcome.error !== "inFlight" /* InFlight */) {
4187
+ handlers.onError?.(outcome.error);
4188
+ }
4189
+ }
4190
+
4157
4191
  // src/hooks/registerErrors.ts
4158
4192
  var MIN_PASSWORD_LENGTH = 8;
4159
- var EMAIL_REGEX4 = /^[^@\s]+@[^.\s]+\.\S+$/;
4193
+ var WHITESPACE_REGEX = /\s/;
4194
+ var EMAIL_PART_COUNT = 2;
4160
4195
  var PASSWORD_LETTER_REGEX = /[a-zA-Z]/;
4161
4196
  var PASSWORD_DIGIT_REGEX = /\d/;
4162
4197
  var PASSWORD_SPECIAL_REGEX = /[^a-zA-Z0-9]/;
@@ -4178,6 +4213,17 @@ function isRegisterPasswordStrong(password) {
4178
4213
  }
4179
4214
  return PASSWORD_SPECIAL_REGEX.test(password);
4180
4215
  }
4216
+ function isEmailShaped(email) {
4217
+ if (WHITESPACE_REGEX.test(email)) {
4218
+ return false;
4219
+ }
4220
+ const parts = email.split("@");
4221
+ if (parts.length !== EMAIL_PART_COUNT) {
4222
+ return false;
4223
+ }
4224
+ const [local = "", domain = ""] = parts;
4225
+ return local !== "" && domain.slice(1, -1).includes(".");
4226
+ }
4181
4227
  function trimRegisterValues(values) {
4182
4228
  return {
4183
4229
  firstName: values.firstName.trim(),
@@ -4205,7 +4251,7 @@ function validateRegisterValues(values, passwordPolicy) {
4205
4251
  if (hasMissingRequiredField(values)) {
4206
4252
  return "missingFields" /* MissingFields */;
4207
4253
  }
4208
- if (!EMAIL_REGEX4.test(values.email)) {
4254
+ if (!isEmailShaped(values.email)) {
4209
4255
  return "invalidEmail" /* InvalidEmail */;
4210
4256
  }
4211
4257
  if (!passwordPolicy(values.password)) {
@@ -4255,7 +4301,8 @@ function toSubmitValues(values) {
4255
4301
  }
4256
4302
  function useRegisterForm({
4257
4303
  onSubmit,
4258
- passwordPolicy = isRegisterPasswordStrong
4304
+ passwordPolicy = isRegisterPasswordStrong,
4305
+ onSubmitAttempt
4259
4306
  }) {
4260
4307
  const [state, setState] = useState(EMPTY_VALUES);
4261
4308
  const [isSubmitting, setIsSubmitting] = useState(false);
@@ -4268,6 +4315,7 @@ function useRegisterForm({
4268
4315
  if (inFlight.current) {
4269
4316
  return { ok: false, error: "inFlight" /* InFlight */ };
4270
4317
  }
4318
+ onSubmitAttempt?.();
4271
4319
  const trimmed = trimRegisterValues(state);
4272
4320
  const refusal = trimmed.website === "" ? validateRegisterValues(trimmed, passwordPolicy) : "failed" /* Failed */;
4273
4321
  if (refusal !== null) {
@@ -4288,7 +4336,7 @@ function useRegisterForm({
4288
4336
  inFlight.current = false;
4289
4337
  setIsSubmitting(false);
4290
4338
  }
4291
- }, [onSubmit, passwordPolicy, state]);
4339
+ }, [onSubmit, onSubmitAttempt, passwordPolicy, state]);
4292
4340
  return { state, setField, submit, isSubmitting, error };
4293
4341
  }
4294
4342
  function RegisterForm({
@@ -4308,18 +4356,15 @@ function RegisterForm({
4308
4356
  () => ({ ...DEFAULT_REGISTER_LABELS, ...labelsProp }),
4309
4357
  [labelsProp]
4310
4358
  );
4311
- const { state, setField, submit, isSubmitting } = useRegisterForm({ onSubmit, passwordPolicy });
4312
- const handlePress = useCallback(() => {
4313
- onSubmitAttempt?.();
4314
- void submit().then((outcome) => {
4315
- if (outcome.ok) {
4316
- onSuccess(outcome.result);
4317
- } else if (outcome.error !== "inFlight" /* InFlight */) {
4318
- onError?.(outcome.error);
4319
- }
4320
- });
4321
- }, [onError, onSubmitAttempt, onSuccess, submit]);
4322
- const buttonStyle = isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
4359
+ const { state, setField, submit, isSubmitting } = useRegisterForm({
4360
+ onSubmit,
4361
+ onSubmitAttempt,
4362
+ passwordPolicy
4363
+ });
4364
+ const handlePress = useCallback(async () => {
4365
+ routeRegisterOutcome(await submit(), { onSuccess, onError });
4366
+ }, [onError, onSuccess, submit]);
4367
+ const handleSubmitEditing = useSubmitOnEnter(handlePress);
4323
4368
  return /* @__PURE__ */ jsx(View, { style: styles3.screen, children: /* @__PURE__ */ jsxs(View, { style: styles3.card, testID: withTestIdPrefix(RegisterTestIds.form, testIdPrefix), children: [
4324
4369
  /* @__PURE__ */ jsx(Text, { style: styles3.title, children: labels.title }),
4325
4370
  /* @__PURE__ */ jsx(Text, { style: styles3.subtitle, children: labels.subtitle }),
@@ -4332,22 +4377,22 @@ function RegisterForm({
4332
4377
  testIdPrefix,
4333
4378
  theme,
4334
4379
  values: state,
4335
- onChange: setField
4380
+ onChange: setField,
4381
+ onSubmitEditing: handleSubmitEditing
4336
4382
  }
4337
4383
  ),
4338
- /* @__PURE__ */ jsx(
4339
- TouchableOpacity,
4384
+ /* @__PURE__ */ jsx(View, { style: styles3.fieldGroup, children: /* @__PURE__ */ jsx(
4385
+ Button,
4340
4386
  {
4387
+ fullWidth: true,
4341
4388
  accessibilityHint: labels.submitHint,
4342
4389
  accessibilityLabel: isSubmitting ? labels.submitting : labels.submit,
4343
- accessibilityRole: "button",
4344
- disabled: isSubmitting,
4345
- style: buttonStyle,
4390
+ label: labels.submit,
4391
+ loading: isSubmitting,
4346
4392
  testID: withTestIdPrefix(RegisterTestIds.submitButton, testIdPrefix),
4347
- onPress: handlePress,
4348
- children: isSubmitting ? /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsx(Text, { style: styles3.primaryButtonText, children: labels.submit })
4393
+ onPress: handlePress
4349
4394
  }
4350
- ),
4395
+ ) }),
4351
4396
  footer
4352
4397
  ] }) });
4353
4398
  }
@@ -4487,6 +4532,6 @@ function createBffChangePasswordClient(options = {}) {
4487
4532
  };
4488
4533
  }
4489
4534
 
4490
- 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_REGISTER_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, RegisterErrorCode, RegisterForm, RegisterTestIds, ResetPasswordError, ResetPasswordForm, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createBffChangePasswordClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isRegisterPasswordStrong, isValidForgotPasswordEmail, mapRegisterErrorCode, 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, useRegisterForm, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
4535
+ 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_REGISTER_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, RegisterErrorCode, RegisterForm, RegisterTestIds, ResetPasswordError, ResetPasswordForm, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createBffChangePasswordClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isRegisterPasswordStrong, 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, useRegisterForm, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
4491
4536
  //# sourceMappingURL=index.mjs.map
4492
4537
  //# sourceMappingURL=index.mjs.map