@dloizides/auth-web 1.5.1 → 1.7.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,11 +1,117 @@
1
- import { createContext, useState, useRef, useEffect, useCallback, useMemo, useContext } from 'react';
2
1
  import { StyleSheet, View, Text, TextInput, TouchableOpacity, ActivityIndicator, Pressable } from 'react-native';
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';
5
5
  import { BffAuthClient, createFetchHttpClient } from '@dloizides/auth-client';
6
6
  export { BffAuthClient, createFetchHttpClient } from '@dloizides/auth-client';
7
7
 
8
- // src/components/LoginForm.tsx
8
+ // src/components/AuthScreen.tsx
9
+ var FULL_WIDTH = "100%";
10
+ var CARD_BORDER_WIDTH = 1;
11
+ function useAuthScreenStyles(theme) {
12
+ return useMemo(() => {
13
+ const { colors, radii, spacing, typography } = theme;
14
+ return StyleSheet.create({
15
+ screen: {
16
+ flex: 1,
17
+ justifyContent: "center",
18
+ alignItems: "center",
19
+ padding: spacing.md,
20
+ backgroundColor: colors.background
21
+ },
22
+ card: {
23
+ width: FULL_WIDTH,
24
+ borderRadius: radii.card,
25
+ borderWidth: CARD_BORDER_WIDTH,
26
+ borderColor: colors.border,
27
+ padding: spacing.xl,
28
+ backgroundColor: colors.surface
29
+ },
30
+ title: {
31
+ fontSize: typography.title,
32
+ fontWeight: "bold",
33
+ marginBottom: spacing.xs,
34
+ color: colors.text
35
+ },
36
+ subtitle: {
37
+ fontSize: typography.subtitle,
38
+ marginBottom: spacing.lg,
39
+ color: colors.textSecondary
40
+ },
41
+ footer: {
42
+ marginTop: spacing.lg,
43
+ width: FULL_WIDTH,
44
+ alignItems: "center"
45
+ }
46
+ });
47
+ }, [theme]);
48
+ }
49
+
50
+ // src/theme/AuthTheme.ts
51
+ var defaultAuthTheme = {
52
+ colors: {
53
+ background: "#f5f5f7",
54
+ surface: "#ffffff",
55
+ text: "#1a1a1a",
56
+ textSecondary: "#6b6b6b",
57
+ border: "#d0d0d5",
58
+ primary: "#2563eb",
59
+ onPrimary: "#ffffff",
60
+ danger: "#d33333",
61
+ success: "#1f7a3d"
62
+ },
63
+ radii: {
64
+ input: 8,
65
+ card: 12
66
+ },
67
+ spacing: {
68
+ xs: 8,
69
+ sm: 12,
70
+ md: 20,
71
+ lg: 32,
72
+ xl: 24
73
+ },
74
+ typography: {
75
+ title: 28,
76
+ subtitle: 16,
77
+ label: 14,
78
+ body: 16,
79
+ caption: 12
80
+ }
81
+ };
82
+ var AuthThemeContext = createContext(defaultAuthTheme);
83
+ function AuthThemeProvider({
84
+ theme,
85
+ children
86
+ }) {
87
+ return /* @__PURE__ */ jsx(AuthThemeContext.Provider, { value: theme, children });
88
+ }
89
+ function useAuthTheme(themeProp) {
90
+ const contextTheme = useContext(AuthThemeContext);
91
+ return useMemo(() => themeProp ?? contextTheme, [themeProp, contextTheme]);
92
+ }
93
+ var DEFAULT_AUTH_CARD_MAX_WIDTH = 420;
94
+ function AuthScreen({
95
+ children,
96
+ theme: themeProp,
97
+ testID,
98
+ cardTestID,
99
+ maxWidth = DEFAULT_AUTH_CARD_MAX_WIDTH,
100
+ title,
101
+ subtitle,
102
+ footer
103
+ }) {
104
+ const theme = useAuthTheme(themeProp);
105
+ const styles3 = useAuthScreenStyles(theme);
106
+ return /* @__PURE__ */ jsxs(View, { style: styles3.screen, testID, children: [
107
+ /* @__PURE__ */ jsxs(View, { style: [styles3.card, { maxWidth }], testID: cardTestID, children: [
108
+ title !== void 0 ? /* @__PURE__ */ jsx(Text, { style: styles3.title, children: title }) : null,
109
+ subtitle !== void 0 ? /* @__PURE__ */ jsx(Text, { style: styles3.subtitle, children: subtitle }) : null,
110
+ children
111
+ ] }),
112
+ footer !== void 0 ? /* @__PURE__ */ jsx(View, { style: [styles3.footer, { maxWidth }], children: footer }) : null
113
+ ] });
114
+ }
9
115
 
