@dloizides/auth-web 1.5.1 → 1.6.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
@@ -1,12 +1,118 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
4
3
  var reactNative = require('react-native');
4
+ var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var reactQuery = require('@tanstack/react-query');
7
7
  var authClient = require('@dloizides/auth-client');
8
8
 
9
- // src/components/LoginForm.tsx
9
+ // src/components/AuthScreen.tsx
10
+ var FULL_WIDTH = "100%";
11
+ var CARD_BORDER_WIDTH = 1;
12
+ function useAuthScreenStyles(theme) {
13
+ return react.useMemo(() => {
14
+ const { colors, radii, spacing, typography } = theme;
15
+ return reactNative.StyleSheet.create({
16
+ screen: {
17
+ flex: 1,
18
+ justifyContent: "center",
19
+ alignItems: "center",
20
+ padding: spacing.md,
21
+ backgroundColor: colors.background
22
+ },
23
+ card: {
24
+ width: FULL_WIDTH,
25
+ borderRadius: radii.card,
26
+ borderWidth: CARD_BORDER_WIDTH,
27
+ borderColor: colors.border,
28
+ padding: spacing.xl,
29
+ backgroundColor: colors.surface
30
+ },
31
+ title: {
32
+ fontSize: typography.title,
33
+ fontWeight: "bold",
34
+ marginBottom: spacing.xs,
35
+ color: colors.text
36
+ },
37
+ subtitle: {
38
+ fontSize: typography.subtitle,
39
+ marginBottom: spacing.lg,
40
+ color: colors.textSecondary
41
+ },
42
+ footer: {
43
+ marginTop: spacing.lg,
44
+ width: FULL_WIDTH,
45
+ alignItems: "center"
46
+ }
47
+ });
48
+ }, [theme]);
49
+ }
50
+
51
+ // src/theme/AuthTheme.ts
52
+ var defaultAuthTheme = {
53
+ colors: {
54
+ background: "#f5f5f7",
55
+ surface: "#ffffff",
56
+ text: "#1a1a1a",
57
+ textSecondary: "#6b6b6b",
58
+ border: "#d0d0d5",
59
+ primary: "#2563eb",
60
+ onPrimary: "#ffffff",
61
+ danger: "#d33333",
62
+ success: "#1f7a3d"
63
+ },
64
+ radii: {
65
+ input: 8,
66
+ card: 12
67
+ },
68
+ spacing: {
69
+ xs: 8,
70
+ sm: 12,
71
+ md: 20,
72
+ lg: 32,
73
+ xl: 24
74
+ },
75
+ typography: {
76
+ title: 28,
77
+ subtitle: 16,
78
+ label: 14,
79
+ body: 16,
80
+ caption: 12
81
+ }
82
+ };
83
+ var AuthThemeContext = react.createContext(defaultAuthTheme);
84
+ function AuthThemeProvider({
85
+ theme,
86
+ children
87
+ }) {
88
+ return /* @__PURE__ */ jsxRuntime.jsx(AuthThemeContext.Provider, { value: theme, children });
89
+ }
90
+ function useAuthTheme(themeProp) {
91
+ const contextTheme = react.useContext(AuthThemeContext);
92
+ return react.useMemo(() => themeProp ?? contextTheme, [themeProp, contextTheme]);
93
+ }
94
+ var DEFAULT_AUTH_CARD_MAX_WIDTH = 420;
95
+ function AuthScreen({
96
+ children,
97
+ theme: themeProp,
98
+ testID,
99
+ cardTestID,
100
+ maxWidth = DEFAULT_AUTH_CARD_MAX_WIDTH,
101
+ title,
102
+ subtitle,
103
+ footer
104
+ }) {
105
+ const theme = useAuthTheme(themeProp);
106
+ const styles3 = useAuthScreenStyles(theme);
107
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.screen, testID, children: [
108
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles3.card, { maxWidth }], testID: cardTestID, children: [
109
+ title !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: title }) : null,
110
+ subtitle !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: subtitle }) : null,
111
+ children
112
+ ] }),
113
+ footer !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles3.footer, { maxWidth }], children: footer }) : null
114
+ ] });
115
+ }
10
116
 
11
117
  // src/components/labels.ts
