remove unused instant pages

This commit is contained in:
Steve Klebanoff
2018-12-19 15:56:12 -08:00
parent ace968a4fc
commit 473537e6e7
7 changed files with 0 additions and 776 deletions

View File

@@ -1,30 +0,0 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { Instant as InstantComponent, InstantProps } from 'ts/pages/instant/instant';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
interface ConnectedState {
translate: Translate;
screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
dispatcher: Dispatcher;
}
const mapStateToProps = (state: State, _ownProps: InstantProps): ConnectedState => ({
translate: state.translate,
screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
dispatcher: new Dispatcher(dispatch),
});
export const Instant: React.ComponentClass<InstantProps> = connect(mapStateToProps, mapDispatchToProps)(
InstantComponent,
);

View File

@@ -1,46 +0,0 @@
import * as _ from 'lodash';
import * as React from 'react';
import { Container } from 'ts/components/ui/container';
import { Text } from 'ts/components/ui/text';
import { colors } from 'ts/style/colors';
import { utils } from 'ts/utils/utils';
export interface ActionLinkProps {
displayText: string;
linkSrc?: string;
onClick?: () => void;
fontSize?: number;
color?: string;
className?: string;
}
export class ActionLink extends React.Component<ActionLinkProps> {
public static defaultProps = {
fontSize: 16,
color: colors.white,
};
public render(): React.ReactNode {
const { displayText, fontSize, color, className } = this.props;
return (
<Container className={`flex items-center ${className}`} onClick={this._handleClick} cursor="pointer">
<Container>
<Text fontSize="16px" fontColor={color}>
{displayText}
</Text>
</Container>
<Container paddingTop="1px" paddingLeft="6px">
<i className="zmdi zmdi-chevron-right bold" style={{ fontSize, color }} />
</Container>
</Container>
);
}
private readonly _handleClick = (event: React.MouseEvent<HTMLElement>) => {
if (!_.isUndefined(this.props.onClick)) {
this.props.onClick();
} else if (!_.isUndefined(this.props.linkSrc)) {
utils.openUrl(this.props.linkSrc);
}
};
}

View File

