-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from vechainfoundation/carpini/isolate-component
feat: isolate button component
- Loading branch information
Showing
15 changed files
with
459 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
161 changes: 161 additions & 0 deletions
161
packages/react-wallet-kit/src/ConnectWalletButton/Components/ConnectWalletModal.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import { | ||
Alert, | ||
AlertIcon, | ||
Box, | ||
Button, | ||
Flex, | ||
HStack, | ||
Icon, | ||
Spinner, | ||
Text, | ||
VStack, | ||
} from '@chakra-ui/react'; | ||
import { LinkIcon, WalletIcon } from '@heroicons/react/24/solid'; | ||
import React, { useCallback, useState } from 'react'; | ||
import { Certificate } from 'thor-devkit'; | ||
import { useConnex, useWallet } from '../../ConnexProvider'; | ||
import { Dialog } from './Dialog'; | ||
import { WalletSourceRadio } from './WalletSourceRadio'; | ||
|
||
interface ConnectedWalletDialogProps { | ||
isOpen: boolean; | ||
onClose: () => void; | ||
} | ||
|
||
export const ConnectWalletModal: React.FC<ConnectedWalletDialogProps> = ({ | ||
isOpen, | ||
onClose, | ||
}) => { | ||
const header = ( | ||
<HStack spacing={2}> | ||
<Icon as={WalletIcon} /> | ||
<Text>Connect Wallet</Text> | ||
</HStack> | ||
); | ||
|
||
return ( | ||
<Dialog | ||
body={<ConnectedWalletBody onClose={onClose} />} | ||
header={header} | ||
isOpen={isOpen} | ||
onClose={onClose} | ||
/> | ||
); | ||
}; | ||
|
||
interface ConnectedWalletBodyProps { | ||
onClose: () => void; | ||
} | ||
|
||
const ConnectedWalletBody: React.FC<ConnectedWalletBodyProps> = ({ | ||
onClose, | ||
}) => { | ||
const { setAccount } = useWallet(); | ||
const { vendor } = useConnex(); | ||
|
||
const [connectionLoading, setConnectionLoading] = useState(false); | ||
const [connectionError, setConnectionError] = useState(''); | ||
|
||
const connectToWalletHandler = | ||
useCallback(async (): Promise<Certificate> => { | ||
const message: Connex.Vendor.CertMessage = { | ||
purpose: 'identification', | ||
payload: { | ||
type: 'text', | ||
content: 'Sign a certificate to prove your identity', | ||
}, | ||
}; | ||
|
||
if (!vendor) throw new Error('Vendor not available'); | ||
|
||
const certResponse = await vendor.sign('cert', message).request(); | ||
|
||
const cert: Certificate = { | ||
purpose: message.purpose, | ||
payload: message.payload, | ||
domain: certResponse.annex.domain, | ||
timestamp: certResponse.annex.timestamp, | ||
signer: certResponse.annex.signer, | ||
signature: certResponse.signature, | ||
}; | ||
|
||
Certificate.verify(cert); | ||
|
||
return cert; | ||
}, [vendor]); | ||
|
||
const onSuccessfullConnection = useCallback( | ||
(cert: Certificate): void => { | ||
setAccount(cert.signer); | ||
onClose(); | ||
}, | ||
[setAccount, onClose], | ||
); | ||
|
||
const connectHandler = useCallback(async () => { | ||
try { | ||
setConnectionError(''); | ||
setConnectionLoading(true); | ||
|
||
const cert = await connectToWalletHandler(); | ||
|
||
onSuccessfullConnection(cert); | ||
} catch (e) { | ||
if (e instanceof Error) { | ||
setConnectionError(e.message); | ||
} else { | ||
setConnectionError('Failed to connect to wallet'); | ||
} | ||
} finally { | ||
setConnectionLoading(false); | ||
} | ||
}, [ | ||
onSuccessfullConnection, | ||
setConnectionError, | ||
setConnectionLoading, | ||
connectToWalletHandler, | ||
]); | ||
|
||
const connect = useCallback(() => { | ||
connectHandler().catch((e) => { | ||
throw e; | ||
}); | ||
}, [connectHandler]); | ||
|
||
return ( | ||
<> | ||
<Flex direction="column" gap={8}> | ||
<Box> | ||
<Text mb="8px">Wallet</Text> | ||
<WalletSourceRadio /> | ||
</Box> | ||
</Flex> | ||
<VStack mt={8} spacing={4} w="full"> | ||
{connectionLoading ? ( | ||
<Alert status="warning"> | ||
<AlertIcon /> | ||
Waiting for wallet approval... | ||
</Alert> | ||
) : null} | ||
{connectionError ? ( | ||
<Alert status="error"> | ||
<AlertIcon /> | ||
{connectionError} | ||
</Alert> | ||
) : null} | ||
|
||
<Button | ||
colorScheme="blue" | ||
disabled={connectionLoading} | ||
leftIcon={ | ||
connectionLoading ? <Spinner /> : <Icon as={LinkIcon} /> | ||
} | ||
onClick={connect} | ||
w="full" | ||
> | ||
{connectionLoading ? 'Connecting...' : 'Connect'} | ||
</Button> | ||
</VStack> | ||
</> | ||
); | ||
}; |
49 changes: 49 additions & 0 deletions
49
packages/react-wallet-kit/src/ConnectWalletButton/Components/Dialog.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import type { HTMLChakraProps } from '@chakra-ui/react'; | ||
import { | ||
Modal, | ||
ModalBody, | ||
ModalCloseButton, | ||
ModalContent, | ||
ModalFooter, | ||
ModalHeader, | ||
ModalOverlay, | ||
} from '@chakra-ui/react'; | ||
import React from 'react'; | ||
|
||
interface DialogProps { | ||
isOpen: boolean; | ||
onClose: () => void; | ||
header?: React.ReactNode; | ||
headerStyle?: HTMLChakraProps<'header'>; | ||
body?: React.ReactNode; | ||
footer?: React.ReactNode; | ||
showCloseButton?: boolean; | ||
closeButtonStyle?: HTMLChakraProps<'button'>; | ||
} | ||
|
||
export const Dialog: React.FC<DialogProps> = ({ | ||
isOpen, | ||
onClose, | ||
header, | ||
headerStyle = {}, | ||
body, | ||
footer, | ||
showCloseButton = true, | ||
closeButtonStyle = {}, | ||
}) => { | ||
return ( | ||
<Modal isOpen={isOpen} onClose={onClose} trapFocus={false}> | ||
<ModalOverlay /> | ||
<ModalContent> | ||
{header ? ( | ||
<ModalHeader {...headerStyle}>{header}</ModalHeader> | ||
) : null} | ||
{showCloseButton ? ( | ||
<ModalCloseButton {...closeButtonStyle} /> | ||
) : null} | ||
{body ? <ModalBody>{body}</ModalBody> : null} | ||
{footer ? <ModalFooter>{footer}</ModalFooter> : null} | ||
</ModalContent> | ||
</Modal> | ||
); | ||
}; |
66 changes: 66 additions & 0 deletions
66
packages/react-wallet-kit/src/ConnectWalletButton/Components/RadioCard.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import type { HTMLChakraProps } from '@chakra-ui/react'; | ||
import { Box, Button, Flex, HStack } from '@chakra-ui/react'; | ||
import React from 'react'; | ||
|
||
interface RadioCardProps extends HTMLChakraProps<'button'> { | ||
children: React.ReactNode; | ||
selected: boolean; | ||
onClick: () => void; | ||
} | ||
|
||
export const RadioCard: React.FC<RadioCardProps> = ({ | ||
children, | ||
selected, | ||
onClick, | ||
...props | ||
}) => { | ||
return ( | ||
<Button | ||
shadow={selected ? 'outline' : 'none'} | ||
variant="outline" | ||
w="full" | ||
{...props} | ||
> | ||
<HStack | ||
justify="space-between" | ||
onClick={onClick} | ||
spacing={2} | ||
w="full" | ||
> | ||
{children} | ||
<RadioCircle filled={selected} /> | ||
</HStack> | ||
</Button> | ||
); | ||
}; | ||
|
||
interface RadioCircleProps extends HTMLChakraProps<'div'> { | ||
filled?: boolean; | ||
} | ||
|
||
const RadioCircle: React.FC<RadioCircleProps> = ({ | ||
filled = false, | ||
...props | ||
}) => { | ||
return ( | ||
<Flex | ||
align="center" | ||
border="1px solid" | ||
borderColor="lightgray" | ||
justify="center" | ||
p={1} | ||
rounded="full" | ||
{...props} | ||
> | ||
<Box | ||
bg={filled ? 'blue.500' : 'transparent'} | ||
display="block" | ||
h={2.5} | ||
margin="auto" | ||
minW={2.5} | ||
rounded="full" | ||
w={2.5} | ||
/> | ||
</Flex> | ||
); | ||
}; |
Oops, something went wrong.