12
118
  var DEFAULT_LOGIN_LABELS = {
@@ -247,7 +353,7 @@ var AuthTestIds = {
247
353
  function withTestIdPrefix(baseId, prefix) {
248
354
  return prefix === void 0 || prefix === "" ? baseId : `${prefix}-${baseId}`;
249
355
  }
250
- var FULL_WIDTH = "100%";
356
+ var FULL_WIDTH2 = "100%";
251
357
  var CARD_MAX_WIDTH = 420;
252
358
  var BUTTON_VERTICAL_PADDING = 14;
253
359
  function useAuthStyles(theme) {
@@ -262,7 +368,7 @@ function useAuthStyles(theme) {
262
368
  backgroundColor: colors.background
263
369
  },
264
370
  card: {
265
- width: FULL_WIDTH,
371
+ width: FULL_WIDTH2,
266
372
  maxWidth: CARD_MAX_WIDTH,
267
373
  borderRadius: radii.card,
268
374
  padding: spacing.xl,
@@ -305,11 +411,6 @@ function useAuthStyles(theme) {
305
411
  primaryButton: {
306
412
  borderRadius: radii.input,
307
413
  paddingVertical: BUTTON_VERTICAL_PADDING,
308
- paddingHorizontal: spacing.md,
309
- // Never shrink below the label width: in a row of actions (e.g. the
310
- // forgot-password modal's Cancel + submit), shrinking would clip a long
311
- // label like "Send reset link" past the button's rounded edge.
312
- flexShrink: 0,
313
414
  alignItems: "center",
314
415
  justifyContent: "center",
315
416
  marginTop: spacing.xs,
@@ -352,8 +453,6 @@ function useAuthStyles(theme) {
352
453
  borderWidth: 1,
353
454
  borderColor: colors.primary,
354
455
  paddingVertical: BUTTON_VERTICAL_PADDING,
355
- paddingHorizontal: spacing.md,
356
- flexShrink: 0,
357
456
  alignItems: "center",
358
457
  justifyContent: "center",
359
458
  marginTop: spacing.sm,
@@ -476,50 +575,6 @@ function useBffAuth(options) {
476
575
  [session.user, session.status, isSubmitting, error, login, logout, refresh]
477
576
  );
478
577
  }
479
-
480
- // src/theme/AuthTheme.ts
481
- var defaultAuthTheme = {
482
- colors: {
483
- background: "#f5f5f7",
484
- surface: "#ffffff",
485
- text: "#1a1a1a",
486
- textSecondary: "#6b6b6b",
487
- border: "#d0d0d5",
488
- primary: "#2563eb",
489
- onPrimary: "#ffffff",
490
- danger: "#d33333",
491
- success: "#1f7a3d"
492
- },
493
- radii: {
494
- input: 8,
495
- card: 12
496
- },
497
- spacing: {
498
- xs: 8,
499
- sm: 12,
500
- md: 20,
501
- lg: 32,
502
- xl: 24
503
- },
504
- typography: {
505
- title: 28,
506
- subtitle: 16,
507
- label: 14,
508
- body: 16,
509
- caption: 12
510
- }
511
- };
512
- var AuthThemeContext = react.createContext(defaultAuthTheme);
513
- function AuthThemeProvider({
514
- theme,
515
- children
516
- }) {
517
- return /* @__PURE__ */ jsxRuntime.jsx(AuthThemeContext.Provider, { value: theme, children });
518
- }
519
- function useAuthTheme(themeProp) {
520
- const contextTheme = react.useContext(AuthThemeContext);
521
- return react.useMemo(() => themeProp ?? contextTheme, [themeProp, contextTheme]);
522
- }
523
578
  function LoginForm({
524
579
  client,
525
580
  theme: themeProp,
@@ -527,7 +582,8 @@ function LoginForm({
527
582
  onSuccess,
528
583
  onForgotPassword,
529
584
  onSignUp,
530
- testIdPrefix
585
+ testIdPrefix,
586
+ chromeless = false
531
587
  }) {
532
588
  const theme = useAuthTheme(themeProp);
533
589
  const styles3 = useAuthStyles(theme);
@@ -558,7 +614,7 @@ function LoginForm({
558
614
  void runLogin();
559
615
  }, [runLogin]);
560
616
  const submitButtonStyle = isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
561
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.card, testID: withTestIdPrefix(AuthTestIds.loginForm, testIdPrefix), children: [
617
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
562
618
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
563
619
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.subtitle }),
564
620
  /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
@@ -647,7 +703,16 @@ function LoginForm({
647
703
  children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.linkText, children: labels.signUp })
648
704
  }
649
705
  ) : null
650
- ] }) });
706
+ ] });
707
+ const card = /* @__PURE__ */ jsxRuntime.jsx(
708
+ reactNative.View,
709
+ {
710
+ style: chromeless ? void 0 : styles3.card,
711
+ testID: withTestIdPrefix(AuthTestIds.loginForm, testIdPrefix),
712
+ children: content
713
+ }
714
+ );
715
+ return chromeless ? card : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: card });
651
716
  }