@@ -1,311 +0,0 @@
import { StandardRelayerAPIOrderProvider } from '@0x/asset-buyer';
import { getContractAddressesForNetworkOrThrow } from '@0x/contract-addresses';
import { assetDataUtils } from '@0x/order-utils';
import { ObjectMap } from '@0x/types';
import * as _ from 'lodash';
import * as React from 'react';
import { CheckMark } from 'ts/components/ui/check_mark';
import { Container } from 'ts/components/ui/container';
import { MultiSelect } from 'ts/components/ui/multi_select';
import { Select, SelectItemConfig } from 'ts/components/ui/select';
import { Spinner } from 'ts/components/ui/spinner';
import { Text } from 'ts/components/ui/text';
import { ConfigGeneratorAddressInput } from 'ts/pages/instant/config_generator_address_input';
import { FeePercentageSlider } from 'ts/pages/instant/fee_percentage_slider';
import { colors } from 'ts/style/colors';
import { WebsitePaths } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { assetMetaDataMap } from '../../../../instant/src/data/asset_meta_data_map';
import { ERC20AssetMetaData, ZeroExInstantBaseConfig } from '../../../../instant/src/types';
export interface ConfigGeneratorProps {
value: ZeroExInstantBaseConfig;
onConfigChange: (config: ZeroExInstantBaseConfig) => void;
}
export interface ConfigGeneratorState {
isLoadingAvailableTokens: boolean;
// Address to token info
availableTokens?: ObjectMap<ERC20AssetMetaData>;
}
const SRA_ENDPOINTS = ['https://api.radarrelay.com/0x/v2/', 'https://sra.bamboorelay.com/0x/v2/'];
export class ConfigGenerator extends React.Component<ConfigGeneratorProps, ConfigGeneratorState> {
public state: ConfigGeneratorState = {
isLoadingAvailableTokens: true,
};
public componentDidMount(): void {
// tslint:disable-next-line:no-floating-promises
this._setAvailableAssetsFromOrderProvider();
}
public componentDidUpdate(prevProps: ConfigGeneratorProps): void {
if (prevProps.value.orderSource !== this.props.value.orderSource) {
// tslint:disable-next-line:no-floating-promises
this._setAvailableAssetsFromOrderProvider();
const newConfig: ZeroExInstantBaseConfig = {
...this.props.value,
availableAssetDatas: undefined,
};
this.props.onConfigChange(newConfig);
}
}
public render(): React.ReactNode {
const { value } = this.props;
if (!_.isString(value.orderSource)) {
throw new Error('ConfigGenerator component only supports string values as an orderSource.');
}
return (
<Container minWidth="350px">
<ConfigGeneratorSection title="Standard relayer API endpoint">
<Select value={value.orderSource} items={this._generateItems()} />
</ConfigGeneratorSection>
<ConfigGeneratorSection {...this._getTokenSelectorProps()}>
{this._renderTokenMultiSelectOrSpinner()}
</ConfigGeneratorSection>
<ConfigGeneratorSection title="Transaction fee ETH address" marginBottom="10px" isOptional={true}>
<ConfigGeneratorAddressInput
value={value.affiliateInfo ? value.affiliateInfo.feeRecipient : ''}
onChange={this._handleAffiliateAddressChange}
/>
</ConfigGeneratorSection>
<ConfigGeneratorSection
title="Fee percentage"
actionText="Learn more"
onActionTextClick={this._handleAffiliatePercentageLearnMoreClick}
>
<FeePercentageSlider
value={value.affiliateInfo.feePercentage}
onChange={this._handleAffiliatePercentageChange}
isDisabled={
_.isUndefined(value.affiliateInfo) ||
_.isUndefined(value.affiliateInfo.feeRecipient) ||
_.isEmpty(value.affiliateInfo.feeRecipient)
}
/>
</ConfigGeneratorSection>
</Container>
);
}
private readonly _getTokenSelectorProps = (): ConfigGeneratorSectionProps => {
if (_.isEmpty(this.state.availableTokens)) {
return {
title: 'What tokens can users buy?',
};
}
if (_.isUndefined(this.props.value.availableAssetDatas)) {
return {
title: 'What tokens can users buy?',
actionText: 'Unselect All',
onActionTextClick: this._handleUnselectAllClick,
};
}
return {
title: 'What tokens can users buy?',
actionText: 'Select All',
onActionTextClick: this._handleSelectAllClick,
};
};
private readonly _generateItems = (): SelectItemConfig[] => {
return _.map(SRA_ENDPOINTS, endpoint => ({
text: endpoint,
onClick: this._handleSRASelection.bind(this, endpoint),
}));
};
private readonly _handleAffiliatePercentageLearnMoreClick = (): void => {
window.open(`${WebsitePaths.Wiki}#Learn-About-Affiliate-Fees`, '_blank');
};
private readonly _handleSRASelection = (sraEndpoint: string) => {
const newConfig: ZeroExInstantBaseConfig = {
...this.props.value,
orderSource: sraEndpoint,
};
this.props.onConfigChange(newConfig);
};
private readonly _handleAffiliateAddressChange = (address: string, isValid: boolean) => {
const oldConfig: ZeroExInstantBaseConfig = this.props.value;
const newConfig: ZeroExInstantBaseConfig = {
...oldConfig,
affiliateInfo: {
feeRecipient: address,
feePercentage: oldConfig.affiliateInfo.feePercentage,
},
};
this.props.onConfigChange(newConfig);
};
private readonly _handleAffiliatePercentageChange = (value: number) => {
const oldConfig: ZeroExInstantBaseConfig = this.props.value;
const newConfig: ZeroExInstantBaseConfig = {
...oldConfig,
affiliateInfo: {
feeRecipient: oldConfig.affiliateInfo.feeRecipient,
feePercentage: value,
},
};
this.props.onConfigChange(newConfig);
};
private readonly _handleSelectAllClick = () => {
const newConfig: ZeroExInstantBaseConfig = {
...this.props.value,
availableAssetDatas: undefined,
};
this.props.onConfigChange(newConfig);
};
private readonly _handleUnselectAllClick = () => {
const newConfig: ZeroExInstantBaseConfig = {
...this.props.value,
availableAssetDatas: [],
};
this.props.onConfigChange(newConfig);
};
private readonly _handleTokenClick = (assetData: string) => {
const { value } = this.props;
let newAvailableAssetDatas: string[] = [];
const allKnownAssetDatas = _.keys(this.state.availableTokens);
const availableAssetDatas = value.availableAssetDatas;
if (_.isUndefined(availableAssetDatas)) {
// It being undefined means it's all tokens.
newAvailableAssetDatas = _.pull(allKnownAssetDatas, assetData);
} else if (!_.includes(availableAssetDatas, assetData)) {
// Add it
newAvailableAssetDatas = [...availableAssetDatas, assetData];
if (newAvailableAssetDatas.length === allKnownAssetDatas.length) {
// If all tokens are manually selected, just show none.
newAvailableAssetDatas = undefined;
}
} else {
// Remove it
newAvailableAssetDatas = _.pull(availableAssetDatas, assetData);
}
const newConfig: ZeroExInstantBaseConfig = {
...this.props.value,
availableAssetDatas: newAvailableAssetDatas,
};
this.props.onConfigChange(newConfig);
};
private readonly _setAvailableAssetsFromOrderProvider = async (): Promise<void> => {
const { value } = this.props;
if (!_.isUndefined(value.orderSource) && _.isString(value.orderSource)) {
this.setState({ isLoadingAvailableTokens: true });
const networkId = constants.NETWORK_ID_MAINNET;
const sraOrderProvider = new StandardRelayerAPIOrderProvider(value.orderSource, networkId);
const etherTokenAddress = getContractAddressesForNetworkOrThrow(networkId).etherToken;
const etherTokenAssetData = assetDataUtils.encodeERC20AssetData(etherTokenAddress);
const assetDatas = await sraOrderProvider.getAvailableMakerAssetDatasAsync(etherTokenAssetData);
const availableTokens = _.reduce(
assetDatas,
(acc, assetData) => {
const metaDataIfExists = assetMetaDataMap[assetData] as ERC20AssetMetaData;
if (metaDataIfExists) {
acc[assetData] = metaDataIfExists;
}
return acc;
},
{} as ObjectMap<ERC20AssetMetaData>,
);
this.setState({ availableTokens, isLoadingAvailableTokens: false });
}
};
private readonly _renderTokenMultiSelectOrSpinner = (): React.ReactNode => {
const { value } = this.props;
const { availableTokens, isLoadingAvailableTokens } = this.state;
const multiSelectHeight = '200px';
if (isLoadingAvailableTokens) {
return (
<Container
className="flex flex-column items-center justify-center"
height={multiSelectHeight}
backgroundColor={colors.white}
borderRadius="4px"
width="100%"
>
<Container position="relative" left="12px" marginBottom="20px">
<Spinner />
</Container>
<Text fontSize="16px">Loading...</Text>
</Container>
);
}
const availableAssetDatas = _.keys(availableTokens);
if (availableAssetDatas.length === 0) {
return (
<Container
className="flex flex-column items-center justify-center"
height={multiSelectHeight}
backgroundColor={colors.white}
borderRadius="4px"
width="100%"
>
<Text fontSize="16px">No tokens available. Try another endpoint?</Text>
</Container>
);
}
const items = _.map(_.keys(availableTokens), assetData => {
const metaData = availableTokens[assetData];
return {
value: assetData,
renderItemContent: (isSelected: boolean) => (
<Container className="flex items-center">
<Container marginRight="10px">
<CheckMark isChecked={isSelected} />
</Container>
<Text
fontSize="16px"
fontColor={isSelected ? colors.mediumBlue : colors.darkerGrey}
fontWeight={300}
>
<b>{metaData.symbol.toUpperCase()}</b> {metaData.name}
</Text>
</Container>
),
onClick: this._handleTokenClick.bind(this, assetData),
};
});
return <MultiSelect items={items} selectedValues={value.availableAssetDatas} height={multiSelectHeight} />;
};
}
export interface ConfigGeneratorSectionProps {
title: string;
actionText?: string;
onActionTextClick?: () => void;
isOptional?: boolean;
marginBottom?: string;
}
export const ConfigGeneratorSection: React.StatelessComponent<ConfigGeneratorSectionProps> = ({
title,
actionText,
onActionTextClick,
isOptional,
marginBottom,
children,
}) => (
<Container marginBottom={marginBottom}>
<Container marginBottom="10px" className="flex justify-between items-center">
<Container>
<Text fontColor={colors.white} fontSize="16px" lineHeight="18px" display="inline">
{title}
</Text>
{isOptional && (
<Text fontColor={colors.grey} fontSize="16px" lineHeight="18px" display="inline">
{' '}
(optional)
</Text>
)}
</Container>
{actionText && (
<Text fontSize="12px" fontColor={colors.grey} onClick={onActionTextClick}>
{actionText}
</Text>
)}
</Container>
{children}
</Container>
);
ConfigGeneratorSection.defaultProps = {
marginBottom: '30px',
};