10
116
  // src/components/labels.ts
11
117
  var DEFAULT_LOGIN_LABELS = {
@@ -246,7 +352,7 @@ var AuthTestIds = {
246
352
  function withTestIdPrefix(baseId, prefix) {
247
353
  return prefix === void 0 || prefix === "" ? baseId : `${prefix}-${baseId}`;
248
354
  }
249
- var FULL_WIDTH = "100%";
355
+ var FULL_WIDTH2 = "100%";
250
356
  var CARD_MAX_WIDTH = 420;
251
357
  var BUTTON_VERTICAL_PADDING = 14;
252
358
  function useAuthStyles(theme) {
@@ -261,7 +367,7 @@ function useAuthStyles(theme) {
261
367
  backgroundColor: colors.background
262
368
  },
263
369
  card: {
264
- width: FULL_WIDTH,
370
+ width: FULL_WIDTH2,
265
371
  maxWidth: CARD_MAX_WIDTH,
266
372
  borderRadius: radii.card,
267
373
  padding: spacing.xl,
@@ -304,11 +410,6 @@ function useAuthStyles(theme) {
304
410
  primaryButton: {
305
411
  borderRadius: radii.input,
306
412
  paddingVertical: BUTTON_VERTICAL_PADDING,
307
- paddingHorizontal: spacing.md,
308
- // Never shrink below the label width: in a row of actions (e.g. the
309
- // forgot-password modal's Cancel + submit), shrinking would clip a long
310
- // label like "Send reset link" past the button's rounded edge.
311
- flexShrink: 0,
312
413
  alignItems: "center",
313
414
  justifyContent: "center",
314
415
  marginTop: spacing.xs,
@@ -351,8 +452,6 @@ function useAuthStyles(theme) {
351
452
  borderWidth: 1,
352
453
  borderColor: colors.primary,
353
454
  paddingVertical: BUTTON_VERTICAL_PADDING,
354
- paddingHorizontal: spacing.md,
355
- flexShrink: 0,
356
455
  alignItems: "center",
357
456
  justifyContent: "center",
358
457
  marginTop: spacing.sm,
@@ -475,50 +574,6 @@ function useBffAuth(options) {
475
574
  [session.user, session.status, isSubmitting, error, login, logout, refresh]
476
575
  );
477
576
  }
478
-
479
- // src/theme/AuthTheme.ts
480
- var defaultAuthTheme = {
481
- colors: {
482
- background: "#f5f5f7",
483
- surface: "#ffffff",
484
- text: "#1a1a1a",
485
- textSecondary: "#6b6b6b",
486
- border: "#d0d0d5",
487
- primary: "#2563eb",
488
- onPrimary: "#ffffff",
489
- danger: "#d33333",
490
- success: "#1f7a3d"
491
- },
492
- radii: {
493
- input: 8,
494
- card: 12
495
- },
496
- spacing: {
497
- xs: 8,
498
- sm: 12,
499
- md: 20,
500
- lg: 32,
501
- xl: 24
502
- },
503
- typography: {
504
- title: 28,
505
- subtitle: 16,
506
- label: 14,
507
- body: 16,
508
- caption: 12
509
- }
510
- };
511
- var AuthThemeContext = createContext(defaultAuthTheme);
512
- function AuthThemeProvider({
513
- theme,
514
- children
515
- }) {
516
- return /* @__PURE__ */ jsx(AuthThemeContext.Provider, { value: theme, children });
517
- }
518
- function useAuthTheme(themeProp) {
519
- const contextTheme = useContext(AuthThemeContext);
520
- return useMemo(() => themeProp ?? contextTheme, [themeProp, contextTheme]);
521
- }
522
577
  function LoginForm({
523
578
  client,
524
579
  theme: themeProp,
@@ -526,7 +581,8 @@ function LoginForm({
526
581
  onSuccess,
527
582
  onForgotPassword,
528
583
  onSignUp,
529
- testIdPrefix
584
+ testIdPrefix,
585
+ chromeless = false
530
586
  }) {
531
587
  const theme = useAuthTheme(themeProp);
532
588
  const styles3 = useAuthStyles(theme);
@@ -557,7 +613,7 @@ function LoginForm({
557
613
  void runLogin();
558
614
  }, [runLogin]);
559
615
  const submitButtonStyle = isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
560
- return /* @__PURE__ */ jsx(View, { style: styles3.screen, children: /* @__PURE__ */ jsxs(View, { style: styles3.card, testID: withTestIdPrefix(AuthTestIds.loginForm, testIdPrefix), children: [
616
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
561
617
  /* @__PURE__ */ jsx(Text, { style: styles3.title, children: labels.title }),
562
618
  /* @__PURE__ */ jsx(Text, { style: styles3.subtitle, children: labels.subtitle }),
563
619
  /* @__PURE__ */ jsxs(View, { style: styles3.fieldGroup, children: [
@@ -646,7 +702,16 @@ function LoginForm({
646
702
  children: /* @__PURE__ */ jsx(Text, { style: styles3.linkText, children: labels.signUp })
647
703
  }
648
704
  ) : null
649
- ] }) });
705
+ ] });
706
+ const card = /* @__PURE__ */ jsx(
707
+ View,
708
+ {
709
+ style: chromeless ? void 0 : styles3.card,
710
+ testID: withTestIdPrefix(AuthTestIds.loginForm, testIdPrefix),
711
+ children: content
712
+ }
713
+ );
714
+ return chromeless ? card : /* @__PURE__ */ jsx(View, { style: styles3.screen, children: card });
650
715
  }
651
716
  function useBffForgotPassword(options) {
652
717
  const { client, ...rest } = options;
@@ -829,9 +894,6 @@ function useModalStyles(theme) {
829
894
  flexDirection: "row",
830
895
  justifyContent: "flex-end",
831
896
  alignItems: "center",
832
- // Wrap (rather than clip) when a long submit label + Cancel can't
833
- // fit a narrow modal on one line.
834
- flexWrap: "wrap",
835
897
  marginTop: theme.spacing.md,
836
898
  gap: theme.spacing.sm
837
899
  },
@@ -839,8 +901,6 @@ function useModalStyles(theme) {
839
901
  borderRadius: theme.radii.input,
840
902
  paddingVertical: theme.spacing.sm,
841
903
  paddingHorizontal: theme.spacing.md,
842
- // Match the submit button: never shrink below the label width.
843
- flexShrink: 0,
844
904
  borderWidth: SECONDARY_BORDER_WIDTH,
845
905
  borderColor: theme.colors.border
846
906
  },
@@ -1501,7 +1561,8 @@ function OtpForm({
1501
1561
  theme: themeProp,
1502
1562
  labels: labelsProp,
1503
1563
  onSuccess,
1504
- testIdPrefix
1564
+ testIdPrefix,
1565
+ chromeless = false
1505
1566
  }) {
1506
1567
  const theme = useAuthTheme(themeProp);
1507
1568
  const styles3 = useAuthStyles(theme);
@@ -1522,7 +1583,7 @@ function OtpForm({
1522
1583
  otp.reset();
1523
1584
  }, [otp]);
1524
1585
  const errorText = localError ?? transportErrorFor(otp.step, otp.error, labels);
1525
- return /* @__PURE__ */ jsx(View, { style: styles3.screen, children: /* @__PURE__ */ jsx(View, { style: styles3.card, testID: withTestIdPrefix(AuthTestIds.otpForm, testIdPrefix), children: otp.step === "requestCode" /* RequestCode */ ? /* @__PURE__ */ jsx(
1586
+ const content = otp.step === "requestCode" /* RequestCode */ ? /* @__PURE__ */ jsx(
1526
1587
  OtpRequestStep,
1527
1588
  {
1528
1589
  errorText,
@@ -1547,7 +1608,16 @@ function OtpForm({
1547
1608
  onResend: handleResend,
1548
1609
  onSubmit: handleVerify
1549
1610
  }
1550
- ) }) });
1611
+ );
1612
+ const card = /* @__PURE__ */ jsx(
1613
+ View,
1614
+ {
1615
+ style: chromeless ? void 0 : styles3.card,
1616
+ testID: withTestIdPrefix(AuthTestIds.otpForm, testIdPrefix),
1617
+ children: content
1618
+ }
1619
+ );
1620
+ return chromeless ? card : /* @__PURE__ */ jsx(View, { style: styles3.screen, children: card });
1551
1621
  }
1552
1622
  function toError3(value) {
1553
1623
  return value instanceof Error ? value : new Error(String(value));
@@ -1626,7 +1696,8 @@ function PinForm({
1626
1696
  theme: themeProp,
1627
1697
  labels: labelsProp,
1628
1698
  onSuccess,
1629
- testIdPrefix
1699
+ testIdPrefix,
1700
+ chromeless = false
1630
1701
  }) {
1631
1702
  const theme = useAuthTheme(themeProp);
1632
1703
  const styles3 = useAuthStyles(theme);
@@ -1640,7 +1711,7 @@ function PinForm({
1640
1711
  const handleSubmit = useSubmitHandler(pin, labels, setLocalError, onSuccess);
1641
1712
  const errorText = localError ?? transportErrorFor2(pin.error, labels);
1642
1713
  const buttonStyle = pin.isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
1643
- return /* @__PURE__ */ jsx(View, { style: styles3.screen, children: /* @__PURE__ */ jsxs(View, { style: styles3.card, testID: withTestIdPrefix(AuthTestIds.pinForm, testIdPrefix), children: [
1714
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
1644
1715
  /* @__PURE__ */ jsx(Text, { style: styles3.title, children: labels.title }),
1645
1716
  /* @__PURE__ */ jsx(Text, { style: styles3.subtitle, children: labels.description }),
1646
1717
  /* @__PURE__ */ jsxs(View, { style: styles3.fieldGroup, children: [
@@ -1685,7 +1756,16 @@ function PinForm({
1685
1756
  children: pin.isSubmitting ? /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsx(Text, { style: styles3.primaryButtonText, children: labels.submit })
1686
1757
  }
1687
1758
  )
1688
- ] }) });
1759
+ ] });
1760
+ const card = /* @__PURE__ */ jsx(
1761
+ View,
1762
+ {
1763
+ style: chromeless ? void 0 : styles3.card,
1764
+ testID: withTestIdPrefix(AuthTestIds.pinForm, testIdPrefix),
1765
+ children: content
1766
+ }
1767
+ );
1768
+ return chromeless ? card : /* @__PURE__ */ jsx(View, { style: styles3.screen, children: card });
1689
1769
  }
1690
1770
  var DOT_SIZE = 18;
1691
1771
  var DOT_BORDER_WIDTH = 2;
@@ -2919,6 +2999,12 @@ function resolvePostLoginRoute(user, table) {
2919
2999
  return table.fallback ?? null;
2920
3000
  }
2921
3001
 
2922
- export { AuthTestIds, AuthThemeProvider, BffAuthStatus, 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, DevicePinEnrollErrorKey, DevicePinEnrollForm, DevicePinErrorKey, DevicePinInput, DevicePinLengthPicker, DevicePinOffer, DevicePinSettingsCard, DevicePinUnlockScreen, ForgotPasswordFields, ForgotPasswordForm, LoginForm, OtpForm, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PasskeyLoginButton, PasskeySettingsCard, PasswordPolicyError, PinForm, PreferredMethodHint, PreferredMethodSettingsCard, ResetPasswordError, ResetPasswordForm, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
3002
+ // src/router/resolveAccessibleRoutes.ts
3003
+ function resolveAccessibleRoutes(user, table) {
3004
+ const userRoles = new Set(collectUserRoles(user));
3005
+ return table.routes.filter((entry) => userRoles.has(entry.role));
3006
+ }
3007
+
3008
+ export { AuthScreen, AuthTestIds, AuthThemeProvider, BffAuthStatus, DEFAULT_AUTH_CARD_MAX_WIDTH, 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, DevicePinEnrollErrorKey, DevicePinEnrollForm, DevicePinErrorKey, DevicePinInput, DevicePinLengthPicker, DevicePinOffer, DevicePinSettingsCard, DevicePinUnlockScreen, ForgotPasswordFields, ForgotPasswordForm, LoginForm, OtpForm, OtpLoginStep, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PasskeyLoginButton, PasskeySettingsCard, PasswordPolicyError, PinForm, PreferredMethodHint, PreferredMethodSettingsCard, ResetPasswordError, ResetPasswordForm, cachePreferredMethod, clearCachedPreferredMethod, collectUserRoles, createBffAuthClient, createPreferencesClient, defaultAuthTheme, isAllowedPinDigits, isPasswordValid, isValidForgotPasswordEmail, readCachedPreferredMethod, readPasskeyError, readPasskeyRegistered, resolveAccessibleRoutes, resolvePostLoginRoute, startPasskeyLogin, startPasskeyRegistration, syncPreferredMethodFromServer, useAuthTheme, useBffAuth, useBffForgotPassword, useBffLoginConfig, useBffResetPassword, useDevicePinDisable, useDevicePinEnroll, useDevicePinUnlock, useForgotPasswordSubmit, useOtpLogin, usePinLogin, usePreferredMethodSetting, useResetPasswordForm, validatePasswordPolicy, withTestIdPrefix };
2923
3009
  //# sourceMappingURL=index.mjs.map
2924
3010
  //# sourceMappingURL=index.mjs.map