Skip to content

Commit 23a81f3

Browse files
committed
Merge branch 'master' of https://github.com/Web3Auth/web3auth-web into feat/passwordless-login-on-modal
2 parents f39da47 + 87feb05 commit 23a81f3

File tree

8 files changed

+125
-65
lines changed

8 files changed

+125
-65
lines changed

demo/vue-app-new/vercel.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"rewrites": [
3+
{
4+
"source": "/(.*)",
5+
"destination": "/index.html"
6+
}
7+
]
8+
}

packages/modal/src/ui/components/ConnectWallet/ConnectWallet.tsx

Lines changed: 34 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type ChainNamespaceType, WALLET_CONNECTORS } from "@web3auth/no-modal";
2-
import { FormEvent, useContext, useEffect, useMemo, useState } from "react";
2+
import { FormEvent, useContext, useMemo, useState } from "react";
33

44
import { CONNECT_WALLET_PAGES } from "../../constants";
55
import { RootContext } from "../../context/RootContext";
@@ -11,8 +11,6 @@ import ConnectWalletList from "./ConnectWalletList";
1111
import ConnectWalletQrCode from "./ConnectWalletQrCode";
1212
import ConnectWalletSearch from "./ConnectWalletSearch";
1313

14-
const WALLET_LIMIT_COUNT = 10;
15-
1614
function ConnectWallet(props: ConnectWalletProps) {
1715
const {
1816
isDark,
@@ -22,7 +20,6 @@ function ConnectWallet(props: ConnectWalletProps) {
2220
walletConnectUri,
2321
walletRegistry,
2422
allExternalButtons,
25-
totalExternalWallets,
2623
customAdapterButtons,
2724
adapterVisibilityMap,
2825
deviceDetails,
@@ -35,13 +32,11 @@ function ConnectWallet(props: ConnectWalletProps) {
3532

3633
const [currentPage, setCurrentPage] = useState(CONNECT_WALLET_PAGES.CONNECT_WALLET);
3734
const [selectedWallet, setSelectedWallet] = useState(false);
38-
const [externalButtons, setExternalButtons] = useState<ExternalButton[]>([]);
39-
const [totalExternalWalletsCount, setTotalExternalWalletsCount] = useState<number>(0);
35+
const [isLoading] = useState<boolean>(false);
4036
const [selectedButton, setSelectedButton] = useState<ExternalButton>(null);
4137
const [walletSearch, setWalletSearch] = useState<string>("");
42-
const [isLoading, setIsLoading] = useState<boolean>(true);
4338
const [selectedChain, setSelectedChain] = useState<string>("all");
44-
const [initialWalletCount, setInitialWalletCount] = useState<number>(0);
39+
const [isShowAllWallets, setIsShowAllWallets] = useState<boolean>(false);
4540

4641
const handleBack = () => {
4742
if (!selectedWallet && currentPage === CONNECT_WALLET_PAGES.CONNECT_WALLET && onBackClick) {
@@ -69,13 +64,9 @@ function ConnectWallet(props: ConnectWalletProps) {
6964
});
7065
}, [allExternalButtons, customAdapterButtons]);
7166

72-
const filteredButtons = (searchValue: string) => {
73-
return allUniqueButtons.filter((button) => button.name.toLowerCase().includes(searchValue.toLowerCase()));
74-
};
75-
7667
const defaultButtonKeys = useMemo(() => new Set(Object.keys(walletRegistry.default)), [walletRegistry]);
7768

78-
const sortedButtons = useMemo(() => {
69+
const defaultButtons = useMemo(() => {
7970
// display order: default injected buttons > custom adapter buttons > default non-injected buttons
8071
const buttons = [
8172
...allExternalButtons.filter((button) => button.hasInjectedWallet && defaultButtonKeys.has(button.name)),
@@ -91,7 +82,7 @@ function ConnectWallet(props: ConnectWalletProps) {
9182
});
9283
}, [allExternalButtons, customAdapterButtons, defaultButtonKeys]);
9384

94-
const visibleButtons = useMemo(() => {
85+
const installedWalletButtons = useMemo(() => {
9586
const visibilityMap = adapterVisibilityMap;
9687
return Object.keys(config).reduce((acc, adapter) => {
9788
if (![WALLET_CONNECTORS.WALLET_CONNECT_V2].includes(adapter) && visibilityMap[adapter]) {
@@ -110,27 +101,38 @@ function ConnectWallet(props: ConnectWalletProps) {
110101
const handleWalletSearch = (e: FormEvent<HTMLInputElement>) => {
111102
const searchValue = (e.target as HTMLInputElement).value;
112103
setWalletSearch(searchValue);
113-
if (searchValue) {
114-
setExternalButtons(filteredButtons(searchValue));
115-
} else {
116-
setExternalButtons(sortedButtons);
117-
}
118-
setInitialWalletCount(sortedButtons.length);
119104
};
120105

121-
useEffect(() => {
106+
const handleChainFilterChange = (chain: string) => {
107+
setSelectedChain(chain);
108+
setIsShowAllWallets(false);
109+
};
110+
111+
const filteredButtons = useMemo(() => {
122112
if (walletDiscoverySupported) {
123-
setExternalButtons(sortedButtons);
124-
setInitialWalletCount(sortedButtons.length);
125-
setTotalExternalWalletsCount(totalExternalWallets);
126-
} else {
127-
setExternalButtons(visibleButtons);
128-
setTotalExternalWalletsCount(visibleButtons.length);
113+
const buttons = allUniqueButtons;
114+
return buttons
115+
.filter((button) => selectedChain === "all" || button.chainNamespaces.includes(selectedChain as ChainNamespaceType))
116+
.filter((button) => button.name.toLowerCase().includes(walletSearch.toLowerCase()));
129117
}
130-
setTimeout(() => {
131-
setIsLoading(false);
132-
}, 0);
133-
}, [walletDiscoverySupported, sortedButtons, visibleButtons, totalExternalWallets]);
118+
return installedWalletButtons;
119+
}, [walletDiscoverySupported, installedWalletButtons, walletSearch, allUniqueButtons, selectedChain]);
120+
121+
const externalButtons = useMemo(() => {
122+
if (walletDiscoverySupported && !walletSearch && !isShowAllWallets) {
123+
return defaultButtons;
124+
}
125+
return filteredButtons;
126+
}, [walletDiscoverySupported, walletSearch, filteredButtons, defaultButtons, isShowAllWallets]);
127+
128+
const totalExternalWalletsCount = useMemo(() => {
129+
return filteredButtons.length;
130+
}, [filteredButtons]);
131+
132+
const initialWalletCount = useMemo(() => {
133+
if (isShowAllWallets) return totalExternalWalletsCount;
134+
return walletDiscoverySupported ? defaultButtons.length : installedWalletButtons.length;
135+
}, [walletDiscoverySupported, defaultButtons, installedWalletButtons, isShowAllWallets, totalExternalWalletsCount]);
134136

135137
const handleWalletClick = (button: ExternalButton) => {
136138
const isInjectedConnectorAndSingleChainNamespace = button.hasInjectedWallet && button.chainNamespaces?.length === 1;
@@ -155,24 +157,7 @@ function ConnectWallet(props: ConnectWalletProps) {
155157
};
156158

157159
const handleMoreWallets = () => {
158-
// setIsLoading(true);
159-
setInitialWalletCount((prev) => prev + 10);
160-
const buttons = allUniqueButtons.slice(initialWalletCount, initialWalletCount + WALLET_LIMIT_COUNT);
161-
setExternalButtons((prev) => [...prev, ...buttons]);
162-
setInitialWalletCount((prev) => prev + WALLET_LIMIT_COUNT);
163-
};
164-
165-
const handleChainFilterChange = (chain: string) => {
166-
setInitialWalletCount(0);
167-
setSelectedChain(chain);
168-
if (chain === "all") {
169-
setExternalButtons(sortedButtons.slice(0, WALLET_LIMIT_COUNT));
170-
setTotalExternalWalletsCount(sortedButtons.length);
171-
} else {
172-
const filteredButtons = sortedButtons.filter((button) => button.chainNamespaces.includes(chain as ChainNamespaceType));
173-
setExternalButtons(filteredButtons.slice(0, WALLET_LIMIT_COUNT));
174-
setTotalExternalWalletsCount(filteredButtons.length);
175-
}
160+
setIsShowAllWallets(true);
176161
};
177162

178163
return (

packages/modal/src/ui/components/ConnectWallet/ConnectWallet.type.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ export interface ConnectWalletProps {
88
walletConnectUri: string | undefined;
99
walletRegistry?: WalletRegistry;
1010
allExternalButtons: ExternalButton[];
11-
totalExternalWallets: number;
1211
customAdapterButtons: ExternalButton[];
1312
adapterVisibilityMap: Record<string, boolean>;
1413
deviceDetails: { platform: platform; browser: browser; os: os };
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { useMemo, useState } from "react";
2+
3+
import { cn } from "../../utils";
4+
import { LoginHintProps } from "./LoginHint.type";
5+
6+
const LoginHint = ({ children, content, isDark = false, hideHint = false }: LoginHintProps) => {
7+
const [showPopover, setShowPopover] = useState(false);
8+
9+
const handleMouseEnter = () => {
10+
setShowPopover(true);
11+
};
12+
13+
const handleMouseLeave = () => {
14+
setShowPopover(false);
15+
};
16+
17+
const triangleStyle = useMemo(() => {
18+
const triangleSize = "8px"; // Customize the size of the triangle
19+
const triangleColor = isDark ? "#ffffff" : "#1f2a37"; // Customize the color of the triangle
20+
return {
21+
borderTop: `${triangleSize} solid transparent`,
22+
borderRight: "none",
23+
borderBottom: `${triangleSize} solid transparent`,
24+
borderLeft: `${triangleSize} solid ${triangleColor}`,
25+
left: "0%",
26+
top: `calc(100% - ${triangleSize})`,
27+
};
28+
}, [isDark]);
29+
30+
return (
31+
<div
32+
className="w3a--relative"
33+
aria-hidden
34+
onMouseEnter={handleMouseEnter}
35+
onMouseLeave={handleMouseLeave}
36+
onFocus={handleMouseEnter}
37+
onBlur={handleMouseLeave}
38+
onClick={handleMouseLeave}
39+
>
40+
{children}
41+
{showPopover && !hideHint && (
42+
<div
43+
data-popover
44+
role="tooltip"
45+
className={cn(
46+
"w3a--absolute w3a--z-[45] w3a--shadow-2xl w3a--rounded-lg w3a--bottom-[100%] w3a--left-[50%] w3a--w-max w3a--text-xs w3a--px-[6px] w3a--py-[3px]",
47+
isDark ? "w3a--bg-app-white w3a--text-app-gray-900" : "w3a--bg-app-gray-800 w3a--text-app-gray-100"
48+
)}
49+
>
50+
{content}
51+
<div className="w3a--absolute" style={triangleStyle}></div>
52+
</div>
53+
)}
54+
</div>
55+
);
56+
};
57+
58+
export default LoginHint;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export interface LoginHintProps {
2+
children: React.ReactNode;
3+
content: string;
4+
isDark?: boolean;
5+
hideHint?: boolean;
6+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default } from "./LoginHint";
2+
export type { LoginHintProps } from "./LoginHint.type";

packages/modal/src/ui/components/Root/Root.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,6 @@ function Root(props: RootProps) {
451451
walletConnectUri={modalState.walletConnectUri}
452452
config={modalState.externalWalletsConfig}
453453
walletRegistry={walletRegistry}
454-
totalExternalWallets={totalExternalWalletsLength}
455454
allExternalButtons={allButtons}
456455
adapterVisibilityMap={adapterVisibilityMap}
457456
customAdapterButtons={customAdapterButtons}

packages/modal/src/ui/components/SocialLoginList/SocialLoginList.tsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { AUTH_CONNECTION } from "@web3auth/auth";
22

33
import { cn, getIcons } from "../../utils";
44
import Button, { BUTTON_TYPE } from "../Button";
5+
import LoginHint from "../LoginHint";
56
import { SocialLoginListProps } from "./SocialLoginList.type";
67

78
function getProviderIcon(method: string, isDark: boolean, extension: string) {
@@ -62,20 +63,22 @@ function SocialLoginList(props: SocialLoginListProps) {
6263
{rowsToShow
6364
.filter((_, index) => (rowsToShow.length === 4 ? index <= 3 : index < 3))
6465
.map((row) => (
65-
<Button
66-
type={BUTTON_TYPE.SOCIAL}
67-
key={row.method}
68-
props={{
69-
showText: false,
70-
method: row.method,
71-
isDark,
72-
isPrimaryBtn: false,
73-
btnStyle: "w3a--flex w3a--items-center !w3a--justify-center w3a--w-full w3a--h-full w3a-arrow w3a-img-login-group",
74-
children: <>{getProviderIcon(row.method, isDark, ".svg")}</>,
75-
onClick: () => handleSocialLoginClick({ connector: row.connector, loginParams: row.loginParams }),
76-
buttonRadius,
77-
}}
78-
/>
66+
<LoginHint key={row.method} content={"Last Login"} isDark={isDark} hideHint={true}>
67+
<Button
68+
type={BUTTON_TYPE.SOCIAL}
69+
key={row.method}
70+
props={{
71+
showText: false,
72+
method: row.method,
73+
isDark,
74+
isPrimaryBtn: false,
75+
btnStyle: "w3a--flex w3a--items-center !w3a--justify-center w3a--w-full w3a--h-full w3a-arrow w3a-img-login-group",
76+
children: <>{getProviderIcon(row.method, isDark, ".svg")}</>,
77+
onClick: () => handleSocialLoginClick({ connector: row.connector, loginParams: row.loginParams }),
78+
buttonRadius,
79+
}}
80+
/>
81+
</LoginHint>
7982
))}
8083
{canShowMore && rowsToShow.length > 4 && (
8184
<Button

0 commit comments

Comments
 (0)