View File

@@ -1,110 +0,0 @@
import * as _ from 'lodash';
import * as React from 'react';
import { Container } from 'ts/components/ui/container';
import { Text } from 'ts/components/ui/text';
import { ActionLink } from 'ts/pages/instant/action_link';
import { CodeDemo } from 'ts/pages/instant/code_demo';
import { ConfigGenerator } from 'ts/pages/instant/config_generator';
import { colors } from 'ts/style/colors';
import { WebsitePaths } from 'ts/types';
import { ZeroExInstantBaseConfig } from '../../../../instant/src/types';
export interface ConfiguratorProps {
hash: string;
}
export interface ConfiguratorState {
instantConfig: ZeroExInstantBaseConfig;
}
export class Configurator extends React.Component<ConfiguratorProps> {
public state: ConfiguratorState = {
instantConfig: {
orderSource: 'https://api.radarrelay.com/0x/v2/',
availableAssetDatas: undefined,
affiliateInfo: {
feeRecipient: '',
feePercentage: 0,
},
},
};
public render(): React.ReactNode {
const { hash } = this.props;
const codeToDisplay = this._generateCodeDemoCode();
return (
<Container
className="flex justify-center py4 px3"
id={hash}
backgroundColor={colors.instantTertiaryBackground}
>
<Container className="mx3">
<Container className="mb3">
<Text fontSize="20px" lineHeight="28px" fontColor={colors.white} fontWeight={500}>
0x Instant Configurator
</Text>
</Container>
<ConfigGenerator value={this.state.instantConfig} onConfigChange={this._handleConfigChange} />
</Container>
<Container className="mx3" height="550px">
<Container className="mb3 flex justify-between">
<Text fontSize="20px" lineHeight="28px" fontColor={colors.white} fontWeight={500}>
Code Snippet
</Text>
<ActionLink
displayText="Explore the Docs"
linkSrc={`${WebsitePaths.Wiki}#Get-Started-With-Instant`}
color={colors.grey}
/>
</Container>
<CodeDemo key={codeToDisplay}>{codeToDisplay}</CodeDemo>
</Container>
</Container>
);
}
private readonly _handleConfigChange = (config: ZeroExInstantBaseConfig) => {
this.setState({
instantConfig: config,
});
};
private readonly _generateCodeDemoCode = (): string => {
const { instantConfig } = this.state;
return `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://instant.0x.org/instant.js"></script>
</head>
<body>
<script>
zeroExInstant.render({
orderSource: '${instantConfig.orderSource}',${
!_.isUndefined(instantConfig.affiliateInfo) && instantConfig.affiliateInfo.feeRecipient
? `\n affiliateInfo: {
feeRecipient: '${instantConfig.affiliateInfo.feeRecipient.toLowerCase()}',
feePercentage: ${instantConfig.affiliateInfo.feePercentage}
},`
: ''
}${
!_.isUndefined(instantConfig.availableAssetDatas)
? `\n availableAssetDatas: ${this._renderAvailableAssetDatasString(
instantConfig.availableAssetDatas,
)}`
: ''
}
}, 'body');
</script>
</body>
</html>`;
};
private readonly _renderAvailableAssetDatasString = (availableAssetDatas: string[]): string => {
const stringAvailableAssetDatas = availableAssetDatas.map(assetData => `'${assetData}'`);
if (availableAssetDatas.length < 2) {
return `[${stringAvailableAssetDatas.join(', ')}]`;
}
return `[\n ${stringAvailableAssetDatas.join(
', \n ',
)}\n ]`;
};
}

