@explita/cloud-auth-client 0.1.1 → 0.1.3
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/components/change-password.js +58 -75
- package/dist/components/icons/alert-circle.d.ts +5 -0
- package/dist/components/icons/alert-circle.js +13 -0
- package/dist/components/icons/chevron-down.d.ts +5 -0
- package/dist/components/icons/chevron-down.js +11 -0
- package/dist/components/icons/lock.d.ts +2 -1
- package/dist/components/icons/lock.js +2 -2
- package/dist/components/icons/logout.d.ts +2 -1
- package/dist/components/icons/logout.js +2 -2
- package/dist/components/icons/setting.d.ts +2 -1
- package/dist/components/icons/setting.js +2 -2
- package/dist/components/icons/shield.d.ts +5 -0
- package/dist/components/icons/shield.js +11 -0
- package/dist/components/icons/user.d.ts +5 -0
- package/dist/components/icons/user.js +12 -0
- package/dist/components/login-form.d.ts +3 -1
- package/dist/components/login-form.js +45 -34
- package/dist/components/message.js +2 -2
- package/dist/components/must-login.js +20 -8
- package/dist/components/reset-password.d.ts +2 -1
- package/dist/components/reset-password.js +62 -60
- package/dist/components/settings.js +16 -8
- package/dist/components/signup-form.d.ts +4 -3
- package/dist/components/signup-form.js +72 -60
- package/dist/components/toggle-2fa.js +42 -26
- package/dist/components/toggle-account-status.js +56 -64
- package/dist/components/ui/input.js +1 -1
- package/dist/components/user-card.js +48 -23
- package/dist/contexts/auth-provider.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/lib/utils.js +7 -1
- package/dist/server/user.d.ts +3 -1
- package/dist/server/user.js +33 -0
- package/dist/styles.css +2645 -1805
- package/dist/types.d.ts +21 -7
- package/package.json +65 -65
|
@@ -43,75 +43,77 @@ const input_1 = require("./ui/input");
|
|
|
43
43
|
const label_1 = require("./ui/label");
|
|
44
44
|
const message_1 = require("./message");
|
|
45
45
|
const auth_provider_1 = require("../contexts/auth-provider");
|
|
46
|
-
function ResetPassword({ className, onChangePassword, ...props }) {
|
|
46
|
+
function ResetPassword({ className, onChangePassword, logo, ...props }) {
|
|
47
47
|
const { sendPasswordResetRequest, computedRouteContext } = (0, auth_provider_1.useAuth)();
|
|
48
|
+
const [isPending, setIsPending] = react_1.default.useState(false);
|
|
49
|
+
const [state, setState] = react_1.default.useState({
|
|
50
|
+
message: "",
|
|
51
|
+
//@ts-ignore
|
|
52
|
+
status: "",
|
|
53
|
+
errors: {},
|
|
54
|
+
});
|
|
48
55
|
const [token, setToken] = (0, react_1.useState)(null);
|
|
49
56
|
const { loginUrl } = computedRouteContext;
|
|
50
57
|
(0, react_1.useEffect)(() => {
|
|
51
58
|
const token = new URLSearchParams(window.location.search).get("token");
|
|
52
59
|
setToken(token);
|
|
53
60
|
}, []);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
status: "failure",
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
const result = await onChangePassword({
|
|
67
|
-
token,
|
|
68
|
-
password: formData.get("password"),
|
|
69
|
-
confirmPassword: formData.get("confirmPassword"),
|
|
70
|
-
});
|
|
71
|
-
return result;
|
|
61
|
+
async function handleSubmit(event) {
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
const formData = new FormData(event.currentTarget);
|
|
64
|
+
setIsPending(true);
|
|
65
|
+
if (!token) {
|
|
66
|
+
const result = await sendPasswordResetRequest(formData.get("email"));
|
|
67
|
+
setIsPending(false);
|
|
68
|
+
setState({ ...result });
|
|
69
|
+
return;
|
|
72
70
|
}
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
if (typeof onChangePassword !== "function") {
|
|
72
|
+
setState({
|
|
73
|
+
message: "onChangePassword function is not defined. Please pass onChangePassword function to ResetPassword component.",
|
|
74
|
+
status: "failure",
|
|
75
|
+
});
|
|
76
|
+
return;
|
|
75
77
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
react_1.default.createElement(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
react_1.default.createElement("div", { className: "ecpauth:
|
|
106
|
-
react_1.default.createElement("div", { className: "ecpauth:
|
|
107
|
-
react_1.default.createElement(label_1.Label, { htmlFor: "password" }, "Password"),
|
|
108
|
-
react_1.default.createElement(input_1.Input, { id: "password", type: "password", name: "password" })),
|
|
109
|
-
react_1.default.createElement("div", { className: "ecpauth:
|
|
110
|
-
react_1.default.createElement(label_1.Label, { htmlFor: "confirmPassword" }, "Confirm Password"),
|
|
111
|
-
react_1.default.createElement(input_1.Input, { id: "confirmPassword", type: "password", name: "confirmPassword" })),
|
|
112
|
-
|
|
113
|
-
loginUrl && (react_1.default.createElement("div", { className: "ecpauth:
|
|
78
|
+
setIsPending(true);
|
|
79
|
+
const result = await onChangePassword({
|
|
80
|
+
token,
|
|
81
|
+
password: formData.get("password"),
|
|
82
|
+
confirmPassword: formData.get("confirmPassword"),
|
|
83
|
+
});
|
|
84
|
+
setIsPending(false);
|
|
85
|
+
setState({ ...result });
|
|
86
|
+
}
|
|
87
|
+
return (react_1.default.createElement("div", { className: (0, utils_1.cn)("ecpauth:relative ecpauth:flex ecpauth:flex-col ecpauth:items-center ecpauth:justify-center ecpauth:w-full ecpauth:mx-auto ecpauth:px-4", className), ...props },
|
|
88
|
+
react_1.default.createElement(card_1.Card, { className: "ecpauth:relative ecpauth:w-full ecpauth:max-w-[450px] ecpauth:overflow-hidden ecpauth:shadow-none ecpauth:lg:shadow-xl ecpauth:border-none ecpauth:rounded-xl" },
|
|
89
|
+
react_1.default.createElement(card_1.CardHeader, { className: "ecpauth:space-y-4 ecpauth:text-center ecpauth:pb-2 ecpauth:pt-10" },
|
|
90
|
+
logo && (react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:items-center ecpauth:justify-center ecpauth:space-x-2 ecpauth:text-xl ecpauth:font-bold ecpauth:text-gray-900 ecpauth:dark:text-white" }, logo)),
|
|
91
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
92
|
+
react_1.default.createElement(card_1.CardTitle, { className: "ecpauth:text-2xl ecpauth:font-black ecpauth:tracking-tight ecpauth:text-gray-900 ecpauth:dark:text-white" }, "Reset Password"),
|
|
93
|
+
react_1.default.createElement(card_1.CardDescription, { className: "ecpauth:text-sm ecpauth:text-gray-500 ecpauth:dark:text-gray-400" }, token
|
|
94
|
+
? "Enter your new password below."
|
|
95
|
+
: "Provide your email to receive a reset link.")),
|
|
96
|
+
state?.status === "success" ? (react_1.default.createElement("div", { className: "ecpauth:mt-3" },
|
|
97
|
+
react_1.default.createElement(message_1.Message, { message: state?.message, variant: "success" }))) : state?.message ? (react_1.default.createElement("div", { className: "ecpauth:mt-3" },
|
|
98
|
+
react_1.default.createElement(message_1.Message, { message: state?.message }))) : null),
|
|
99
|
+
react_1.default.createElement(card_1.CardContent, { className: "ecpauth:space-y-6 ecpauth:p-8 ecpauth:px-12" },
|
|
100
|
+
!token ? (react_1.default.createElement("form", { onSubmit: handleSubmit, className: "ecpauth:space-y-6" },
|
|
101
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
102
|
+
react_1.default.createElement(label_1.Label, { htmlFor: "email", className: "ecpauth:text-sm ecpauth:font-medium ecpauth:text-gray-700 ecpauth:dark:text-gray-300" }, "Email Address"),
|
|
103
|
+
react_1.default.createElement(input_1.Input, { id: "email", type: "email", placeholder: "email@example.com", name: "email", defaultValue:
|
|
104
|
+
//@ts-ignore
|
|
105
|
+
state?.form?.email, className: "ecpauth:h-11 ecpauth:border-blue-200 ecpauth:focus-visible:ring-blue-500 ecpauth:focus-visible:border-blue-500 ecpauth:placeholder:text-gray-400 ecpauth:rounded-lg" })),
|
|
106
|
+
react_1.default.createElement(button_1.Button, { type: "submit", className: "ecpauth:w-full ecpauth:h-11 ecpauth:bg-blue-600! ecpauth:hover:bg-blue-700! ecpauth:text-white! ecpauth:font-semibold ecpauth:text-base ecpauth:shadow-lg ecpauth:shadow-blue-600/20 ecpauth:rounded-lg ecpauth:transition-all ecpauth:active:scale-[0.98]", disabled: isPending }, isPending ? "Sending..." : "Send Reset Link"))) : (react_1.default.createElement("form", { onSubmit: handleSubmit, className: "ecpauth:space-y-6" },
|
|
107
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-4" },
|
|
108
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
109
|
+
react_1.default.createElement(label_1.Label, { htmlFor: "password", className: "ecpauth:text-sm ecpauth:font-medium ecpauth:text-gray-700 ecpauth:dark:text-gray-300" }, "New Password"),
|
|
110
|
+
react_1.default.createElement(input_1.Input, { id: "password", type: "password", name: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", className: "ecpauth:h-11 ecpauth:border-blue-200 ecpauth:focus-visible:ring-blue-500 ecpauth:focus-visible:border-blue-500 ecpauth:placeholder:text-gray-400 ecpauth:rounded-lg" })),
|
|
111
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
112
|
+
react_1.default.createElement(label_1.Label, { htmlFor: "confirmPassword", className: "ecpauth:text-sm ecpauth:font-medium ecpauth:text-gray-700 ecpauth:dark:text-gray-300" }, "Confirm New Password"),
|
|
113
|
+
react_1.default.createElement(input_1.Input, { id: "confirmPassword", type: "password", name: "confirmPassword", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", className: "ecpauth:h-11 ecpauth:border-blue-200 ecpauth:focus-visible:ring-blue-500 ecpauth:focus-visible:border-blue-500 ecpauth:placeholder:text-gray-400 ecpauth:rounded-lg" }))),
|
|
114
|
+
react_1.default.createElement(button_1.Button, { type: "submit", className: "ecpauth:w-full ecpauth:h-11 ecpauth:bg-blue-600! ecpauth:hover:bg-blue-700! ecpauth:text-white! ecpauth:font-semibold ecpauth:text-base ecpauth:shadow-lg ecpauth:shadow-blue-600/20 ecpauth:rounded-lg ecpauth:transition-all ecpauth:active:scale-[0.98]", disabled: isPending }, isPending ? "Resetting..." : "Reset Password"))),
|
|
115
|
+
loginUrl && (react_1.default.createElement("div", { className: "ecpauth:text-center ecpauth:text-sm ecpauth:text-gray-500 ecpauth:border-t ecpauth:border-gray-100 ecpauth:dark:border-gray-800 ecpauth:pt-6" },
|
|
114
116
|
"Back to",
|
|
115
117
|
" ",
|
|
116
|
-
react_1.default.createElement("a", { href: loginUrl, className: "ecpauth:underline ecpauth:
|
|
118
|
+
react_1.default.createElement("a", { href: loginUrl, className: "ecpauth:font-semibold ecpauth:text-gray-900 ecpauth:hover:underline ecpauth:dark:text-white" }, "Login")))))));
|
|
117
119
|
}
|
|
@@ -10,20 +10,28 @@ const auth_provider_1 = require("../contexts/auth-provider");
|
|
|
10
10
|
const must_login_1 = require("./must-login");
|
|
11
11
|
const toggle_2fa_1 = require("./toggle-2fa");
|
|
12
12
|
const utils_1 = require("../lib/utils");
|
|
13
|
+
const setting_1 = require("./icons/setting");
|
|
13
14
|
function Settings({ open, onOpenChange, onToggle2FA }) {
|
|
14
15
|
const { user } = (0, auth_provider_1.useAuth)();
|
|
15
16
|
return (react_1.default.createElement(dialog_1.Dialog, { open: open, onOpenChange: (state) => {
|
|
16
17
|
onOpenChange(state);
|
|
17
18
|
(0, utils_1.unstuckPointerEvents)();
|
|
18
19
|
} },
|
|
19
|
-
react_1.default.createElement(dialog_1.DialogContent,
|
|
20
|
+
react_1.default.createElement(dialog_1.DialogContent, { className: "ecpauth:p-0 ecpauth:overflow-hidden ecpauth:border-gray-200 ecpauth:dark:border-gray-800 ecpauth:shadow-2xl ecpauth:rounded-2xl ecpauth:max-w-xl" }, !user ? (react_1.default.createElement(must_login_1.MustLogin, { onOpenChange: (state) => {
|
|
20
21
|
onOpenChange(state);
|
|
21
22
|
(0, utils_1.unstuckPointerEvents)();
|
|
22
|
-
} })) : (react_1.default.createElement("div", { className: "ecpauth:
|
|
23
|
-
react_1.default.createElement(
|
|
24
|
-
react_1.default.createElement(
|
|
25
|
-
react_1.default.createElement("
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
} })) : (react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:flex-col" },
|
|
24
|
+
react_1.default.createElement("div", { className: "ecpauth:relative ecpauth:px-6 ecpauth:pt-8 ecpauth:pb-6 ecpauth:border-b ecpauth:border-gray-100 ecpauth:dark:border-gray-800/50" },
|
|
25
|
+
react_1.default.createElement("div", { className: "ecpauth:relative ecpauth:z-10 ecpauth:flex ecpauth:items-center ecpauth:gap-4" },
|
|
26
|
+
react_1.default.createElement("div", { className: "ecpauth:size-12 ecpauth:rounded-xl ecpauth:bg-blue-50 ecpauth:dark:bg-blue-900/20 ecpauth:text-blue-600 ecpauth:dark:text-blue-400 ecpauth:flex ecpauth:items-center ecpauth:justify-center ecpauth:shadow-sm ecpauth:border ecpauth:border-blue-100 ecpauth:dark:border-blue-800/50" },
|
|
27
|
+
react_1.default.createElement(setting_1.SettingIcon, { size: 24 })),
|
|
28
|
+
react_1.default.createElement(dialog_1.DialogHeader, { className: "ecpauth:space-y-0.5" },
|
|
29
|
+
react_1.default.createElement(dialog_1.DialogTitle, { className: "ecpauth:text-xl ecpauth:font-bold ecpauth:text-gray-900 ecpauth:dark:text-white" }, "Account Settings"),
|
|
30
|
+
react_1.default.createElement(dialog_1.DialogDescription, { className: "ecpauth:text-sm ecpauth:text-gray-500 ecpauth:dark:text-gray-400" }, "Manage your security preferences and account details.")))),
|
|
31
|
+
react_1.default.createElement("div", { className: "ecpauth:p-6 ecpauth:overflow-y-auto ecpauth:max-h-[70vh]" },
|
|
32
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-8" },
|
|
33
|
+
react_1.default.createElement("section", null,
|
|
34
|
+
react_1.default.createElement(toggle_2fa_1.Toggle2FA, { onSubmit: onToggle2FA })))),
|
|
35
|
+
react_1.default.createElement("div", { className: "ecpauth:px-6 ecpauth:py-4 ecpauth:bg-gray-50 ecpauth:dark:bg-gray-900/50 ecpauth:border-t ecpauth:border-gray-100 ecpauth:dark:border-gray-800/50 ecpauth:flex ecpauth:justify-end" },
|
|
36
|
+
react_1.default.createElement("button", { type: "button", onClick: () => onOpenChange(false), className: "ecpauth:px-4 ecpauth:py-2 ecpauth:text-sm ecpauth:font-semibold ecpauth:text-gray-600 ecpauth:dark:text-gray-400 ecpauth:hover:text-gray-900 ecpauth:dark:hover:text-white ecpauth:transition-colors" }, "Close Settings")))))));
|
|
29
37
|
}
|
|
@@ -3,9 +3,10 @@ import { CreateUser, FormResponse, User } from "../types";
|
|
|
3
3
|
type Props = {
|
|
4
4
|
className?: string;
|
|
5
5
|
onSubmit: (data: CreateUser) => Promise<FormResponse<User>>;
|
|
6
|
-
groupId
|
|
7
|
-
|
|
6
|
+
groupId: string | number;
|
|
7
|
+
metadata?: Record<string, string>;
|
|
8
8
|
acceptUsername?: boolean;
|
|
9
|
+
logo?: React.ReactNode;
|
|
9
10
|
};
|
|
10
|
-
export declare function Signup({ className, onSubmit, groupId,
|
|
11
|
+
export declare function Signup({ className, onSubmit, groupId, metadata, acceptUsername, logo, ...props }: Props): React.JSX.Element;
|
|
11
12
|
export {};
|
|
@@ -43,10 +43,22 @@ const input_1 = require("./ui/input");
|
|
|
43
43
|
const label_1 = require("./ui/label");
|
|
44
44
|
const message_1 = require("./message");
|
|
45
45
|
const auth_provider_1 = require("../contexts/auth-provider");
|
|
46
|
-
function Signup({ className, onSubmit, groupId,
|
|
46
|
+
function Signup({ className, onSubmit, groupId, metadata, acceptUsername = true, logo, ...props }) {
|
|
47
47
|
const { computedRouteContext } = (0, auth_provider_1.useAuth)();
|
|
48
|
+
const [isPending, setIsPending] = react_1.default.useState(false);
|
|
49
|
+
const [state, setState] = react_1.default.useState({
|
|
50
|
+
message: "",
|
|
51
|
+
//@ts-ignore
|
|
52
|
+
status: "",
|
|
53
|
+
form: {},
|
|
54
|
+
errors: undefined,
|
|
55
|
+
authToken: "",
|
|
56
|
+
});
|
|
48
57
|
const { loginUrl } = computedRouteContext;
|
|
49
|
-
|
|
58
|
+
async function handleSubmit(e) {
|
|
59
|
+
e.preventDefault();
|
|
60
|
+
const formData = new FormData(e.currentTarget);
|
|
61
|
+
//@ts-ignore
|
|
50
62
|
const form = {
|
|
51
63
|
firstName: formData.get("firstName"),
|
|
52
64
|
lastName: formData.get("lastName"),
|
|
@@ -55,24 +67,26 @@ function Signup({ className, onSubmit, groupId, metaData, acceptUsername = true,
|
|
|
55
67
|
password: formData.get("password"),
|
|
56
68
|
confirmPassword: formData.get("confirmPassword"),
|
|
57
69
|
groupId,
|
|
58
|
-
|
|
70
|
+
metadata,
|
|
59
71
|
};
|
|
60
72
|
if (typeof onSubmit !== "function") {
|
|
61
|
-
|
|
73
|
+
setState({
|
|
62
74
|
message: "onSubmit function is not defined. Please pass onSubmit function to SignupForm component.",
|
|
63
75
|
status: "failure",
|
|
64
|
-
|
|
76
|
+
//@ts-ignore
|
|
65
77
|
errors: undefined,
|
|
66
78
|
authToken: undefined,
|
|
67
|
-
};
|
|
79
|
+
});
|
|
68
80
|
}
|
|
81
|
+
setIsPending(true);
|
|
69
82
|
const result = await onSubmit({ ...form });
|
|
70
|
-
|
|
83
|
+
setIsPending(false);
|
|
84
|
+
setState({
|
|
71
85
|
...result,
|
|
72
|
-
|
|
86
|
+
//@ts-ignore
|
|
73
87
|
authToken: result.status === "success" ? result.authToken : undefined,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
76
90
|
(0, react_1.useEffect)(() => {
|
|
77
91
|
let timer;
|
|
78
92
|
if (state?.status === "success" && loginUrl) {
|
|
@@ -84,54 +98,52 @@ function Signup({ className, onSubmit, groupId, metaData, acceptUsername = true,
|
|
|
84
98
|
clearTimeout(timer);
|
|
85
99
|
};
|
|
86
100
|
}, [state?.status, loginUrl]);
|
|
87
|
-
return (react_1.default.createElement("div", { className: (0, utils_1.cn)("ecpauth:flex ecpauth:flex-col ecpauth:
|
|
88
|
-
react_1.default.createElement(card_1.Card,
|
|
89
|
-
react_1.default.createElement(card_1.CardHeader,
|
|
90
|
-
react_1.default.createElement(
|
|
91
|
-
react_1.default.createElement(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
react_1.default.createElement("
|
|
95
|
-
react_1.default.createElement("div", { className: "ecpauth:
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
react_1.default.createElement("div", { className: "ecpauth:
|
|
121
|
-
react_1.default.createElement(label_1.Label, { htmlFor: "password" }, "Password"),
|
|
122
|
-
react_1.default.createElement(input_1.Input, { id: "password", type: "password", name: "password" }),
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
react_1.default.createElement(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
" ",
|
|
136
|
-
react_1.default.createElement("a", { href: loginUrl, className: "ecpauth:underline ecpauth:underline-offset-4" }, "Login"))))))));
|
|
101
|
+
return (react_1.default.createElement("div", { className: (0, utils_1.cn)("ecpauth:relative ecpauth:flex ecpauth:flex-col ecpauth:items-center ecpauth:justify-center ecpauth:w-full ecpauth:mx-auto ecpauth:px-4", className), ...props },
|
|
102
|
+
react_1.default.createElement(card_1.Card, { className: "ecpauth:relative ecpauth:w-full ecpauth:max-w-[550px] ecpauth:overflow-hidden ecpauth:shadow-none ecpauth:lg:shadow-xl ecpauth:border-none ecpauth:rounded-xl" },
|
|
103
|
+
react_1.default.createElement(card_1.CardHeader, { className: "ecpauth:space-y-4 ecpauth:text-center ecpauth:pb-2 ecpauth:pt-10" },
|
|
104
|
+
logo && (react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:items-center ecpauth:justify-center ecpauth:space-x-2 ecpauth:text-xl ecpauth:font-bold ecpauth:text-gray-900 ecpauth:dark:text-white" }, logo)),
|
|
105
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
106
|
+
react_1.default.createElement(card_1.CardTitle, { className: "ecpauth:text-2xl ecpauth:font-black ecpauth:tracking-tight ecpauth:text-gray-900 ecpauth:dark:text-white" }, "Create Account"),
|
|
107
|
+
react_1.default.createElement(card_1.CardDescription, { className: "ecpauth:text-sm ecpauth:text-gray-500 ecpauth:dark:text-gray-400" }, "Provide your details to sign up for your account.")),
|
|
108
|
+
state?.status === "success" ? (react_1.default.createElement("div", { className: "ecpauth:mt-3" },
|
|
109
|
+
react_1.default.createElement(message_1.Message, { message: state?.message, variant: "success" }))) : state?.message ? (react_1.default.createElement("div", { className: "ecpauth:mt-3" },
|
|
110
|
+
react_1.default.createElement(message_1.Message, { message: state?.message }))) : null),
|
|
111
|
+
react_1.default.createElement(card_1.CardContent, { className: "ecpauth:space-y-6 ecpauth:p-8 ecpauth:px-12" },
|
|
112
|
+
react_1.default.createElement("form", { onSubmit: handleSubmit, className: "ecpauth:space-y-6" },
|
|
113
|
+
react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:grid-cols-1 ecpauth:md:grid-cols-2 ecpauth:gap-4" },
|
|
114
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
115
|
+
react_1.default.createElement(label_1.Label, { htmlFor: "firstName", className: "ecpauth:text-sm ecpauth:font-medium ecpauth:text-gray-700 ecpauth:dark:text-gray-300" }, "First Name"),
|
|
116
|
+
react_1.default.createElement(input_1.Input, { id: "firstName", type: "text", placeholder: "First Name", name: "firstName" }),
|
|
117
|
+
state?.status === "validation-error" &&
|
|
118
|
+
state?.errors?.firstName && (react_1.default.createElement("p", { className: "ecpauth:mt-1 ecpauth:text-[11px] ecpauth:text-red-500" }, state.errors.firstName))),
|
|
119
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
120
|
+
react_1.default.createElement(label_1.Label, { htmlFor: "lastName", className: "ecpauth:text-sm ecpauth:font-medium ecpauth:text-gray-700 ecpauth:dark:text-gray-300" }, "Last Name"),
|
|
121
|
+
react_1.default.createElement(input_1.Input, { id: "lastName", type: "text", placeholder: "Last Name", name: "lastName" }),
|
|
122
|
+
state?.status === "validation-error" &&
|
|
123
|
+
state?.errors?.lastName && (react_1.default.createElement("p", { className: "ecpauth:mt-1 ecpauth:text-[11px] ecpauth:text-red-500" }, state.errors.lastName)))),
|
|
124
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
125
|
+
react_1.default.createElement(label_1.Label, { htmlFor: "email", className: "ecpauth:text-sm ecpauth:font-medium ecpauth:text-gray-700 ecpauth:dark:text-gray-300" }, "Email Address"),
|
|
126
|
+
react_1.default.createElement(input_1.Input, { id: "email", type: "email", placeholder: "email@example.com", name: "email" }),
|
|
127
|
+
state?.status === "validation-error" && state?.errors?.email && (react_1.default.createElement("p", { className: "ecpauth:mt-1 ecpauth:text-[11px] ecpauth:text-red-500" }, state.errors.email))),
|
|
128
|
+
acceptUsername && (react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
129
|
+
react_1.default.createElement(label_1.Label, { htmlFor: "username", className: "ecpauth:text-sm ecpauth:font-medium ecpauth:text-gray-700 ecpauth:dark:text-gray-300" }, "Username"),
|
|
130
|
+
react_1.default.createElement(input_1.Input, { id: "username", type: "text", placeholder: "Username", name: "username" }),
|
|
131
|
+
state?.status === "validation-error" &&
|
|
132
|
+
state?.errors?.username && (react_1.default.createElement("p", { className: "ecpauth:mt-1 ecpauth:text-[11px] ecpauth:text-red-500" }, state.errors.username)))),
|
|
133
|
+
react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:grid-cols-1 ecpauth:md:grid-cols-2 ecpauth:gap-4" },
|
|
134
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
135
|
+
react_1.default.createElement(label_1.Label, { htmlFor: "password", className: "ecpauth:text-sm ecpauth:font-medium ecpauth:text-gray-700 ecpauth:dark:text-gray-300" }, "Password"),
|
|
136
|
+
react_1.default.createElement(input_1.Input, { id: "password", type: "password", name: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }),
|
|
137
|
+
state?.status === "validation-error" &&
|
|
138
|
+
state?.errors?.password && (react_1.default.createElement("p", { className: "ecpauth:mt-1 ecpauth:text-[11px] ecpauth:text-red-500" }, state.errors.password))),
|
|
139
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
140
|
+
react_1.default.createElement(label_1.Label, { htmlFor: "confirmPassword", className: "ecpauth:text-sm ecpauth:font-medium ecpauth:text-gray-700 ecpauth:dark:text-gray-300" }, "Confirm Password"),
|
|
141
|
+
react_1.default.createElement(input_1.Input, { id: "confirmPassword", type: "password", name: "confirmPassword", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }),
|
|
142
|
+
state?.status === "validation-error" &&
|
|
143
|
+
state?.errors?.confirmPassword && (react_1.default.createElement("p", { className: "ecpauth:mt-1 ecpauth:text-[11px] ecpauth:text-red-500" }, state.errors.confirmPassword)))),
|
|
144
|
+
react_1.default.createElement(button_1.Button, { type: "submit", className: "ecpauth:w-full ecpauth:h-11 ecpauth:bg-blue-600! ecpauth:hover:bg-blue-700! ecpauth:text-white! ecpauth:font-semibold ecpauth:text-base ecpauth:shadow-lg ecpauth:shadow-blue-600/20 ecpauth:rounded-lg ecpauth:transition-all ecpauth:active:scale-[0.98]", disabled: isPending }, isPending ? "Signing up..." : "Sign Up")),
|
|
145
|
+
loginUrl && (react_1.default.createElement("div", { className: "ecpauth:text-center ecpauth:text-sm ecpauth:text-gray-500 ecpauth:border-t ecpauth:border-gray-100 ecpauth:dark:border-gray-800 ecpauth:pt-6" },
|
|
146
|
+
"Already have an account?",
|
|
147
|
+
" ",
|
|
148
|
+
react_1.default.createElement("a", { href: loginUrl, className: "ecpauth:font-semibold ecpauth:text-gray-900 ecpauth:hover:underline ecpauth:dark:text-white" }, "Login")))))));
|
|
137
149
|
}
|
|
@@ -41,41 +41,57 @@ const switch_1 = require("./ui/switch");
|
|
|
41
41
|
const loader_1 = require("./loader");
|
|
42
42
|
const message_1 = require("./message");
|
|
43
43
|
const utils_1 = require("../lib/utils");
|
|
44
|
+
const shield_1 = require("./icons/shield");
|
|
44
45
|
function Toggle2FA({ onSubmit }) {
|
|
45
46
|
const { user, revalidate } = (0, auth_provider_1.useAuth)();
|
|
47
|
+
const [isPending, setIsPending] = react_1.default.useState(false);
|
|
48
|
+
const [state, setState] = react_1.default.useState({
|
|
49
|
+
message: "",
|
|
50
|
+
//@ts-ignore
|
|
51
|
+
status: "",
|
|
52
|
+
});
|
|
46
53
|
const [_, startTransition] = (0, react_1.useTransition)();
|
|
47
54
|
const canUseOtp = (0, utils_1.isOtpAvailable)();
|
|
48
|
-
|
|
55
|
+
async function handleSubmit() {
|
|
49
56
|
if (typeof onSubmit !== "function") {
|
|
50
|
-
|
|
57
|
+
setState({
|
|
51
58
|
message: "Toggle 2FA function is not defined. Please pass onSubmit function to Settings component. If you are using UserCard component, please pass onToggle2FA function to it.",
|
|
52
59
|
status: "failure",
|
|
53
|
-
};
|
|
60
|
+
});
|
|
61
|
+
return;
|
|
54
62
|
}
|
|
55
|
-
|
|
56
|
-
|
|
63
|
+
setIsPending(true);
|
|
64
|
+
const result = await onSubmit();
|
|
65
|
+
if (result.status !== "failure") {
|
|
57
66
|
revalidate();
|
|
58
|
-
return result;
|
|
59
67
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
},
|
|
64
|
-
return (react_1.default.createElement("div", { className: "ecpauth:text-stone-800 ecpauth:dark:text-stone-50" },
|
|
68
|
+
setIsPending(false);
|
|
69
|
+
setState(result);
|
|
70
|
+
}
|
|
71
|
+
return (react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:flex-col ecpauth:gap-6 ecpauth:text-gray-900 ecpauth:dark:text-white" },
|
|
65
72
|
isPending && react_1.default.createElement(loader_1.Loader, null),
|
|
66
|
-
react_1.default.createElement("
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
react_1.default.createElement("
|
|
71
|
-
|
|
72
|
-
react_1.default.createElement("div", { className: "ecpauth:
|
|
73
|
-
react_1.default.createElement("
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-1.5" },
|
|
74
|
+
react_1.default.createElement("h3", { className: "ecpauth:text-base ecpauth:font-bold ecpauth:flex ecpauth:items-center ecpauth:gap-2" },
|
|
75
|
+
react_1.default.createElement(shield_1.ShieldIcon, { size: 18, className: "ecpauth:text-blue-600 ecpauth:dark:text-blue-400" }),
|
|
76
|
+
"Two-Factor Authentication"),
|
|
77
|
+
react_1.default.createElement("p", { className: "ecpauth:text-sm ecpauth:text-gray-500 ecpauth:dark:text-gray-400" }, "Add an extra layer of security to your account by requiring a verification code.")),
|
|
78
|
+
state?.status === "success" ? (react_1.default.createElement(message_1.Message, { message: state?.message, variant: "success" })) : state?.message ? (react_1.default.createElement(message_1.Message, { message: state?.message })) : null,
|
|
79
|
+
react_1.default.createElement("div", { className: "ecpauth:group ecpauth:relative ecpauth:p-4 ecpauth:rounded-xl ecpauth:border ecpauth:border-gray-200 ecpauth:dark:border-gray-800 ecpauth:bg-gray-50/50 ecpauth:dark:bg-white/5 ecpauth:transition-all ecpauth:hover:border-blue-200 ecpauth:dark:hover:border-blue-900/30" },
|
|
80
|
+
react_1.default.createElement("div", { className: "ecpauth:flex ecpauth:items-start ecpauth:justify-between ecpauth:gap-4" },
|
|
81
|
+
react_1.default.createElement("div", { className: "ecpauth:space-y-1" },
|
|
82
|
+
react_1.default.createElement("p", { className: "ecpauth:text-sm ecpauth:font-bold ecpauth:text-gray-900 ecpauth:dark:text-white" }, "Email Authentication"),
|
|
83
|
+
react_1.default.createElement("p", { className: "ecpauth:text-xs ecpauth:leading-relaxed ecpauth:text-gray-500 ecpauth:dark:text-gray-400" },
|
|
84
|
+
"A verification code will be sent to",
|
|
85
|
+
" ",
|
|
86
|
+
react_1.default.createElement("span", { className: "ecpauth:font-semibold ecpauth:text-gray-700 ecpauth:dark:text-gray-200" }, user?.email),
|
|
87
|
+
" ",
|
|
88
|
+
"whenever you sign in.")),
|
|
89
|
+
react_1.default.createElement("div", { className: "ecpauth:pt-1" },
|
|
90
|
+
react_1.default.createElement(switch_1.Switch, { checked: !!user?.with2fa, onCheckedChange: () => startTransition(handleSubmit), disabled: !canUseOtp, className: "ecpauth:data-[state=checked]:bg-blue-600" }))),
|
|
91
|
+
!canUseOtp && (react_1.default.createElement("div", { className: "ecpauth:mt-3 ecpauth:pt-3 ecpauth:border-t ecpauth:border-gray-200/50 ecpauth:dark:border-gray-800/50" },
|
|
92
|
+
react_1.default.createElement("p", { className: "ecpauth:text-[11px] ecpauth:text-red-500 ecpauth:flex ecpauth:items-center ecpauth:gap-1.5 ecpauth:font-medium" },
|
|
93
|
+
react_1.default.createElement("span", { className: "ecpauth:size-1.5 ecpauth:bg-red-500 ecpauth:rounded-full ecpauth:animate-pulse" }),
|
|
94
|
+
"Feature unavailable: please install @explita/cloud-otp-client")))),
|
|
95
|
+
react_1.default.createElement("div", { className: "ecpauth:px-2" },
|
|
96
|
+
react_1.default.createElement("p", { className: "ecpauth:text-[11px] ecpauth:text-gray-400 ecpauth:dark:text-gray-500 ecpauth:italic" }, "Note: Disabling 2FA makes your account and your data more vulnerable to unauthorized access."))));
|
|
81
97
|
}
|