@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 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-alpha.1",
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 '{\"type\":\"commonjs\"}' | npx json > lib/cjs/package.json && echo '{\"type\":\"module\"} ' | npx json > lib/esm/package.json"
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": "358bee40dee1bfa54abf61050860d152947e32c5"
43
+ "gitHead": "44f9b3ec082a62a7001d9c9195c8848b62e2b9a1"
44
44
  }
@@ -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(candyMachineId, collectionTitle, collectionDescription, collectionPhoto);
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
- development ? DEV_URL : PROD_URL
29
- }/checkout/mint?candyMachineId=${candyMachineId}&closeOnSuccess=false${
30
- collectionTitle ? `&collectionTitle=${collectionTitle}` : ""
31
- }${collectionDescription ? `&collectionDescription=${collectionDescription}` : ""}${
32
- collectionPhoto ? `&collectionPhoto=${collectionPhoto}` : ""
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(candyMachineId, collectionTitle, collectionDescription, collectionPhoto);
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> = ({ development = false, children, ...props }) => {
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
- <CrossMintModalContext.Provider
17
- value={{
18
- visible,
19
- setVisible,
20
- }}
21
- >
22
- <CrossMintPopupProvider development={development}>
23
- {children}
24
- {visible && <CrossMintModal {...props} />}
25
- </CrossMintPopupProvider>
26
- </CrossMintModalContext.Provider>
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,3 +3,5 @@ export * from "./CrossMintModal";
3
3
  export * from "./useCrossMintModal";
4
4
  export * from "./useCrossMintPopup";
5
5
  export * from "./CrossMintProvider";
6
+ export * from "./useCrossMintStatus";
7
+ export * from "./CrossMintStatusButton";
@@ -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
+ }