View File

@@ -1,115 +0,0 @@
import * as _ from 'lodash';
import * as React from 'react';
import { Container } from 'ts/components/ui/container';
import { Image } from 'ts/components/ui/image';
import { Text } from 'ts/components/ui/text';
import { ActionLink, ActionLinkProps } from 'ts/pages/instant/action_link';
import { colors } from 'ts/style/colors';
import { ScreenWidths, WebsitePaths } from 'ts/types';
export interface FeatureProps {
screenWidth: ScreenWidths;
onGetStartedClick: () => void;
}
export const Features = (props: FeatureProps) => {
const isSmallScreen = props.screenWidth === ScreenWidths.Sm;
const getStartedLinkInfo = {
displayText: 'Get started',
onClick: props.onGetStartedClick,
};
const exploreTheDocsLinkInfo = {
displayText: 'Explore the docs',
linkSrc: `${WebsitePaths.Wiki}#Get-Started-With-Instant`,
};
const tokenLinkInfos = isSmallScreen ? [getStartedLinkInfo] : [getStartedLinkInfo, exploreTheDocsLinkInfo];
return (
<Container backgroundColor={colors.instantSecondaryBackground} className="py3 flex flex-column px3">
<FeatureItem
imgSrc="images/instant/feature_1.svg"
title="Support ERC-20 and ERC-721 tokens"
description="Seamlessly integrate token purchasing into your product experience by offering digital assets ranging from in-game items to stablecoins."
linkInfos={tokenLinkInfos}
screenWidth={props.screenWidth}
/>
<FeatureItem
imgSrc="images/instant/feature_2.svg"
title="Generate revenue for your business"
description="With just a few lines of code, you can earn up to 5% in affiliate fees on every transaction from your crypto wallet or dApp."
linkInfos={[
{
displayText: 'Learn about affiliate fees',
linkSrc: `${WebsitePaths.Wiki}#Learn-About-Affiliate-Fees`,
},
]}
screenWidth={props.screenWidth}
/>
<FeatureItem
imgSrc="images/instant/feature_3.svg"
title="Easy and Flexible Integration"
description="Use our out-of-the-box design or customize the user interface by integrating the AssetBuyer engine. You can also tap into 0x networked liquidity or choose your own liquidity pool."
linkInfos={[
{
displayText: 'Explore AssetBuyer',
linkSrc: `${WebsitePaths.Docs}/asset-buyer`,
},
]}
screenWidth={props.screenWidth}
/>
</Container>
);
};
interface FeatureItemProps {
imgSrc: string;
title: string;
description: string;
linkInfos: ActionLinkProps[];
screenWidth: ScreenWidths;
}
const FeatureItem = (props: FeatureItemProps) => {
const { imgSrc, title, description, linkInfos, screenWidth } = props;
const isLargeScreen = screenWidth === ScreenWidths.Lg;
const maxWidth = isLargeScreen ? '500px' : undefined;
const image = (
<Container className="center" minWidth="435px" maxHeight="225px">
<Image src={imgSrc} additionalStyle={{ filter: 'drop-shadow(0px 4px 4px rgba(0,0,0,.25))' }} />
</Container>
);
const info = (
<Container maxWidth={maxWidth}>
<Text fontSize="24px" lineHeight="34px" fontColor={colors.white} fontWeight={500}>
{title}
</Text>
<Container marginTop="28px">
<Text fontFamily="Roboto Mono" fontSize="14px" lineHeight="2em" fontColor={colors.grey500}>
{description}
</Text>
</Container>
<Container className="flex" marginTop="28px">
{_.map(linkInfos, linkInfo => (
<Container key={linkInfo.displayText} marginRight="32px">
<ActionLink {...linkInfo} />
</Container>
))}
</Container>
</Container>
);
return (
<Container className="flex flex-column items-center py4 px3">
{isLargeScreen ? (
<Container className="flex">
{image}
<Container marginLeft="115px">{info}</Container>
</Container>
) : (
<Container className="flex flex-column items-center" width="100%">
{image}
<Container marginTop="48px">{info}</Container>
</Container>
)}
</Container>
);
};