652
717
  function useBffForgotPassword(options) {
653
718
  const { client, ...rest } = options;
@@ -830,9 +895,6 @@ function useModalStyles(theme) {
830
895
  flexDirection: "row",
831
896
  justifyContent: "flex-end",
832
897
  alignItems: "center",
833
- // Wrap (rather than clip) when a long submit label + Cancel can't
834
- // fit a narrow modal on one line.
835
- flexWrap: "wrap",
836
898
  marginTop: theme.spacing.md,
837
899
  gap: theme.spacing.sm
838
900
  },
@@ -840,8 +902,6 @@ function useModalStyles(theme) {
840
902
  borderRadius: theme.radii.input,
841
903
  paddingVertical: theme.spacing.sm,
842
904
  paddingHorizontal: theme.spacing.md,
843
- // Match the submit button: never shrink below the label width.
844
- flexShrink: 0,
845
905
  borderWidth: SECONDARY_BORDER_WIDTH,
846
906
  borderColor: theme.colors.border
847
907
  },
@@ -1502,7 +1562,8 @@ function OtpForm({
1502
1562
  theme: themeProp,
1503
1563
  labels: labelsProp,
1504
1564
  onSuccess,
1505
- testIdPrefix
1565
+ testIdPrefix,
1566
+ chromeless = false
1506
1567
  }) {
1507
1568
  const theme = useAuthTheme(themeProp);
1508
1569
  const styles3 = useAuthStyles(theme);
@@ -1523,7 +1584,7 @@ function OtpForm({
1523
1584
  otp.reset();
1524
1585
  }, [otp]);
1525
1586
  const errorText = localError ?? transportErrorFor(otp.step, otp.error, labels);
1526
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.card, testID: withTestIdPrefix(AuthTestIds.otpForm, testIdPrefix), children: otp.step === "requestCode" /* RequestCode */ ? /* @__PURE__ */ jsxRuntime.jsx(
1587
+ const content = otp.step === "requestCode" /* RequestCode */ ? /* @__PURE__ */ jsxRuntime.jsx(
1527
1588
  OtpRequestStep,
1528
1589
  {
1529
1590
  errorText,
@@ -1548,7 +1609,16 @@ function OtpForm({
1548
1609
  onResend: handleResend,
1549
1610
  onSubmit: handleVerify
1550
1611
  }
1551
- ) }) });
1612
+ );
1613
+ const card = /* @__PURE__ */ jsxRuntime.jsx(
1614
+ reactNative.View,
1615
+ {
1616
+ style: chromeless ? void 0 : styles3.card,
1617
+ testID: withTestIdPrefix(AuthTestIds.otpForm, testIdPrefix),
1618
+ children: content
1619
+ }
1620
+ );
1621
+ return chromeless ? card : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: card });
1552
1622
  }
1553
1623
  function toError3(value) {
1554
1624
  return value instanceof Error ? value : new Error(String(value));
@@ -1627,7 +1697,8 @@ function PinForm({
1627
1697
  theme: themeProp,
1628
1698
  labels: labelsProp,
1629
1699
  onSuccess,
1630
- testIdPrefix
1700
+ testIdPrefix,
1701
+ chromeless = false
1631
1702
  }) {
1632
1703
  const theme = useAuthTheme(themeProp);
1633
1704
  const styles3 = useAuthStyles(theme);
@@ -1641,7 +1712,7 @@ function PinForm({
1641
1712
  const handleSubmit = useSubmitHandler(pin, labels, setLocalError, onSuccess);
1642
1713
  const errorText = localError ?? transportErrorFor2(pin.error, labels);
1643
1714
  const buttonStyle = pin.isSubmitting ? [styles3.primaryButton, styles3.primaryButtonDisabled] : styles3.primaryButton;
1644
- return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.card, testID: withTestIdPrefix(AuthTestIds.pinForm, testIdPrefix), children: [
1715
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1645
1716
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.title, children: labels.title }),
1646
1717
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.subtitle, children: labels.description }),
1647
1718
  /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.fieldGroup, children: [
@@ -1686,7 +1757,16 @@ function PinForm({
1686
1757
  children: pin.isSubmitting ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: theme.colors.onPrimary, size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.primaryButtonText, children: labels.submit })
1687
1758
  }
1688
1759
  )
1689
- ] }) });
1760
+ ] });
1761
+ const card = /* @__PURE__ */ jsxRuntime.jsx(
1762
+ reactNative.View,
1763
+ {
1764
+ style: chromeless ? void 0 : styles3.card,
1765
+ testID: withTestIdPrefix(AuthTestIds.pinForm, testIdPrefix),
1766
+ children: content
1767
+ }
1768
+ );
1769
+ return chromeless ? card : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.screen, children: card });
1690
1770
  }
1691
1771
  var DOT_SIZE = 18;
1692
1772
  var DOT_BORDER_WIDTH = 2;
@@ -2928,9 +3008,11 @@ Object.defineProperty(exports, "createFetchHttpClient", {
2928
3008
  enumerable: true,
2929
3009
  get: function () { return authClient.createFetchHttpClient; }
2930
3010
  });
3011
+ exports.AuthScreen = AuthScreen;
2931
3012
  exports.AuthTestIds = AuthTestIds;
2932
3013
  exports.AuthThemeProvider = AuthThemeProvider;
2933
3014
  exports.BffAuthStatus = BffAuthStatus;
3015
+ exports.DEFAULT_AUTH_CARD_MAX_WIDTH = DEFAULT_AUTH_CARD_MAX_WIDTH;
2934
3016
  exports.DEFAULT_DEVICE_PIN_ENROLL_LABELS = DEFAULT_DEVICE_PIN_ENROLL_LABELS;
2935
3017
  exports.DEFAULT_DEVICE_PIN_SETTINGS_LABELS = DEFAULT_DEVICE_PIN_SETTINGS_LABELS;
2936
3018
  exports.DEFAULT_DEVICE_PIN_UNLOCK_LABELS = DEFAULT_DEVICE_PIN_UNLOCK_LABELS;