@crossmint/client-sdk-react-ui 0.0.5-alpha.1 → 0.0.5
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/README.md +1 -1
- package/package.json +3 -3
- package/src/CrossMintButton.tsx +14 -3
- package/src/CrossMintModalProvider.tsx +0 -1
- package/src/CrossMintPopupProvider.tsx +18 -12
- package/src/CrossMintProvider.tsx +23 -13
- package/src/CrossMintStatusButton.tsx +71 -0
- package/src/CrossMintStatusProvider.tsx +55 -0
- package/src/index.ts +2 -0
- package/src/useCrossMintPopup.tsx +4 -2
- package/src/useCrossMintStatus.tsx +21 -0
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ CrossMintProvider is a react context that is used to provide your app with our p
|
|
|
8
8
|
|
|
9
9
|
| propName | default | required | description |
|
|
10
10
|
| --------- | ----------- | -------- | ------------------------------------------------------------------------------- |
|
|
11
|
+
| clientId | `undefined` | `true` | Your client integration identifier |
|
|
11
12
|
| className | `undefined` | `false` | Use this to add a custom classname/s to the modal overlay |
|
|
12
13
|
| container | `body` | `false` | Use this to specify the container in which the modal overlay should be rendered |
|
|
13
14
|
|
|
@@ -17,7 +18,6 @@ CrossMintButton is a button component that is used to trigger the opening of the
|
|
|
17
18
|
|
|
18
19
|
| propName | default | required | description |
|
|
19
20
|
| --------------------- | ----------- | -------- | -------------------------------------------------------------------------------------------- |
|
|
20
|
-
| candyMachineId | `undefined` | `true` | This is the ID of the Candy Machine in which you would like to mint from |
|
|
21
21
|
| collectionTitle | `undefined` | `false` | This will be shown to the user during the checkout process. Max length: 120 |
|
|
22
22
|
| collectionDescription | `undefined` | `false` | This will be shown to the user during the checkout process. Max length: 24 |
|
|
23
23
|
| collectionPhoto | `undefined` | `false` | This will be shown to the user during the checkout process. Preferred resolution: 200x200 px |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crossmint/client-sdk-react-ui",
|
|
3
|
-
"version": "0.0.5
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"author": "Paella Labs Inc",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": "https://github.com/CrossMint/crossmint-client-sdk",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"scripts": {
|
|
29
29
|
"clean": "shx rm -rf lib/*",
|
|
30
30
|
"build": "yarn clean && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json",
|
|
31
|
-
"postbuild": "echo
|
|
31
|
+
"postbuild": "echo {\"type\":\"commonjs\"} | npx json > lib/cjs/package.json && echo {\"type\":\"module\"} | npx json > lib/esm/package.json"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"react": "^17.0.2",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"react": "^17.0.2",
|
|
41
41
|
"react-dom": "^17.0.2"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "44f9b3ec082a62a7001d9c9195c8848b62e2b9a1"
|
|
44
44
|
}
|
package/src/CrossMintButton.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { CSSProperties, FC, MouseEvent, MouseEventHandler, useMemo, useCallback } from "react";
|
|
2
|
+
import { OnboardingRequestStatusResponse, useCrossMintStatus } from ".";
|
|
2
3
|
import { useCrossMintPopup } from "./useCrossMintPopup";
|
|
3
4
|
|
|
4
5
|
export interface ButtonProps {
|
|
5
|
-
candyMachineId: string;
|
|
6
6
|
className?: string;
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
onClick?: (e: MouseEvent<HTMLButtonElement>) => void;
|
|
@@ -12,10 +12,12 @@ export interface ButtonProps {
|
|
|
12
12
|
collectionTitle?: string;
|
|
13
13
|
collectionDescription?: string;
|
|
14
14
|
collectionPhoto?: string;
|
|
15
|
+
mintTo?: string;
|
|
16
|
+
emailTo?: string;
|
|
17
|
+
listingId?: string;
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
export const CrossMintButton: FC<ButtonProps> = ({
|
|
18
|
-
candyMachineId,
|
|
19
21
|
className,
|
|
20
22
|
disabled,
|
|
21
23
|
onClick,
|
|
@@ -25,8 +27,13 @@ export const CrossMintButton: FC<ButtonProps> = ({
|
|
|
25
27
|
collectionTitle,
|
|
26
28
|
collectionDescription,
|
|
27
29
|
collectionPhoto,
|
|
30
|
+
mintTo,
|
|
31
|
+
emailTo,
|
|
32
|
+
listingId,
|
|
28
33
|
...props
|
|
29
34
|
}) => {
|
|
35
|
+
const { hideMintOnInactiveClient, status } = useCrossMintStatus();
|
|
36
|
+
|
|
30
37
|
const { connecting, connect } = useCrossMintPopup();
|
|
31
38
|
|
|
32
39
|
const handleClick: MouseEventHandler<HTMLButtonElement> = useCallback(
|
|
@@ -34,7 +41,7 @@ export const CrossMintButton: FC<ButtonProps> = ({
|
|
|
34
41
|
if (onClick) onClick(event);
|
|
35
42
|
|
|
36
43
|
if (!event.defaultPrevented)
|
|
37
|
-
connect(
|
|
44
|
+
connect(collectionTitle, collectionDescription, collectionPhoto, mintTo, emailTo, listingId);
|
|
38
45
|
},
|
|
39
46
|
[onClick]
|
|
40
47
|
);
|
|
@@ -44,6 +51,10 @@ export const CrossMintButton: FC<ButtonProps> = ({
|
|
|
44
51
|
return <p>Buy with credit card</p>;
|
|
45
52
|
}, [connecting]);
|
|
46
53
|
|
|
54
|
+
if (hideMintOnInactiveClient && status !== OnboardingRequestStatusResponse.ACCEPTED) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
47
58
|
return (
|
|
48
59
|
<button
|
|
49
60
|
className={`client-sdk-button-trigger client-sdk-button-trigger-${theme}`}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { FC, ReactNode, useState } from "react";
|
|
2
2
|
import { CrossMintModal, CrossMintModalProps } from "./CrossMintModal";
|
|
3
3
|
import { CrossMintModalContext } from "./useCrossMintModal";
|
|
4
|
-
// import { WalletModal, WalletModalProps } from './WalletModal';
|
|
5
4
|
|
|
6
5
|
export interface CrossMintModalProviderProps extends CrossMintModalProps {
|
|
7
6
|
children: ReactNode;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { FC, ReactNode, useState } from "react";
|
|
2
|
-
import { useCrossMintModal } from ".";
|
|
2
|
+
import { useCrossMintModal, useCrossMintStatus } from ".";
|
|
3
3
|
import { PopupContext } from "./useCrossMintPopup";
|
|
4
4
|
|
|
5
5
|
export interface PopupProviderProps {
|
|
@@ -14,22 +14,26 @@ export const CrossMintPopupProvider: FC<PopupProviderProps> = ({ development, ch
|
|
|
14
14
|
const [connecting, setConnecting] = useState(false);
|
|
15
15
|
const [popup, setPopup] = useState<Window | null>(null);
|
|
16
16
|
|
|
17
|
+
const { clientId } = useCrossMintStatus();
|
|
18
|
+
|
|
17
19
|
const { setVisible } = useCrossMintModal();
|
|
18
20
|
|
|
19
21
|
const createPopup = (
|
|
20
|
-
candyMachineId: string,
|
|
21
22
|
collectionTitle?: string,
|
|
22
23
|
collectionDescription?: string,
|
|
23
|
-
collectionPhoto?: string
|
|
24
|
+
collectionPhoto?: string,
|
|
25
|
+
mintTo?: string,
|
|
26
|
+
emailTo?: string,
|
|
27
|
+
listingId?: string
|
|
24
28
|
) => {
|
|
25
29
|
const pop = window.open(
|
|
26
30
|
`${development ? DEV_URL : PROD_URL}/signin?callbackUrl=${encodeURIComponent(
|
|
27
|
-
`${
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
}${
|
|
32
|
-
|
|
31
|
+
`${development ? DEV_URL : PROD_URL}/checkout/mint?clientId=${clientId}&closeOnSuccess=false${
|
|
32
|
+
collectionTitle && `collectionTitle=${collectionTitle}`
|
|
33
|
+
}${collectionDescription && `&collectionDescription=${collectionDescription}`}${
|
|
34
|
+
collectionPhoto && `&collectionPhoto=${collectionPhoto}`
|
|
35
|
+
}${mintTo && `&mintTo=${mintTo}`}${emailTo && `&emailTo=${emailTo}`}${
|
|
36
|
+
listingId && `&listingId=${listingId}`
|
|
33
37
|
}`
|
|
34
38
|
)}`,
|
|
35
39
|
"popUpWindow",
|
|
@@ -46,16 +50,18 @@ export const CrossMintPopupProvider: FC<PopupProviderProps> = ({ development, ch
|
|
|
46
50
|
};
|
|
47
51
|
|
|
48
52
|
const connect = (
|
|
49
|
-
candyMachineId: string,
|
|
50
53
|
collectionTitle?: string,
|
|
51
54
|
collectionDescription?: string,
|
|
52
|
-
collectionPhoto?: string
|
|
55
|
+
collectionPhoto?: string,
|
|
56
|
+
mintTo?: string,
|
|
57
|
+
emailTo?: string,
|
|
58
|
+
listingId?: string
|
|
53
59
|
) => {
|
|
54
60
|
if (connecting) return;
|
|
55
61
|
|
|
56
62
|
setConnecting(true);
|
|
57
63
|
|
|
58
|
-
createPopup(
|
|
64
|
+
createPopup(collectionTitle, collectionDescription, collectionPhoto, mintTo, emailTo, listingId);
|
|
59
65
|
};
|
|
60
66
|
|
|
61
67
|
function registerListeners(pop: Window) {
|
|
@@ -1,28 +1,38 @@
|
|
|
1
1
|
import React, { FC, ReactNode, useState } from "react";
|
|
2
2
|
import { CrossMintModal, CrossMintModalProps } from "./CrossMintModal";
|
|
3
3
|
import { CrossMintPopupProvider } from "./CrossMintPopupProvider";
|
|
4
|
+
import { CrossMintStatusProvider } from "./CrossMintStatusProvider";
|
|
4
5
|
import { CrossMintModalContext } from "./useCrossMintModal";
|
|
5
|
-
// import { WalletModal, WalletModalProps } from './WalletModal';
|
|
6
6
|
|
|
7
7
|
export interface CrossMintProviderProps extends CrossMintModalProps {
|
|
8
|
+
clientId: string;
|
|
9
|
+
hideMintOnInactiveClient?: boolean;
|
|
8
10
|
development?: boolean;
|
|
9
11
|
children: ReactNode;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
export const CrossMintProvider: FC<CrossMintProviderProps> = ({
|
|
14
|
+
export const CrossMintProvider: FC<CrossMintProviderProps> = ({
|
|
15
|
+
clientId,
|
|
16
|
+
hideMintOnInactiveClient = false,
|
|
17
|
+
development = false,
|
|
18
|
+
children,
|
|
19
|
+
...props
|
|
20
|
+
}) => {
|
|
13
21
|
const [visible, setVisible] = useState(false);
|
|
14
22
|
|
|
15
23
|
return (
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
{
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
<CrossMintStatusProvider clientId={clientId} hideMintOnInactiveClient={hideMintOnInactiveClient}>
|
|
25
|
+
<CrossMintModalContext.Provider
|
|
26
|
+
value={{
|
|
27
|
+
visible,
|
|
28
|
+
setVisible,
|
|
29
|
+
}}
|
|
30
|
+
>
|
|
31
|
+
<CrossMintPopupProvider development={development}>
|
|
32
|
+
{children}
|
|
33
|
+
{visible && <CrossMintModal {...props} />}
|
|
34
|
+
</CrossMintPopupProvider>
|
|
35
|
+
</CrossMintModalContext.Provider>
|
|
36
|
+
</CrossMintStatusProvider>
|
|
27
37
|
);
|
|
28
38
|
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React, { CSSProperties, FC, MouseEvent, MouseEventHandler, useMemo, useCallback } from "react";
|
|
2
|
+
import { OnboardingRequestStatusResponse, useCrossMintStatus } from "./useCrossMintStatus";
|
|
3
|
+
|
|
4
|
+
export interface StatusButtonProps {
|
|
5
|
+
className?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
onClick?: (e: MouseEvent<HTMLButtonElement>) => void;
|
|
8
|
+
style?: CSSProperties;
|
|
9
|
+
tabIndex?: number;
|
|
10
|
+
theme?: "light" | "dark";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const CrossMintStatusButton: FC<StatusButtonProps> = ({
|
|
14
|
+
className,
|
|
15
|
+
disabled,
|
|
16
|
+
onClick,
|
|
17
|
+
style,
|
|
18
|
+
tabIndex,
|
|
19
|
+
theme = "dark",
|
|
20
|
+
...props
|
|
21
|
+
}) => {
|
|
22
|
+
const { status, clientId } = useCrossMintStatus();
|
|
23
|
+
|
|
24
|
+
const handleClick: MouseEventHandler<HTMLButtonElement> = useCallback(
|
|
25
|
+
(event) => {
|
|
26
|
+
if (onClick) onClick(event);
|
|
27
|
+
|
|
28
|
+
if (status === OnboardingRequestStatusResponse.WAITING_SUBMISSION) {
|
|
29
|
+
window.open(
|
|
30
|
+
`https://crossmint.io/developers/onboarding${clientId && `?clientId=${clientId}`}`,
|
|
31
|
+
"_blank"
|
|
32
|
+
);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
[status]
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const content = useMemo(() => {
|
|
40
|
+
switch (status) {
|
|
41
|
+
case OnboardingRequestStatusResponse.INVALID:
|
|
42
|
+
return <p>Invalid clientId</p>;
|
|
43
|
+
case OnboardingRequestStatusResponse.WAITING_SUBMISSION:
|
|
44
|
+
return <p>Click here to setup CrossMint</p>;
|
|
45
|
+
case OnboardingRequestStatusResponse.PENDING:
|
|
46
|
+
return <p>Your application is under review</p>;
|
|
47
|
+
case OnboardingRequestStatusResponse.ACCEPTED:
|
|
48
|
+
return <p>You're good to go!</p>;
|
|
49
|
+
case OnboardingRequestStatusResponse.REJECTED:
|
|
50
|
+
return <p>You're application was rejected</p>;
|
|
51
|
+
}
|
|
52
|
+
}, [status]);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<button
|
|
56
|
+
className={`client-sdk-button-trigger client-sdk-button-trigger-${theme}`}
|
|
57
|
+
disabled={status !== OnboardingRequestStatusResponse.WAITING_SUBMISSION}
|
|
58
|
+
onClick={handleClick}
|
|
59
|
+
style={{ ...style }}
|
|
60
|
+
tabIndex={tabIndex}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
<img
|
|
64
|
+
className="client-sdk-button-icon"
|
|
65
|
+
src="https://www.crossmint.io/assets/crossmint/logo.png"
|
|
66
|
+
alt="Crossmint logo"
|
|
67
|
+
/>
|
|
68
|
+
{content}
|
|
69
|
+
</button>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React, { FC, ReactNode, useEffect, useState } from "react";
|
|
2
|
+
import { OnboardingRequestStatusResponse, CrossMintStatusContext } from "./useCrossMintStatus";
|
|
3
|
+
|
|
4
|
+
export interface CrossMintStatusProviderProps {
|
|
5
|
+
clientId: string;
|
|
6
|
+
hideMintOnInactiveClient: boolean;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const CrossMintStatusProvider: FC<CrossMintStatusProviderProps> = ({
|
|
11
|
+
clientId,
|
|
12
|
+
hideMintOnInactiveClient,
|
|
13
|
+
children,
|
|
14
|
+
}) => {
|
|
15
|
+
const [status, setStatus] = useState<OnboardingRequestStatusResponse>(
|
|
16
|
+
OnboardingRequestStatusResponse.WAITING_SUBMISSION
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
async function fetchClientIntegration() {
|
|
20
|
+
const res = await fetch(`https://crossmint.io/api/crossmint/onboardingRequests/${clientId}/status`);
|
|
21
|
+
|
|
22
|
+
if (res.status === 200) {
|
|
23
|
+
const resData: { clientId: string; status: OnboardingRequestStatusResponse } = await res.json();
|
|
24
|
+
|
|
25
|
+
console.log("resData", resData);
|
|
26
|
+
setStatus(resData.status);
|
|
27
|
+
} else {
|
|
28
|
+
if (status !== OnboardingRequestStatusResponse.INVALID) {
|
|
29
|
+
setStatus(OnboardingRequestStatusResponse.INVALID);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
fetchClientIntegration();
|
|
36
|
+
|
|
37
|
+
const interval = setInterval(() => {
|
|
38
|
+
fetchClientIntegration();
|
|
39
|
+
}, 60 * 1000);
|
|
40
|
+
|
|
41
|
+
return () => clearInterval(interval);
|
|
42
|
+
}, []);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<CrossMintStatusContext.Provider
|
|
46
|
+
value={{
|
|
47
|
+
status,
|
|
48
|
+
clientId,
|
|
49
|
+
hideMintOnInactiveClient,
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
</CrossMintStatusContext.Provider>
|
|
54
|
+
);
|
|
55
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -3,10 +3,12 @@ import { createContext, useContext } from "react";
|
|
|
3
3
|
export interface PopupContextState {
|
|
4
4
|
connecting: boolean;
|
|
5
5
|
connect: (
|
|
6
|
-
candyMachineId: string,
|
|
7
6
|
collectionTitle?: string,
|
|
8
7
|
collectionDescription?: string,
|
|
9
|
-
collectionPhoto?: string
|
|
8
|
+
collectionPhoto?: string,
|
|
9
|
+
mintTo?: string,
|
|
10
|
+
emailTo?: string,
|
|
11
|
+
listingId?: string
|
|
10
12
|
) => void;
|
|
11
13
|
|
|
12
14
|
popup: Window | null;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
|
|
3
|
+
export enum OnboardingRequestStatusResponse {
|
|
4
|
+
WAITING_SUBMISSION = "waiting-submission",
|
|
5
|
+
PENDING = "pending",
|
|
6
|
+
REJECTED = "rejected",
|
|
7
|
+
ACCEPTED = "accepted",
|
|
8
|
+
INVALID = "invalid",
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface CrossMintStatusContextState {
|
|
12
|
+
status: OnboardingRequestStatusResponse;
|
|
13
|
+
clientId: string;
|
|
14
|
+
hideMintOnInactiveClient: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const CrossMintStatusContext = createContext<CrossMintStatusContextState>({} as CrossMintStatusContextState);
|
|
18
|
+
|
|
19
|
+
export function useCrossMintStatus(): CrossMintStatusContextState {
|
|
20
|
+
return useContext(CrossMintStatusContext);
|
|
21
|
+
}
|