View File

@@ -1,77 +0,0 @@
import Slider from 'rc-slider';
import 'rc-slider/assets/index.css';
import * as React from 'react';
import { Text } from 'ts/components/ui/text';
import { colors } from 'ts/style/colors';
import { injectGlobal } from 'ts/style/theme';
const SliderWithTooltip = (Slider as any).createSliderWithTooltip(Slider);
// tslint:disable-next-line:no-unused-expression
injectGlobal`
.rc-slider-tooltip-inner {
box-shadow: none !important;
background-color: ${colors.white} !important;
border-radius: 4px !important;
padding: 3px 12px !important;
height: auto !important;
position: relative;
top: 7px;
&: after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-width: 6px;
bottom: 100%;
left: 100%;
border-bottom-color: ${colors.white};
margin-left: -60%;
}
}
.rc-slider-disabled {
background-color: inherit !important;
}
`;
export interface FeePercentageSliderProps {
value: number;
isDisabled: boolean;
onChange: (value: number) => void;
}
export class FeePercentageSlider extends React.Component<FeePercentageSliderProps> {
public render(): React.ReactNode {
return (
<SliderWithTooltip
disabled={this.props.isDisabled}
min={0}
max={0.05}
step={0.0025}
value={this.props.value}
onChange={this.props.onChange}
tipFormatter={this._feePercentageSliderFormatter}
tipProps={{ placement: 'bottom' }}
trackStyle={{
backgroundColor: '#b4b4b4',
}}
railStyle={{
backgroundColor: '#696969',
}}
handleStyle={{
border: 'none',
boxShadow: 'none',
}}
activeDotStyle={{
boxShadow: 'none',
border: 'none',
}}
/>
);
}
private readonly _feePercentageSliderFormatter = (value: number): React.ReactNode => {
return <Text fontColor={colors.black} fontSize="14px" fontWeight={700}>{`${(value * 100).toFixed(2)}%`}</Text>;
};
}

