@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/CHANGELOG.md +17 -17
- package/dist/index.d.mts +167 -85
- package/dist/index.d.ts +167 -85
- package/dist/index.js +158 -69
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +156 -70
- package/dist/index.mjs.map +1 -1
- package/package.json +110 -110
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/
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|