@gluwa/connect-kit 0.2.0-next.1 → 0.2.0-next.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/CHANGELOG.md +11 -0
- package/assets/creditwallet.png +0 -0
- package/assets/fonts/Inter-Medium.ttf +0 -0
- package/assets/fonts/Inter-Medium.woff2 +0 -0
- package/assets/fonts/Inter-Regular.ttf +0 -0
- package/assets/fonts/Inter-Regular.woff2 +0 -0
- package/assets/fonts/Inter-SemiBold.ttf +0 -0
- package/assets/fonts/Inter-SemiBold.woff2 +0 -0
- package/assets/graphic.png +0 -0
- package/assets/metamask.png +0 -0
- package/assets/wc-logo.svg +3 -0
- package/assets/wc-search.png +0 -0
- package/dist/chunk-EDNRW47A.js +401 -0
- package/dist/credit-connect.js +2 -409
- package/dist/index.css +1903 -390
- package/dist/index.d.ts +16 -10
- package/dist/index.js +1110 -870
- package/dist/package.json +7 -6
- package/package.json +8 -8
- package/src/ConnectKitProvider.tsx +90 -65
- package/src/assets.d.ts +5 -0
- package/src/components/actionItem/index.tsx +50 -0
- package/src/components/actionItem/style.scss +47 -0
- package/src/components/copyLink/index.tsx +16 -0
- package/src/components/copyLink/style.scss +16 -0
- package/src/components/qrArea/index.tsx +70 -0
- package/src/components/qrArea/style.scss +130 -0
- package/src/components/searchBar/asset/Search.tsx +20 -0
- package/src/components/searchBar/asset/XMarkCircle.tsx +24 -0
- package/src/components/searchBar/index.tsx +44 -0
- package/src/components/searchBar/style.scss +58 -0
- package/src/components/snackbar/index.tsx +25 -0
- package/src/components/snackbar/style.scss +51 -0
- package/src/components/toggle/index.tsx +27 -0
- package/src/components/toggle/style.scss +53 -0
- package/src/components/walletGrid/index.tsx +64 -0
- package/src/components/walletGrid/style.scss +108 -0
- package/src/components/walletItem/index.tsx +49 -0
- package/src/components/walletItem/style.scss +70 -0
- package/src/connector-meta.ts +12 -7
- package/src/core/config.ts +20 -1
- package/src/creditConnectConnector.ts +17 -25
- package/src/hooks/useWCState.ts +22 -5
- package/src/hooks/useWagmiConnect.ts +0 -1
- package/src/index.ts +2 -2
- package/src/layout/allWallets/index.tsx +52 -0
- package/src/layout/allWallets/style.scss +62 -0
- package/src/layout/connectDialog/asset/backIcon.tsx +24 -0
- package/src/layout/connectDialog/asset/checkIcon.tsx +28 -0
- package/src/layout/connectDialog/asset/closeIcon.tsx +21 -0
- package/src/layout/connectDialog/asset/copyIcon.tsx +28 -0
- package/src/layout/connectDialog/asset/linkIcon.tsx +24 -0
- package/src/layout/connectDialog/asset/spinner.tsx +21 -0
- package/src/layout/connectDialog/idle/index.tsx +32 -0
- package/src/layout/connectDialog/idle/style.scss +61 -0
- package/src/layout/connectDialog/index.tsx +286 -0
- package/src/layout/connectDialog/loading/index.tsx +13 -0
- package/src/layout/connectDialog/loading/style.scss +19 -0
- package/src/layout/connectDialog/metaMask/index.tsx +61 -0
- package/src/layout/connectDialog/metaMask/style.scss +65 -0
- package/src/layout/connectDialog/qr/index.tsx +33 -0
- package/src/layout/connectDialog/style.scss +95 -0
- package/src/layout/connectDialog/timeout/index.tsx +31 -0
- package/src/layout/connectDialog/timeout/style.scss +64 -0
- package/src/layout/connectDialog/walletConnect/index.tsx +45 -0
- package/src/layout/connectDialog/walletConnect/style.scss +48 -0
- package/src/layout/connectDialog/walletQR/index.tsx +37 -0
- package/src/layout/detailPanel/index.tsx +147 -0
- package/src/layout/detailPanel/style.scss +64 -0
- package/src/layout/selectorPanel/index.tsx +100 -0
- package/src/layout/selectorPanel/style.scss +113 -0
- package/src/style/color.scss +417 -0
- package/src/style/font.scss +28 -0
- package/src/style/index.scss +5 -0
- package/src/style/mixin.scss +217 -0
- package/src/style/reset.scss +110 -0
- package/src/style/variables.scss +13 -0
- package/src/types.ts +11 -8
- package/src/utils/platform.ts +6 -0
- package/tsup.config.ts +32 -2
- package/dist/chunk-DDA6FP6U.js +0 -7
- package/src/ConnectModal.scss +0 -665
- package/src/ConnectModal.tsx +0 -573
- package/src/components/QRFrame.tsx +0 -43
- package/src/views/CreditWalletView.tsx +0 -58
- package/src/views/IdleView.tsx +0 -10
- package/src/views/MetaMaskView.tsx +0 -66
- package/src/views/SwitchChainView.tsx +0 -72
- package/src/views/WalletConnectView.tsx +0 -206
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gluwa/connect-kit",
|
|
3
|
-
"version": "0.2.0-next.
|
|
3
|
+
"version": "0.2.0-next.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"types": "./src/credit-connect.ts",
|
|
12
12
|
"default": "./src/credit-connect.ts"
|
|
13
13
|
},
|
|
14
|
+
"./index.css": "./dist/index.css",
|
|
14
15
|
"./package.json": "./package.json"
|
|
15
16
|
},
|
|
16
17
|
"publishConfig": {
|
|
@@ -45,7 +46,11 @@
|
|
|
45
46
|
"dependencies": {
|
|
46
47
|
"qrcode.react": "^4.2.0",
|
|
47
48
|
"wagmi": "^2.15.6",
|
|
48
|
-
"@wagmi/core": "^2.16.7"
|
|
49
|
+
"@wagmi/core": "^2.16.7",
|
|
50
|
+
"@gluwa/credit-connect-sdk": "workspace:*",
|
|
51
|
+
"@gluwa/credit-connect-storage-local": "workspace:*",
|
|
52
|
+
"@gluwa/credit-connect-e2ee-tweetnacl": "workspace:*",
|
|
53
|
+
"@gluwa/credit-connect-hub-node-ws": "workspace:*"
|
|
49
54
|
},
|
|
50
55
|
"devDependencies": {
|
|
51
56
|
"@gluwa/credit-connect-sdk": "workspace:*",
|
|
@@ -62,15 +67,11 @@
|
|
|
62
67
|
"wagmi": "^2.15.6"
|
|
63
68
|
},
|
|
64
69
|
"peerDependencies": {
|
|
65
|
-
"@gluwa/credit-connect-sdk": "workspace:*",
|
|
66
70
|
"@tanstack/react-query": ">=5.0.0",
|
|
67
71
|
"react": "^18.0.0 || ^19.0.0",
|
|
68
72
|
"viem": ">=2.0.0"
|
|
69
73
|
},
|
|
70
74
|
"peerDependenciesMeta": {
|
|
71
|
-
"@gluwa/credit-connect-sdk": {
|
|
72
|
-
"optional": true
|
|
73
|
-
},
|
|
74
75
|
"@tanstack/react-query": {
|
|
75
76
|
"optional": true
|
|
76
77
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gluwa/connect-kit",
|
|
3
|
-
"version": "0.2.0-next.
|
|
3
|
+
"version": "0.2.0-next.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -25,7 +25,11 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"qrcode.react": "^4.2.0",
|
|
27
27
|
"wagmi": "^2.15.6",
|
|
28
|
-
"@wagmi/core": "^2.16.7"
|
|
28
|
+
"@wagmi/core": "^2.16.7",
|
|
29
|
+
"@gluwa/credit-connect-sdk": "0.2.0-next.3",
|
|
30
|
+
"@gluwa/credit-connect-storage-local": "0.2.0-next.3",
|
|
31
|
+
"@gluwa/credit-connect-e2ee-tweetnacl": "0.2.0-next.3",
|
|
32
|
+
"@gluwa/credit-connect-hub-node-ws": "0.1.0-next.3"
|
|
29
33
|
},
|
|
30
34
|
"devDependencies": {
|
|
31
35
|
"@tanstack/react-query": "^5.62.0",
|
|
@@ -39,18 +43,14 @@
|
|
|
39
43
|
"typescript-eslint": "^8.18.2",
|
|
40
44
|
"viem": "^2.31.7",
|
|
41
45
|
"wagmi": "^2.15.6",
|
|
42
|
-
"@gluwa/credit-connect-sdk": "0.2.0-next.
|
|
46
|
+
"@gluwa/credit-connect-sdk": "0.2.0-next.3"
|
|
43
47
|
},
|
|
44
48
|
"peerDependencies": {
|
|
45
49
|
"@tanstack/react-query": ">=5.0.0",
|
|
46
50
|
"react": "^18.0.0 || ^19.0.0",
|
|
47
|
-
"viem": ">=2.0.0"
|
|
48
|
-
"@gluwa/credit-connect-sdk": "0.2.0-next.1"
|
|
51
|
+
"viem": ">=2.0.0"
|
|
49
52
|
},
|
|
50
53
|
"peerDependenciesMeta": {
|
|
51
|
-
"@gluwa/credit-connect-sdk": {
|
|
52
|
-
"optional": true
|
|
53
|
-
},
|
|
54
54
|
"@tanstack/react-query": {
|
|
55
55
|
"optional": true
|
|
56
56
|
}
|
|
@@ -9,15 +9,20 @@ import {
|
|
|
9
9
|
type FC,
|
|
10
10
|
type ReactNode,
|
|
11
11
|
} from 'react';
|
|
12
|
-
import { WagmiProvider, useAccount, useDisconnect, useSwitchChain } from 'wagmi';
|
|
12
|
+
import { WagmiProvider, useAccount, useConfig, useDisconnect, useSwitchChain } from 'wagmi';
|
|
13
|
+
import { getAccount } from '@wagmi/core';
|
|
13
14
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
14
|
-
import { ConnectModal } from './ConnectModal';
|
|
15
|
+
// import { ConnectModal } from './ConnectModal';
|
|
16
|
+
import { ConnectDialog } from './layout/connectDialog';
|
|
15
17
|
import { getConfig, getKitConfig, initConfig } from './core/config';
|
|
18
|
+
import { resolveConnectorId } from './connector-meta';
|
|
16
19
|
import type {
|
|
17
20
|
ConnectErrorContext,
|
|
18
21
|
ConnectKitConfig,
|
|
22
|
+
ConnectKitTheme,
|
|
19
23
|
ConnectResult,
|
|
20
24
|
ConnectorId,
|
|
25
|
+
ConnectorKey,
|
|
21
26
|
Connectors,
|
|
22
27
|
} from './types';
|
|
23
28
|
|
|
@@ -28,16 +33,21 @@ export interface ConnectKitProviderProps {
|
|
|
28
33
|
kitConfig?: ConnectKitConfig;
|
|
29
34
|
connectors: Connectors;
|
|
30
35
|
requiredChainId?: number;
|
|
36
|
+
theme: ConnectKitTheme;
|
|
31
37
|
onConnect?: (result: ConnectResult) => void;
|
|
32
38
|
onLog?: (message: string, error?: Error) => void;
|
|
33
39
|
renderConnectError?: (ctx: ConnectErrorContext) => ReactNode;
|
|
34
40
|
}
|
|
35
|
-
|
|
36
41
|
export interface ConnectKitContextValue {
|
|
37
42
|
isOpen: boolean;
|
|
38
43
|
open: () => void;
|
|
39
44
|
close: () => void;
|
|
40
45
|
isConnected: boolean;
|
|
46
|
+
needsChainSwitch: boolean;
|
|
47
|
+
requiredChainId: number | undefined;
|
|
48
|
+
currentChainId: number | undefined;
|
|
49
|
+
isSwitchingChain: boolean;
|
|
50
|
+
switchToRequiredChain: () => Promise<void>;
|
|
41
51
|
address: `0x${string}` | undefined;
|
|
42
52
|
connectorId: ConnectorId | null;
|
|
43
53
|
disconnect: () => Promise<void>;
|
|
@@ -45,14 +55,16 @@ export interface ConnectKitContextValue {
|
|
|
45
55
|
|
|
46
56
|
const ConnectKitContext = createContext<ConnectKitContextValue | null>(null);
|
|
47
57
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
// 외부 API Connectors (ConnectorKey 배열) → 내부 ConnectorId[] 매핑.
|
|
59
|
+
// 입력 순서 그대로 selector 표시 순서.
|
|
60
|
+
const CONNECTOR_KEY_TO_ID: Record<ConnectorKey, ConnectorId> = {
|
|
61
|
+
creditWallet: 'CREDIT_CONNECT',
|
|
62
|
+
metamask: 'METAMASK',
|
|
63
|
+
walletConnect: 'WALLET_CONNECT',
|
|
64
|
+
};
|
|
65
|
+
const resolveConnectorsFromConfig = (connectorsConfig?: Connectors): ConnectorId[] => {
|
|
66
|
+
if (!connectorsConfig) return [];
|
|
67
|
+
return connectorsConfig.map((key) => CONNECTOR_KEY_TO_ID[key]);
|
|
56
68
|
};
|
|
57
69
|
|
|
58
70
|
export const ConnectKitProvider: FC<ConnectKitProviderProps> = (props) => {
|
|
@@ -81,14 +93,17 @@ const ConnectKitProviderInner: FC<ConnectKitProviderInnerProps> = ({
|
|
|
81
93
|
connectors,
|
|
82
94
|
kitConfig,
|
|
83
95
|
requiredChainId,
|
|
96
|
+
theme,
|
|
84
97
|
onConnect,
|
|
85
98
|
onLog,
|
|
86
|
-
renderConnectError,
|
|
87
99
|
}) => {
|
|
100
|
+
// NOTE: renderConnectError 는 ConnectDialog 가 아직 error UI customization 을 받지 않으므로
|
|
101
|
+
// destructure 에서 제외. 추후 ConnectDialog 의 timeout/error content 에 wire 필요 시 복원.
|
|
88
102
|
const [isOpen, setIsOpen] = useState(false);
|
|
89
103
|
const [pendingResult, setPendingResult] = useState<ConnectResult | null>(null);
|
|
90
104
|
|
|
91
105
|
const account = useAccount();
|
|
106
|
+
const wagmiConfig = useConfig();
|
|
92
107
|
const { disconnectAsync } = useDisconnect();
|
|
93
108
|
const { switchChainAsync } = useSwitchChain();
|
|
94
109
|
|
|
@@ -97,14 +112,6 @@ const ConnectKitProviderInner: FC<ConnectKitProviderInnerProps> = ({
|
|
|
97
112
|
onConnectRef.current = onConnect;
|
|
98
113
|
}, [onConnect]);
|
|
99
114
|
|
|
100
|
-
const chainMismatch =
|
|
101
|
-
requiredChainId != null &&
|
|
102
|
-
account.status === 'connected' &&
|
|
103
|
-
account.chainId != null &&
|
|
104
|
-
account.chainId !== requiredChainId;
|
|
105
|
-
|
|
106
|
-
const [autoSwitchFailedKey, setAutoSwitchFailedKey] = useState<string | null>(null);
|
|
107
|
-
const autoSwitchInFlightRef = useRef(false);
|
|
108
115
|
const isMountedRef = useRef(true);
|
|
109
116
|
useEffect(() => {
|
|
110
117
|
isMountedRef.current = true;
|
|
@@ -113,39 +120,15 @@ const ConnectKitProviderInner: FC<ConnectKitProviderInnerProps> = ({
|
|
|
113
120
|
};
|
|
114
121
|
}, []);
|
|
115
122
|
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
const needsChainSwitch =
|
|
124
|
+
requiredChainId != null &&
|
|
125
|
+
account.status === 'connected' &&
|
|
126
|
+
account.chainId != null &&
|
|
127
|
+
account.chainId !== requiredChainId;
|
|
120
128
|
|
|
121
|
-
|
|
122
|
-
if (!chainMismatch || requiredChainId == null) return;
|
|
123
|
-
if (autoSwitchInFlightRef.current) return;
|
|
124
|
-
if (mismatchKey != null && mismatchKey === autoSwitchFailedKey) return;
|
|
125
|
-
|
|
126
|
-
autoSwitchInFlightRef.current = true;
|
|
127
|
-
switchChainAsync({ chainId: requiredChainId })
|
|
128
|
-
.catch((err: unknown) => {
|
|
129
|
-
if (!isMountedRef.current) return;
|
|
130
|
-
const normalized = err instanceof Error ? err : new Error(String(err));
|
|
131
|
-
onLog?.(`[connect-kit] silent switch chain failed: ${normalized.message}`, normalized);
|
|
132
|
-
if (mismatchKey != null) {
|
|
133
|
-
setAutoSwitchFailedKey(mismatchKey);
|
|
134
|
-
}
|
|
135
|
-
})
|
|
136
|
-
.finally(() => {
|
|
137
|
-
autoSwitchInFlightRef.current = false;
|
|
138
|
-
});
|
|
139
|
-
}, [chainMismatch, mismatchKey, requiredChainId, autoSwitchFailedKey, switchChainAsync, onLog]);
|
|
129
|
+
const [isSwitchingChain, setIsSwitchingChain] = useState(false);
|
|
140
130
|
|
|
141
|
-
|
|
142
|
-
if (!chainMismatch && autoSwitchFailedKey != null) {
|
|
143
|
-
setAutoSwitchFailedKey(null);
|
|
144
|
-
}
|
|
145
|
-
}, [chainMismatch, autoSwitchFailedKey]);
|
|
146
|
-
|
|
147
|
-
const autoSwitchFailedForCurrent = mismatchKey != null && mismatchKey === autoSwitchFailedKey;
|
|
148
|
-
const effectiveOpen = isOpen || (chainMismatch && autoSwitchFailedForCurrent);
|
|
131
|
+
const effectiveOpen = isOpen;
|
|
149
132
|
|
|
150
133
|
const open = useCallback((): void => {
|
|
151
134
|
setIsOpen(true);
|
|
@@ -153,29 +136,62 @@ const ConnectKitProviderInner: FC<ConnectKitProviderInnerProps> = ({
|
|
|
153
136
|
|
|
154
137
|
const close = useCallback((): void => {
|
|
155
138
|
setIsOpen(false);
|
|
156
|
-
|
|
139
|
+
const status = getAccount(wagmiConfig).status;
|
|
140
|
+
if (status === 'connecting' || status === 'reconnecting') {
|
|
141
|
+
disconnectAsync().catch(() => undefined);
|
|
142
|
+
}
|
|
143
|
+
}, [wagmiConfig, disconnectAsync]);
|
|
157
144
|
|
|
158
145
|
const disconnect = useCallback(async (): Promise<void> => {
|
|
159
146
|
await disconnectAsync();
|
|
160
147
|
}, [disconnectAsync]);
|
|
161
148
|
|
|
162
|
-
const
|
|
149
|
+
const switchToRequiredChain = useCallback(async (): Promise<void> => {
|
|
150
|
+
if (requiredChainId == null) return;
|
|
151
|
+
setIsSwitchingChain(true);
|
|
152
|
+
try {
|
|
153
|
+
await switchChainAsync({ chainId: requiredChainId });
|
|
154
|
+
} finally {
|
|
155
|
+
if (isMountedRef.current) setIsSwitchingChain(false);
|
|
156
|
+
}
|
|
157
|
+
}, [requiredChainId, switchChainAsync]);
|
|
158
|
+
|
|
159
|
+
// ConnectDialog 의 wagmi connect 성공 → pendingResult set → 아래 useEffect 가
|
|
160
|
+
// account.status === 'connected' 확인 후 외부 onConnect 호출 + modal close.
|
|
161
|
+
// wagmi state 가 비동기로 'connected' 로 전환되는 race 흡수용.
|
|
162
|
+
const handleDialogConnect = useCallback((result: ConnectResult): void => {
|
|
163
163
|
setPendingResult(result);
|
|
164
164
|
}, []);
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
const handleDialogError = useCallback(
|
|
167
|
+
(error: Error, connectorId: ConnectorId): void => {
|
|
168
|
+
onLog?.(`[connect-kit] connect failed: ${connectorId} — ${error.message}`, error);
|
|
169
|
+
},
|
|
170
|
+
[onLog],
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// 연결 성공 시 modal 자동 close — wagmi state 만 기준으로.
|
|
174
|
+
// 이전 구현은 pendingResult 가 set 된 경우만 close 했는데, `setPendingResult` 는
|
|
175
|
+
// ConnectDialog 의 onConnect (`connectAsync.then`) 안에서만 호출됨. MM deeplink 같은
|
|
176
|
+
// 시나리오 (앱 이동 → 승인 → 복귀) 에서 wagmi 가 자체적으로 'connected' 로 전이하지만
|
|
177
|
+
// connectAsync 의 promise 는 resolve 안 될 수 있음 → pendingResult set 안 됨 → modal 안 닫힘.
|
|
178
|
+
// 모든 connector (WC/CC/MM) 의 connected 가 일관된 close 트리거가 되도록 단순화.
|
|
179
|
+
useEffect((): void => {
|
|
180
|
+
if (!effectiveOpen) return;
|
|
181
|
+
if (account.status !== 'connected') return;
|
|
182
|
+
setIsOpen(false);
|
|
183
|
+
}, [effectiveOpen, account.status]);
|
|
184
|
+
|
|
185
|
+
// 외부 onConnect 콜백은 best-effort — pendingResult 가 set 된 경우만 호출.
|
|
186
|
+
useEffect((): void => {
|
|
167
187
|
if (!pendingResult) return;
|
|
168
188
|
if (account.status !== 'connected') {
|
|
169
189
|
setPendingResult(null);
|
|
170
190
|
return;
|
|
171
191
|
}
|
|
172
|
-
if (requiredChainId != null && account.chainId !== requiredChainId) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
192
|
onConnectRef.current?.(pendingResult);
|
|
176
193
|
setPendingResult(null);
|
|
177
|
-
|
|
178
|
-
}, [pendingResult, account.status, account.chainId, requiredChainId]);
|
|
194
|
+
}, [pendingResult, account.status]);
|
|
179
195
|
|
|
180
196
|
const value = useMemo<ConnectKitContextValue>(
|
|
181
197
|
() => ({
|
|
@@ -183,6 +199,11 @@ const ConnectKitProviderInner: FC<ConnectKitProviderInnerProps> = ({
|
|
|
183
199
|
open,
|
|
184
200
|
close,
|
|
185
201
|
isConnected: account.status === 'connected',
|
|
202
|
+
needsChainSwitch,
|
|
203
|
+
requiredChainId,
|
|
204
|
+
currentChainId: account.chainId,
|
|
205
|
+
isSwitchingChain,
|
|
206
|
+
switchToRequiredChain,
|
|
186
207
|
address: account.address,
|
|
187
208
|
connectorId: resolveConnectorId(account.connector?.id),
|
|
188
209
|
disconnect,
|
|
@@ -192,6 +213,11 @@ const ConnectKitProviderInner: FC<ConnectKitProviderInnerProps> = ({
|
|
|
192
213
|
open,
|
|
193
214
|
close,
|
|
194
215
|
account.status,
|
|
216
|
+
needsChainSwitch,
|
|
217
|
+
requiredChainId,
|
|
218
|
+
account.chainId,
|
|
219
|
+
isSwitchingChain,
|
|
220
|
+
switchToRequiredChain,
|
|
195
221
|
account.address,
|
|
196
222
|
account.connector?.id,
|
|
197
223
|
disconnect,
|
|
@@ -201,15 +227,14 @@ const ConnectKitProviderInner: FC<ConnectKitProviderInnerProps> = ({
|
|
|
201
227
|
return (
|
|
202
228
|
<ConnectKitContext.Provider value={value}>
|
|
203
229
|
{children}
|
|
204
|
-
<
|
|
230
|
+
<ConnectDialog
|
|
205
231
|
open={effectiveOpen}
|
|
206
|
-
|
|
232
|
+
theme={theme}
|
|
233
|
+
connectors={resolveConnectorsFromConfig(connectors)}
|
|
207
234
|
wcProjectId={kitConfig.wcProjectId}
|
|
208
|
-
requiredChainId={requiredChainId}
|
|
209
|
-
renderConnectError={renderConnectError}
|
|
210
|
-
onConnect={handleModalConnect}
|
|
211
235
|
onClose={close}
|
|
212
|
-
|
|
236
|
+
onConnect={handleDialogConnect}
|
|
237
|
+
onError={handleDialogError}
|
|
213
238
|
/>
|
|
214
239
|
</ConnectKitContext.Provider>
|
|
215
240
|
);
|
package/src/assets.d.ts
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type ReactNode, type AnchorHTMLAttributes, type ButtonHTMLAttributes } from 'react';
|
|
2
|
+
import './style.scss';
|
|
3
|
+
|
|
4
|
+
interface ActionItemContent {
|
|
5
|
+
label?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
action?: string;
|
|
8
|
+
children?: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type ActionItemAsAnchor = { as: 'a' } & AnchorHTMLAttributes<HTMLAnchorElement> & ActionItemContent;
|
|
12
|
+
type ActionItemAsButton = { as: 'button' } & ButtonHTMLAttributes<HTMLButtonElement> &
|
|
13
|
+
ActionItemContent;
|
|
14
|
+
|
|
15
|
+
type ActionItemProps = ActionItemAsAnchor | ActionItemAsButton;
|
|
16
|
+
|
|
17
|
+
const ActionItemBody = ({ label, description, action, children }: ActionItemContent): ReactNode => {
|
|
18
|
+
if (children) return <>{children}</>;
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
<span className="ck-action-item-content">
|
|
22
|
+
<span className="ck-action-item-label">{label}</span>
|
|
23
|
+
{description && <span className="ck-action-item-desc">{description}</span>}
|
|
24
|
+
</span>
|
|
25
|
+
{action && <span className="ck-action-item-action">{action}</span>}
|
|
26
|
+
</>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const ActionItem = (props: ActionItemProps) => {
|
|
31
|
+
if (props.as === 'a') {
|
|
32
|
+
const { as: _, label, description, action, children, className, ...rest } = props;
|
|
33
|
+
return (
|
|
34
|
+
<a className={`ck-action-item${className ? ` ${className}` : ''}`} {...rest}>
|
|
35
|
+
<ActionItemBody label={label} description={description} action={action}>
|
|
36
|
+
{children}
|
|
37
|
+
</ActionItemBody>
|
|
38
|
+
</a>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const { as: _, label, description, action, children, className, ...rest } = props;
|
|
43
|
+
return (
|
|
44
|
+
<button className={`ck-action-item${className ? ` ${className}` : ''}`} {...rest}>
|
|
45
|
+
<ActionItemBody label={label} description={description} action={action}>
|
|
46
|
+
{children}
|
|
47
|
+
</ActionItemBody>
|
|
48
|
+
</button>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
@use '../../style/mixin.scss' as *;
|
|
2
|
+
|
|
3
|
+
.ck-root .ck-action-item {
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: 16px;
|
|
7
|
+
width: 100%;
|
|
8
|
+
padding: 16px 20px;
|
|
9
|
+
border-radius: 12px;
|
|
10
|
+
background: var(--scale-gray-100);
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
margin-top: auto;
|
|
13
|
+
flex-shrink: 0;
|
|
14
|
+
text-decoration: none;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.ck-action-item-content {
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
gap: 2px;
|
|
21
|
+
flex: 1;
|
|
22
|
+
min-width: 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.ck-action-item-label {
|
|
26
|
+
@include textToken('subtitle2-bold');
|
|
27
|
+
color: var(--scale-gray-900);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.ck-action-item-desc {
|
|
31
|
+
@include textToken('label5-regular');
|
|
32
|
+
color: var(--scale-gray-600);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.ck-action-item-action {
|
|
36
|
+
display: inline-flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
padding: 0 20px;
|
|
40
|
+
height: 44px;
|
|
41
|
+
border-radius: 6px;
|
|
42
|
+
background: var(--scale-blue2-alpha-100);
|
|
43
|
+
@include textToken('label5-bold');
|
|
44
|
+
color: var(--semantic-brand-trugi-primary);
|
|
45
|
+
white-space: nowrap;
|
|
46
|
+
flex-shrink: 0;
|
|
47
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type FC } from 'react';
|
|
2
|
+
import './style.scss';
|
|
3
|
+
import { CopyIcon } from '../../layout/connectDialog/asset/copyIcon';
|
|
4
|
+
|
|
5
|
+
interface CopyLinkProps {
|
|
6
|
+
onCopy?: () => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const CopyLink: FC<CopyLinkProps> = ({ onCopy }) => {
|
|
10
|
+
return (
|
|
11
|
+
<button type="button" className="ck-copy-link" onClick={onCopy}>
|
|
12
|
+
<CopyIcon className="ck-copy-link-icon" />
|
|
13
|
+
Copy link
|
|
14
|
+
</button>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
@use '../../style/mixin.scss' as *;
|
|
2
|
+
|
|
3
|
+
.ck-root .ck-copy-link {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
align-self: center;
|
|
7
|
+
gap: 6px;
|
|
8
|
+
@include textToken('body3-l1-regular');
|
|
9
|
+
color: var(--scale-gray-500);
|
|
10
|
+
cursor: pointer;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.ck-copy-link-icon {
|
|
14
|
+
flex-shrink: 0;
|
|
15
|
+
color: var(--scale-gray-500);
|
|
16
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type FC, type CSSProperties } from 'react';
|
|
2
|
+
import { QRCodeSVG } from 'qrcode.react';
|
|
3
|
+
import { CopyLink } from '../copyLink';
|
|
4
|
+
import './style.scss';
|
|
5
|
+
|
|
6
|
+
export type QrAreaStatus = 'loading' | 'ready' | 'timeout';
|
|
7
|
+
|
|
8
|
+
interface QrAreaProps {
|
|
9
|
+
uri?: string | null;
|
|
10
|
+
status: QrAreaStatus;
|
|
11
|
+
logoUrl?: string;
|
|
12
|
+
hasBg?: boolean;
|
|
13
|
+
label?: string;
|
|
14
|
+
onCopy?: () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const BG_COLOR = '#ffffff';
|
|
18
|
+
const FG_COLOR = '#000000';
|
|
19
|
+
const FG_GRADIENT = 'url(#ck-qr-gradient)';
|
|
20
|
+
|
|
21
|
+
export const QrArea: FC<QrAreaProps> = ({ uri, status, logoUrl, hasBg = false, label, onCopy }) => {
|
|
22
|
+
const bgColor = hasBg ? BG_COLOR : 'transparent';
|
|
23
|
+
const fgColor = hasBg ? FG_COLOR : FG_GRADIENT;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div className="ck-qr-area">
|
|
27
|
+
<div className="ck-qr-group">
|
|
28
|
+
<figure className={`ck-qr ck-qr-${status}`} aria-label="QR Code">
|
|
29
|
+
{status === 'loading' && (
|
|
30
|
+
<div className="ck-qr-skeleton" aria-busy="true" aria-label="Loading QR code" />
|
|
31
|
+
)}
|
|
32
|
+
{status === 'ready' && uri && (
|
|
33
|
+
<div
|
|
34
|
+
className="ck-qr-frame"
|
|
35
|
+
style={{ 'background': bgColor, '--ck-qr-bg': bgColor } as CSSProperties}
|
|
36
|
+
>
|
|
37
|
+
{!hasBg && (
|
|
38
|
+
<svg width="0" height="0" style={{ position: 'absolute' }} aria-hidden="true">
|
|
39
|
+
<defs>
|
|
40
|
+
<linearGradient id="ck-qr-gradient" x1="67%" y1="11%" x2="45%" y2="99%">
|
|
41
|
+
<stop offset="0%" stopColor="#7B91FF" />
|
|
42
|
+
<stop offset="100%" stopColor="#61BCFF" />
|
|
43
|
+
</linearGradient>
|
|
44
|
+
</defs>
|
|
45
|
+
</svg>
|
|
46
|
+
)}
|
|
47
|
+
<QRCodeSVG
|
|
48
|
+
value={uri}
|
|
49
|
+
size={288}
|
|
50
|
+
bgColor={bgColor}
|
|
51
|
+
fgColor={fgColor}
|
|
52
|
+
level="M"
|
|
53
|
+
marginSize={0}
|
|
54
|
+
imageSettings={
|
|
55
|
+
logoUrl ? { src: logoUrl, width: 68, height: 68, excavate: true } : undefined
|
|
56
|
+
}
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
)}
|
|
60
|
+
</figure>
|
|
61
|
+
{(label || onCopy) && (
|
|
62
|
+
<div className="ck-qr-text">
|
|
63
|
+
{label && <p className="ck-qr-label">{label}</p>}
|
|
64
|
+
{onCopy && <CopyLink onCopy={onCopy} />}
|
|
65
|
+
</div>
|
|
66
|
+
)}
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
};
|