View File

@@ -1,87 +0,0 @@
import { utils as sharedUtils } from '@0x/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
import { Footer } from 'ts/components/footer';
import { MetaTags } from 'ts/components/meta_tags';
import { TopBar } from 'ts/components/top_bar/top_bar';
import { Container } from 'ts/components/ui/container';
import { Configurator } from 'ts/pages/instant/configurator';
import { Features } from 'ts/pages/instant/features';
import { Introducing0xInstant } from 'ts/pages/instant/introducing_0x_instant';
import { NeedMore } from 'ts/pages/instant/need_more';
import { Screenshots } from 'ts/pages/instant/screenshots';
import { Dispatcher } from 'ts/redux/dispatcher';
import { colors } from 'ts/style/colors';
import { ScreenWidths, WebsitePaths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils';
export interface InstantProps {
location: Location;
translate: Translate;
dispatcher: Dispatcher;
screenWidth: ScreenWidths;
}
export interface InstantState {}
const CONFIGURATOR_HASH = 'configure';
const THROTTLE_TIMEOUT = 100;
const DOCUMENT_TITLE = '0x Instant';
const DOCUMENT_DESCRIPTION = '0x Instant';
export class Instant extends React.Component<InstantProps, InstantState> {
// TODO: consolidate this small screen scaffolding into one place (its being used in portal and docs as well)
private readonly _throttledScreenWidthUpdate: () => void;
public constructor(props: InstantProps) {
super(props);
this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
}
public componentDidMount(): void {
window.addEventListener('resize', this._throttledScreenWidthUpdate);
window.scrollTo(0, 0);
}
public render(): React.ReactNode {
return (
<Container overflowX="hidden">
<MetaTags title={DOCUMENT_TITLE} description={DOCUMENT_DESCRIPTION} />
<DocumentTitle title={DOCUMENT_TITLE} />
<TopBar
blockchainIsLoaded={false}
location={this.props.location}
style={{ backgroundColor: colors.instantPrimaryBackground, position: 'relative' }}
translate={this.props.translate}
isNightVersion={true}
/>
<Container backgroundColor={colors.instantPrimaryBackground} />
<Introducing0xInstant screenWidth={this.props.screenWidth} onCTAClick={this._onGetStartedClick} />
<Screenshots screenWidth={this.props.screenWidth} />
<Features screenWidth={this.props.screenWidth} onGetStartedClick={this._onGetStartedClick} />
{!this._isSmallScreen() && <Configurator hash={CONFIGURATOR_HASH} />}
<NeedMore screenWidth={this.props.screenWidth} />
<Footer translate={this.props.translate} dispatcher={this.props.dispatcher} />
</Container>
);
}
private readonly _onGetStartedClick = () => {
if (this._isSmallScreen()) {
utils.openUrl(`${WebsitePaths.Wiki}#Get-Started-With-Instant`);
} else {
this._scrollToConfigurator();
}
};
private _isSmallScreen(): boolean {
const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm;
return isSmallScreen;
}
private _scrollToConfigurator(): void {
sharedUtils.setUrlHash(CONFIGURATOR_HASH);
sharedUtils.scrollToHash(CONFIGURATOR_HASH, '');
}
private _updateScreenWidth(): void {
const newScreenWidth = utils.getScreenWidth();
this.props.dispatcher.updateScreenWidth(newScreenWidth);
}
}