chore: solve merge conflicts
This commit is contained in:
commit
9f838dc62d
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
|
@ -58,12 +58,19 @@ const Secondary = styled(DefaultButton)`
|
|||
}
|
||||
`;
|
||||
|
||||
const Icon = styled.img`
|
||||
height: 9px;
|
||||
width: 12px;
|
||||
margin-right: 10px;
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
label: string,
|
||||
onClick?: () => void,
|
||||
to?: ?string,
|
||||
variant?: 'primary' | 'secondary',
|
||||
disabled?: boolean,
|
||||
icon?: string,
|
||||
className?: string,
|
||||
isLoading?: boolean,
|
||||
};
|
||||
|
@ -74,25 +81,41 @@ export const Button = ({
|
|||
to,
|
||||
variant,
|
||||
disabled,
|
||||
icon,
|
||||
className,
|
||||
isLoading,
|
||||
}: Props) => {
|
||||
if (to && onClick) throw new Error('Should define either "to" or "onClick"');
|
||||
|
||||
const props = { onClick, disabled: disabled || isLoading, className };
|
||||
const props = {
|
||||
onClick, disabled: disabled || isLoading, icon: null, className,
|
||||
};
|
||||
const buttonLabel = isLoading ? 'Loading...' : label;
|
||||
|
||||
const component = variant === 'primary' ? (
|
||||
<Primary {...props}>{buttonLabel}</Primary>
|
||||
<Primary {...props}>
|
||||
{icon
|
||||
? <Icon src={icon} />
|
||||
: null
|
||||
}
|
||||
{buttonLabel}
|
||||
</Primary>
|
||||
) : (
|
||||
<Secondary {...props}>{buttonLabel}</Secondary>
|
||||
<Secondary {...props}>
|
||||
{icon
|
||||
? <Icon src={icon} />
|
||||
: null
|
||||
}
|
||||
{buttonLabel}
|
||||
</Secondary>
|
||||
);
|
||||
|
||||
return to ? <Link to={String(to)}>{component}</Link> : component;
|
||||
};
|
||||
|
||||
Button.defaultProps = {
|
||||
to: null,
|
||||
to: '',
|
||||
icon: null,
|
||||
variant: 'primary',
|
||||
onClick: null,
|
||||
disabled: false,
|
||||
|
|
|
@ -9,6 +9,8 @@ import ClickOutside from 'react-click-outside';
|
|||
|
||||
import { TextComponent } from './text';
|
||||
|
||||
import truncateAddress from '../utils/truncateAddress';
|
||||
|
||||
/* eslint-disable max-len */
|
||||
const MenuWrapper = styled.div`
|
||||
background-image: ${props => `linear-gradient(to right, ${darken(
|
||||
|
@ -18,6 +20,7 @@ const MenuWrapper = styled.div`
|
|||
border-radius: ${props => props.theme.boxBorderRadius};
|
||||
margin-left: -10px;
|
||||
max-width: 400px;
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
const MenuItem = styled.button`
|
||||
|
@ -30,6 +33,7 @@ const MenuItem = styled.button`
|
|||
padding: 15px;
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
|
||||
|
@ -50,6 +54,18 @@ const MenuItem = styled.button`
|
|||
}
|
||||
`;
|
||||
|
||||
const OptionItem = styled(MenuItem)`
|
||||
&:hover {
|
||||
background-color: #F9D114;
|
||||
}
|
||||
`;
|
||||
|
||||
const Option = styled(TextComponent)`
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
const PopoverWithStyle = styled(Popover)`
|
||||
& > .Popover-tip {
|
||||
fill: ${props => props.theme.colors.activeItem};
|
||||
|
@ -60,6 +76,7 @@ type Props = {
|
|||
renderTrigger: (toggleVisibility: () => void, isOpen: boolean) => Node,
|
||||
options: Array<{ label: string, onClick: () => void }>,
|
||||
label?: string | null,
|
||||
truncate?: boolean,
|
||||
};
|
||||
|
||||
type State = {
|
||||
|
@ -73,11 +90,14 @@ export class DropdownComponent extends Component<Props, State> {
|
|||
|
||||
static defaultProps = {
|
||||
label: null,
|
||||
truncate: false,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { isOpen } = this.state;
|
||||
const { label, options, renderTrigger } = this.props;
|
||||
const {
|
||||
label, options, truncate, renderTrigger,
|
||||
} = this.props;
|
||||
|
||||
const body = [
|
||||
<ClickOutside
|
||||
|
@ -90,9 +110,9 @@ export class DropdownComponent extends Component<Props, State> {
|
|||
</MenuItem>
|
||||
)}
|
||||
{options.map(({ label: optionLabel, onClick }) => (
|
||||
<MenuItem onClick={onClick} key={optionLabel}>
|
||||
<TextComponent value={optionLabel} />
|
||||
</MenuItem>
|
||||
<OptionItem onClick={onClick} key={optionLabel}>
|
||||
<Option value={truncate ? truncateAddress(optionLabel) : optionLabel} />
|
||||
</OptionItem>
|
||||
))}
|
||||
</MenuWrapper>
|
||||
</ClickOutside>,
|
||||
|
|
|
@ -6,6 +6,8 @@ import styled from 'styled-components';
|
|||
import { ZcashLogo } from './zcash-logo';
|
||||
import { TextComponent } from './text';
|
||||
import { Divider } from './divider';
|
||||
import { RowComponent } from './row';
|
||||
import { StatusPill } from './status-pill';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
height: ${props => props.theme.headerHeight};
|
||||
|
@ -38,6 +40,12 @@ const TitleWrapper = styled.div`
|
|||
padding-right: ${props => props.theme.layoutPaddingRight};
|
||||
`;
|
||||
|
||||
const TitleRow = styled(RowComponent)`
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const Title = styled(TextComponent)`
|
||||
font-size: ${props => `${props.theme.fontSize.large}em`};
|
||||
margin-top: 10px;
|
||||
|
@ -57,7 +65,10 @@ export const HeaderComponent = ({ title }: Props) => (
|
|||
<ZcashLogo />
|
||||
</LogoWrapper>
|
||||
<TitleWrapper>
|
||||
<Title value={title} />
|
||||
<TitleRow alignItems='center' justifyContent='space-around'>
|
||||
<Title value={title} />
|
||||
<StatusPill />
|
||||
</TitleRow>
|
||||
<Divider opacity={0.1} />
|
||||
</TitleWrapper>
|
||||
</Wrapper>
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
import styled, { keyframes } from 'styled-components';
|
||||
import eres from 'eres';
|
||||
|
||||
import { TextComponent } from './text';
|
||||
|
||||
import rpc from '../../services/api';
|
||||
|
||||
import readyIcon from '../assets/images/green_check.png';
|
||||
import syncIcon from '../assets/images/sync_icon.png';
|
||||
import errorIcon from '../assets/images/error_icon.png';
|
||||
|
||||
const rotate = keyframes`
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
`;
|
||||
|
||||
const Wrapper = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
background-color: #000;
|
||||
border-radius: 27px;
|
||||
padding: 7px 13px;
|
||||
`;
|
||||
|
||||
const Icon = styled.img`
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 8px;
|
||||
animation: 2s linear infinite;
|
||||
animation-name: ${props => (props.animated ? rotate : 'none')};
|
||||
`;
|
||||
|
||||
const StatusPillLabel = styled(TextComponent)`
|
||||
color: ${props => props.theme.colors.statusPillLabel};
|
||||
font-weight: ${props => props.theme.fontWeight.bold};
|
||||
text-transform: uppercase;
|
||||
`;
|
||||
|
||||
type Props = {};
|
||||
|
||||
type State = {
|
||||
type: string,
|
||||
icon: string,
|
||||
progress: number,
|
||||
isSynching: boolean,
|
||||
};
|
||||
|
||||
export class StatusPill extends Component<Props, State> {
|
||||
timer: ?IntervalID = null;
|
||||
|
||||
state = {
|
||||
type: 'synching',
|
||||
icon: syncIcon,
|
||||
progress: 0,
|
||||
isSynching: true,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.timer = setInterval(() => {
|
||||
this.getBlockchainStatus();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer);
|
||||
this.timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
getBlockchainStatus = async () => {
|
||||
const [blockchainErr, blockchaininfo] = await eres(
|
||||
rpc.getblockchaininfo(),
|
||||
);
|
||||
|
||||
const newProgress = blockchaininfo.verificationprogress * 100;
|
||||
|
||||
this.setState({
|
||||
progress: newProgress,
|
||||
...(newProgress > 99.99 ? {
|
||||
type: 'ready',
|
||||
icon: readyIcon,
|
||||
isSynching: false,
|
||||
} : {}),
|
||||
});
|
||||
|
||||
if (blockchainErr) {
|
||||
this.setState(() => ({ type: 'error', icon: errorIcon }));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
type, icon, progress, isSynching,
|
||||
} = this.state;
|
||||
const showPercent = isSynching ? `(${progress.toFixed(2)}%)` : '';
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Icon src={icon} animated={isSynching} />
|
||||
<StatusPillLabel value={`${type} ${showPercent}`} />
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
name: StatusPill
|
||||
---
|
||||
|
||||
import { Playground, PropsTable } from 'docz'
|
||||
|
||||
import { StatusPill } from './status-pill.js'
|
||||
import { DoczWrapper } from '../theme.js'
|
||||
|
||||
# StatusPill
|
||||
|
||||
## Properties
|
||||
|
||||
<PropsTable of={StatusPill} />
|
||||
|
||||
## Basic Usage
|
||||
|
||||
<Playground>
|
||||
<DoczWrapper>
|
||||
{() => <StatusPill percent={83.} />}
|
||||
</DoczWrapper>
|
||||
</Playground>
|
|
@ -0,0 +1,103 @@
|
|||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { ColumnComponent } from './column';
|
||||
import { Button } from './button';
|
||||
import { QRCode } from './qrcode';
|
||||
|
||||
import truncateAddress from '../utils/truncateAddress';
|
||||
|
||||
import eyeIcon from '../assets/images/eye.png';
|
||||
|
||||
const AddressWrapper = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
background-color: #000;
|
||||
border-radius: 6px;
|
||||
padding: 7px 13px;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const Input = styled.input`
|
||||
border-radius: ${props => props.theme.boxBorderRadius};
|
||||
border: none;
|
||||
background-color: ${props => props.theme.colors.inputBackground};
|
||||
color: ${props => props.theme.colors.text};
|
||||
padding: 15px;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
font-family: ${props => props.theme.fontFamily};
|
||||
|
||||
::placeholder {
|
||||
opacity: 0.5;
|
||||
}
|
||||
`;
|
||||
|
||||
const QRCodeWrapper = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
background-color: #000;
|
||||
border-radius: 6px;
|
||||
padding: 20px;
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
address: string,
|
||||
};
|
||||
|
||||
type State = {
|
||||
isVisible: boolean,
|
||||
};
|
||||
|
||||
export class WalletAddress extends Component<Props, State> {
|
||||
state = {
|
||||
isVisible: false,
|
||||
};
|
||||
|
||||
show = () => {
|
||||
this.setState(
|
||||
() => ({ isVisible: true }),
|
||||
);
|
||||
};
|
||||
|
||||
hide = () => {
|
||||
this.setState(
|
||||
() => ({ isVisible: false }),
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
render() {
|
||||
const { address } = this.props;
|
||||
const { isVisible } = this.state;
|
||||
const toggleVisibility = isVisible ? this.hide : this.show;
|
||||
|
||||
return (
|
||||
<ColumnComponent width='100%'>
|
||||
<AddressWrapper>
|
||||
<Input
|
||||
value={isVisible ? address : truncateAddress(address)}
|
||||
onChange={() => {}}
|
||||
onFocus={event => event.currentTarget.select()}
|
||||
/>
|
||||
<Button
|
||||
icon={eyeIcon}
|
||||
label={`${isVisible ? 'Hide' : 'Show'} full address and QR Code`}
|
||||
onClick={toggleVisibility}
|
||||
variant='secondary'
|
||||
/>
|
||||
</AddressWrapper>
|
||||
{isVisible
|
||||
? (
|
||||
<QRCodeWrapper>
|
||||
<QRCode value={address} />
|
||||
</QRCodeWrapper>
|
||||
)
|
||||
: null}
|
||||
</ColumnComponent>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
name: Wallet Address
|
||||
---
|
||||
|
||||
import { Playground, PropsTable } from 'docz'
|
||||
|
||||
import { WalletAddress } from './wallet-address.js'
|
||||
import { DoczWrapper } from '../theme.js'
|
||||
|
||||
# Wallet Address
|
||||
|
||||
## Properties
|
||||
|
||||
<PropsTable of={WalletAddress} />
|
||||
|
||||
## Basic usage
|
||||
|
||||
<Playground>
|
||||
<DoczWrapper>
|
||||
{() => (
|
||||
<div style={{ width: '700px' }}>
|
||||
<WalletAddress
|
||||
address='t14oHp2v54vfmdgQ3v3SNuQga8JKHTNi2a1'
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</DoczWrapper>
|
||||
</Playground>
|
|
@ -7,11 +7,11 @@ import { normalize } from 'polished'; // eslint-disable-line
|
|||
|
||||
import { DARK } from './constants/themes';
|
||||
|
||||
const darkOne = '#F5CB00';
|
||||
const darkOne = '#F4B728';
|
||||
const lightOne = '#ffffff';
|
||||
const brandOne = '#000';
|
||||
const brandTwo = '#3B3B3F';
|
||||
const activeItem = '#F5CB00';
|
||||
const activeItem = '#F4B728';
|
||||
const text = '#FFF';
|
||||
const cardBackgroundColor = '#000';
|
||||
const sidebarLogoGradientBegin = '#F4B728';
|
||||
|
@ -24,6 +24,7 @@ const transactionReceived = '#6AEAC0';
|
|||
const transactionsDate = '#777777';
|
||||
const transactionsItemHovered = '#222222';
|
||||
const selectButtonShadow = 'rgba(238,201,76,0.65)';
|
||||
const statusPillLabel = '#727272';
|
||||
const transactionsDetailsLabel = transactionsDate;
|
||||
|
||||
const appTheme = {
|
||||
|
@ -68,6 +69,7 @@ const appTheme = {
|
|||
inputBackground: brandOne,
|
||||
selectButtonShadow,
|
||||
transactionsDetailsLabel,
|
||||
statusPillLabel,
|
||||
},
|
||||
sidebarWidth: '180px',
|
||||
headerHeight: '60px',
|
||||
|
|
|
@ -3,10 +3,8 @@ import React from 'react';
|
|||
import styled from 'styled-components';
|
||||
|
||||
import { InputLabelComponent } from '../components/input-label';
|
||||
import { InputComponent } from '../components/input';
|
||||
import { QRCode } from '../components/qrcode';
|
||||
import { RowComponent } from '../components/row';
|
||||
import { ColumnComponent } from '../components/column';
|
||||
import { WalletAddress } from '../components/wallet-address';
|
||||
|
||||
type Props = {
|
||||
addresses: Array<string>,
|
||||
|
@ -27,21 +25,14 @@ const Label = styled(InputLabelComponent)`
|
|||
|
||||
export const ReceiveView = ({ addresses }: Props) => (
|
||||
<Wrapper>
|
||||
<Label value='Addresses: ' />
|
||||
{(addresses || []).map(address => (
|
||||
<Row
|
||||
key={address}
|
||||
alignItems='center'
|
||||
justifyContent='space-between'
|
||||
>
|
||||
<ColumnComponent width='85%'>
|
||||
<Label value='Your Address: ' />
|
||||
<InputComponent
|
||||
value={address}
|
||||
onChange={() => {}}
|
||||
onFocus={event => event.currentTarget.select()}
|
||||
/>
|
||||
</ColumnComponent>
|
||||
<QRCode value={address} />
|
||||
<WalletAddress address={address} />
|
||||
</Row>
|
||||
))}
|
||||
</Wrapper>
|
||||
|
|
Loading…
Reference in New Issue