@crossmint/client-sdk-react-ui 1.7.1 → 1.9.1
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.cjs +1 -1
- package/dist/index.d.cts +20 -7
- package/dist/index.d.ts +20 -7
- package/dist/index.js +1 -1
- package/package.json +17 -7
- package/src/components/auth/AuthForm.tsx +50 -0
- package/src/components/auth/AuthFormBackButton.tsx +26 -0
- package/src/components/auth/AuthFormDialog.tsx +33 -0
- package/src/components/auth/EmbeddedAuthForm.tsx +5 -0
- package/src/components/auth/methods/email/EmailAuthFlow.tsx +19 -0
- package/src/components/auth/methods/email/EmailOTPInput.tsx +123 -0
- package/src/components/auth/methods/email/EmailSignIn.tsx +113 -0
- package/src/components/auth/methods/farcaster/FarcasterSignIn.tsx +170 -0
- package/src/components/auth/methods/google/GoogleSignIn.tsx +62 -0
- package/src/components/common/Dialog.tsx +141 -0
- package/src/components/common/Divider.tsx +25 -0
- package/src/components/common/InputOTP.tsx +89 -0
- package/src/components/common/PoweredByCrossmint.tsx +4 -9
- package/src/components/common/Spinner.tsx +22 -0
- package/src/components/dynamic-xyz/DynamicContextProviderWrapper.tsx +31 -0
- package/src/components/embed/v3/CrossmintEmbeddedCheckoutV3.tsx +7 -0
- package/src/components/embed/v3/EmbeddedCheckoutV3IFrame.tsx +74 -0
- package/src/components/embed/v3/crypto/CryptoWalletConnectionHandler.tsx +138 -0
- package/src/components/embed/v3/crypto/utils/handleEvmTransaction.ts +65 -0
- package/src/components/embed/v3/crypto/utils/handleSendTransaction.ts +31 -0
- package/src/components/embed/v3/crypto/utils/handleSolanaTransaction.ts +51 -0
- package/src/components/embed/v3/index.ts +1 -0
- package/src/components/index.ts +3 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useAuthSignIn.ts +117 -0
- package/src/hooks/useCrossmintCheckout.tsx +54 -0
- package/src/hooks/useOAuthWindowListener.ts +87 -0
- package/src/hooks/useRefreshToken.test.ts +21 -8
- package/src/hooks/useRefreshToken.ts +5 -4
- package/src/icons/alert.tsx +19 -0
- package/src/icons/discord.tsx +18 -0
- package/src/icons/emailOTP.tsx +147 -0
- package/src/icons/farcaster.tsx +26 -0
- package/src/icons/google.tsx +30 -0
- package/src/icons/leftArrow.tsx +20 -0
- package/src/icons/poweredByLeaf.tsx +2 -2
- package/src/providers/CrossmintAuthProvider.test.tsx +4 -3
- package/src/providers/CrossmintAuthProvider.tsx +36 -32
- package/src/providers/CrossmintWalletProvider.tsx +3 -3
- package/src/providers/auth/AuthFormProvider.test.tsx +105 -0
- package/src/providers/auth/AuthFormProvider.tsx +116 -0
- package/src/providers/auth/FarcasterProvider.tsx +12 -0
- package/src/twind.config.ts +101 -1
- package/src/types/auth.ts +4 -0
- package/src/utils/authCookies.ts +0 -3
- package/src/utils/createCrossmintApiClient.ts +17 -0
- package/src/components/auth/AuthModal.tsx +0 -207
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { Dialog, Transition } from "@headlessui/react";
|
|
2
|
-
import { type CSSProperties, Fragment, useEffect, useRef, useState } from "react";
|
|
3
|
-
import { z } from "zod";
|
|
4
|
-
|
|
5
|
-
import { IFrameWindow } from "@crossmint/client-sdk-window";
|
|
6
|
-
import type { UIConfig } from "@crossmint/common-sdk-base";
|
|
7
|
-
import { CrossmintInternalEvents } from "@crossmint/client-sdk-base";
|
|
8
|
-
import type { AuthMaterial } from "@crossmint/common-sdk-auth";
|
|
9
|
-
import type { LoginMethod } from "@/providers";
|
|
10
|
-
|
|
11
|
-
import X from "../../icons/x";
|
|
12
|
-
|
|
13
|
-
const authMaterialSchema = z.object({
|
|
14
|
-
oneTimeSecret: z.string(),
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
const incomingModalIframeEvents = {
|
|
18
|
-
authMaterialFromAuthFrame: authMaterialSchema,
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
type IncomingModalIframeEventsType = {
|
|
22
|
-
authMaterialFromAuthFrame: typeof incomingModalIframeEvents.authMaterialFromAuthFrame;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
type AuthModalProps = {
|
|
26
|
-
setModalOpen: (open: boolean) => void;
|
|
27
|
-
apiKey: string;
|
|
28
|
-
fetchAuthMaterial: (refreshToken: string) => Promise<AuthMaterial>;
|
|
29
|
-
baseUrl: string;
|
|
30
|
-
appearance?: UIConfig;
|
|
31
|
-
loginMethods?: LoginMethod[];
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export default function AuthModal({
|
|
35
|
-
setModalOpen,
|
|
36
|
-
apiKey,
|
|
37
|
-
fetchAuthMaterial,
|
|
38
|
-
baseUrl,
|
|
39
|
-
appearance,
|
|
40
|
-
loginMethods,
|
|
41
|
-
}: AuthModalProps) {
|
|
42
|
-
let iframeSrc = `${baseUrl}sdk/2024-09-26/auth/frame?apiKey=${apiKey}`;
|
|
43
|
-
if (appearance != null) {
|
|
44
|
-
// The appearance object is serialized into a query parameter
|
|
45
|
-
iframeSrc += `&uiConfig=${encodeURIComponent(JSON.stringify(appearance))}`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (loginMethods != null) {
|
|
49
|
-
iframeSrc += `&loginMethods=${loginMethods.join(",")}`;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const iframeRef = useRef<HTMLIFrameElement | null>(null);
|
|
53
|
-
const iframeWindowRef = useRef<IFrameWindow<IncomingModalIframeEventsType, Record<string, never>> | null>(null);
|
|
54
|
-
|
|
55
|
-
const [iframeChildrenHeight, setIframeChildrenHeight] = useState(0);
|
|
56
|
-
const iframePaddingTopPX = 48;
|
|
57
|
-
const iframePaddingBottomPX = 32;
|
|
58
|
-
const paddingOffset = iframePaddingTopPX + iframePaddingBottomPX;
|
|
59
|
-
// Farcaster needs more height to render its QR code container.
|
|
60
|
-
const iFrameRenderMinHeightPX = loginMethods?.includes("farcaster") ? 500 : 300;
|
|
61
|
-
|
|
62
|
-
const setupIframeWindowListener = () => {
|
|
63
|
-
if (iframeWindowRef.current == null) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
iframeWindowRef.current.on("authMaterialFromAuthFrame", (data) => {
|
|
68
|
-
fetchAuthMaterial(data.oneTimeSecret);
|
|
69
|
-
iframeWindowRef.current?.off("authMaterialFromAuthFrame");
|
|
70
|
-
setModalOpen(false);
|
|
71
|
-
});
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const handleIframeLoaded = async () => {
|
|
75
|
-
if (iframeRef.current == null) {
|
|
76
|
-
// The iframe should be load, here we should log on DD if possible
|
|
77
|
-
console.error("Something wrong happened, please try again");
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (iframeWindowRef.current == null) {
|
|
82
|
-
const initIframe = await IFrameWindow.init(iframeRef.current, {
|
|
83
|
-
incomingEvents: incomingModalIframeEvents,
|
|
84
|
-
outgoingEvents: {},
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
iframeWindowRef.current = initIframe;
|
|
88
|
-
setupIframeWindowListener();
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
useEffect(() => {
|
|
93
|
-
function _onEvent(event: MessageEvent) {
|
|
94
|
-
if (event.data.type === CrossmintInternalEvents.UI_HEIGHT_CHANGED) {
|
|
95
|
-
setIframeChildrenHeight(event.data.payload.height);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
window.addEventListener("message", _onEvent);
|
|
99
|
-
return () => {
|
|
100
|
-
window.removeEventListener("message", _onEvent);
|
|
101
|
-
};
|
|
102
|
-
}, []);
|
|
103
|
-
|
|
104
|
-
return (
|
|
105
|
-
<Transition.Root show as={Fragment}>
|
|
106
|
-
<Dialog as="div" style={styles.dialog} onClose={() => setModalOpen(false)}>
|
|
107
|
-
<Transition.Child
|
|
108
|
-
as={Fragment}
|
|
109
|
-
enter="ease-out duration-400"
|
|
110
|
-
enterFrom="opacity-0"
|
|
111
|
-
enterTo="opacity-100"
|
|
112
|
-
leave="ease-in duration-400"
|
|
113
|
-
leaveFrom="opacity-100"
|
|
114
|
-
leaveTo="opacity-0"
|
|
115
|
-
>
|
|
116
|
-
<div style={styles.transitionBegin} />
|
|
117
|
-
</Transition.Child>
|
|
118
|
-
<Transition.Child
|
|
119
|
-
as={Fragment}
|
|
120
|
-
enter="ease-out duration-400"
|
|
121
|
-
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
|
122
|
-
enterTo="opacity-100 translate-y-0 sm:scale-100"
|
|
123
|
-
leave="ease-in duration-400"
|
|
124
|
-
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
|
125
|
-
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
|
126
|
-
>
|
|
127
|
-
<div style={styles.transitionEnd} onClick={(e) => e.stopPropagation()}>
|
|
128
|
-
<div style={{ position: "relative", width: "100%" }}>
|
|
129
|
-
<button
|
|
130
|
-
type="button"
|
|
131
|
-
aria-label="Close"
|
|
132
|
-
style={{
|
|
133
|
-
width: "1.5rem",
|
|
134
|
-
position: "absolute",
|
|
135
|
-
right: "1.5rem",
|
|
136
|
-
top: "1.5rem",
|
|
137
|
-
cursor: "pointer",
|
|
138
|
-
color: appearance?.colors?.border ?? "#909ca3",
|
|
139
|
-
outlineOffset: "4px",
|
|
140
|
-
borderRadius: "100%",
|
|
141
|
-
}}
|
|
142
|
-
onClick={() => setModalOpen(false)}
|
|
143
|
-
>
|
|
144
|
-
<X />
|
|
145
|
-
</button>
|
|
146
|
-
</div>
|
|
147
|
-
<iframe
|
|
148
|
-
ref={iframeRef}
|
|
149
|
-
src={iframeSrc}
|
|
150
|
-
onLoad={handleIframeLoaded}
|
|
151
|
-
title="Authentication Modal"
|
|
152
|
-
style={{
|
|
153
|
-
width: "100%",
|
|
154
|
-
minHeight: iFrameRenderMinHeightPX,
|
|
155
|
-
border: "1px solid",
|
|
156
|
-
borderColor: appearance?.colors?.border ?? "#D0D5DD",
|
|
157
|
-
borderRadius: appearance?.borderRadius ?? "1rem",
|
|
158
|
-
backgroundColor: appearance?.colors?.background ?? "white",
|
|
159
|
-
height: iframeChildrenHeight + paddingOffset,
|
|
160
|
-
paddingTop: iframePaddingTopPX,
|
|
161
|
-
paddingBottom: iframePaddingBottomPX,
|
|
162
|
-
}}
|
|
163
|
-
/>
|
|
164
|
-
</div>
|
|
165
|
-
</Transition.Child>
|
|
166
|
-
</Dialog>
|
|
167
|
-
</Transition.Root>
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const styles: { [key: string]: CSSProperties } = {
|
|
172
|
-
dialog: {
|
|
173
|
-
display: "flex",
|
|
174
|
-
justifyContent: "center",
|
|
175
|
-
alignItems: "center",
|
|
176
|
-
overflowY: "auto",
|
|
177
|
-
position: "fixed",
|
|
178
|
-
top: 0,
|
|
179
|
-
right: 0,
|
|
180
|
-
bottom: 0,
|
|
181
|
-
left: 0,
|
|
182
|
-
zIndex: 20,
|
|
183
|
-
},
|
|
184
|
-
transitionBegin: {
|
|
185
|
-
background: "rgba(139, 151, 151, 0.2)",
|
|
186
|
-
backdropFilter: "blur(2px)",
|
|
187
|
-
position: "fixed",
|
|
188
|
-
top: 0,
|
|
189
|
-
right: 0,
|
|
190
|
-
bottom: 0,
|
|
191
|
-
left: 0,
|
|
192
|
-
transitionProperty: "opacity",
|
|
193
|
-
transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
|
|
194
|
-
transitionDuration: "300ms",
|
|
195
|
-
zIndex: -10,
|
|
196
|
-
},
|
|
197
|
-
transitionEnd: {
|
|
198
|
-
display: "flex",
|
|
199
|
-
flexDirection: "column",
|
|
200
|
-
alignItems: "center",
|
|
201
|
-
width: "100%",
|
|
202
|
-
maxWidth: "448px",
|
|
203
|
-
borderRadius: "0.75rem",
|
|
204
|
-
boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
|
205
|
-
zIndex: 30,
|
|
206
|
-
},
|
|
207
|
-
};
|