diff options
Diffstat (limited to 'packages')
20 files changed, 26 insertions, 959 deletions
diff --git a/packages/website/ts/@next/components/blockIconLink.tsx b/packages/website/ts/@next/components/blockIconLink.tsx index bdcc5c29d..8d66a4afa 100644 --- a/packages/website/ts/@next/components/blockIconLink.tsx +++ b/packages/website/ts/@next/components/blockIconLink.tsx @@ -1,20 +1,24 @@ +import { History, Location } from 'history'; import * as React from 'react'; -import { withRouter } from 'react-router-dom'; +import { match, withRouter } from 'react-router-dom'; import styled from 'styled-components'; import { Button } from 'ts/@next/components/button'; import { Icon } from 'ts/@next/components/icon'; -interface Props { +interface BaseComponentProps { icon?: string; iconComponent?: React.ReactNode; title: string; linkLabel: string; linkUrl?: string; linkAction?: () => void; + history: History; + location: Location; + match: match<any>; } -class BaseComponent extends React.PureComponent<Props> { +class BaseComponent extends React.PureComponent<BaseComponentProps> { public onClick = (): void => { const { linkAction, linkUrl } = this.props; @@ -44,7 +48,7 @@ class BaseComponent extends React.PureComponent<Props> { } } -export const BlockIconLink = withRouter(BaseComponent); +export const BlockIconLink = withRouter<BaseComponentProps>(BaseComponent); const Wrap = styled.div` width: calc(50% - 15px); diff --git a/packages/website/ts/@next/components/button.tsx b/packages/website/ts/@next/components/button.tsx index 675f69308..348f1b7b4 100644 --- a/packages/website/ts/@next/components/button.tsx +++ b/packages/website/ts/@next/components/button.tsx @@ -37,7 +37,7 @@ export const Button = (props: ButtonInterface) => { linkElem = ReactRouterLink; } - const Component = linkElem ? ButtonBase.withComponent(linkElem) : ButtonBase; + const Component = linkElem ? ButtonBase.withComponent<any>(linkElem) : ButtonBase; const targetProp = href && target ? { target } : {}; return ( diff --git a/packages/website/ts/@next/components/header.tsx b/packages/website/ts/@next/components/header.tsx index 24bfa28ba..e886923df 100644 --- a/packages/website/ts/@next/components/header.tsx +++ b/packages/website/ts/@next/components/header.tsx @@ -29,7 +29,7 @@ interface NavItemProps { id?: string; text?: string; dropdownWidth?: number; - dropdownComponent?: React.ReactNode; + dropdownComponent?: React.FunctionComponent<any>; shouldOpenInNewTab?: boolean; } diff --git a/packages/website/ts/@next/components/link.tsx b/packages/website/ts/@next/components/link.tsx index a7711451b..080a0abcc 100644 --- a/packages/website/ts/@next/components/link.tsx +++ b/packages/website/ts/@next/components/link.tsx @@ -14,6 +14,7 @@ interface LinkInterface { textColor: string; }; shouldOpenInNewTab?: boolean; + target?: string; } export const Link = (props: LinkInterface) => { diff --git a/packages/website/ts/@next/components/mobileNav.tsx b/packages/website/ts/@next/components/mobileNav.tsx index 122036b9a..13cf46fca 100644 --- a/packages/website/ts/@next/components/mobileNav.tsx +++ b/packages/website/ts/@next/components/mobileNav.tsx @@ -96,13 +96,16 @@ const Overlay = styled.div` cursor: pointer; `; +interface SectionProps { + isDark?: boolean; +} const Section = styled.div < - { isDark: boolean } > + SectionProps > ` width: 100%; padding: 15px 30px; - background-color: ${props => props.isDark && props.theme.mobileNavBgLower}; + background-color: ${props => (props.isDark ? props.theme.mobileNavBgLower : 'transparent')}; `; const Grid = diff --git a/packages/website/ts/@next/components/modals/input.tsx b/packages/website/ts/@next/components/modals/input.tsx index d4d53402a..e3062b895 100644 --- a/packages/website/ts/@next/components/modals/input.tsx +++ b/packages/website/ts/@next/components/modals/input.tsx @@ -13,6 +13,7 @@ interface InputProps { type?: string; errors?: ErrorProps; isErrors?: boolean; + required?: boolean; } interface ErrorProps { diff --git a/packages/website/ts/@next/components/newsletter_form.tsx b/packages/website/ts/@next/components/newsletter_form.tsx index ce6b04993..8572ccc5f 100644 --- a/packages/website/ts/@next/components/newsletter_form.tsx +++ b/packages/website/ts/@next/components/newsletter_form.tsx @@ -15,6 +15,7 @@ interface InputProps { type: string; label: string; textColor: string; + required?: boolean; } interface ArrowProps { @@ -78,7 +79,7 @@ class Form extends React.Component<FormProps> { ); } - private async _onSubmitAsync(e: Event): Promise<void> { + private async _onSubmitAsync(e: React.FormEvent<HTMLFormElement>): Promise<void> { e.preventDefault(); const email = this.emailInput.current.value; diff --git a/packages/website/ts/@next/pages/community.tsx b/packages/website/ts/@next/pages/community.tsx index eb3e7210d..a259e3438 100644 --- a/packages/website/ts/@next/pages/community.tsx +++ b/packages/website/ts/@next/pages/community.tsx @@ -253,9 +253,11 @@ const EventContent = styled.div` padding: 30px 30px; `; -// Community Links +interface StyledCommunityLinkProps { + bgColor: string; +} const StyledCommunityLink = styled.a` - background-color: ${(props: CommunityLinkProps) => props.bgColor}; + background-color: ${(props: StyledCommunityLinkProps) => props.bgColor}; color: ${colors.white}; width: 175px; height: 175px; diff --git a/packages/website/ts/@next/pages/instant/config_generator.tsx b/packages/website/ts/@next/pages/instant/config_generator.tsx index d4497ac92..3f00e33e2 100644 --- a/packages/website/ts/@next/pages/instant/config_generator.tsx +++ b/packages/website/ts/@next/pages/instant/config_generator.tsx @@ -128,7 +128,7 @@ export class ConfigGenerator extends React.Component<ConfigGeneratorProps, Confi private readonly _handleAffiliatePercentageLearnMoreClick = (): void => { window.open(`${WebsitePaths.Wiki}#Learn-About-Affiliate-Fees`, '_blank'); }; - private readonly _handleSRASelection = (event: Event) => { + private readonly _handleSRASelection = (event: React.ChangeEvent<HTMLSelectElement>) => { const sraEndpoint = event.target.value; const newConfig: ZeroExInstantBaseConfig = { ...this.props.value, diff --git a/packages/website/ts/components/ui/container.tsx b/packages/website/ts/components/ui/container.tsx index ae00851e5..778f59f27 100644 --- a/packages/website/ts/components/ui/container.tsx +++ b/packages/website/ts/components/ui/container.tsx @@ -28,6 +28,7 @@ export interface ContainerProps { borderBottomRightRadius?: StringOrNum; borderBottom?: StringOrNum; borderColor?: string; + children?: React.ReactNode; maxWidth?: StringOrNum; maxHeight?: StringOrNum; width?: StringOrNum; diff --git a/packages/website/ts/components/ui/select.tsx b/packages/website/ts/components/ui/select.tsx deleted file mode 100644 index e4fb50f59..000000000 --- a/packages/website/ts/components/ui/select.tsx +++ /dev/null @@ -1,170 +0,0 @@ -import { colors } from '@0x/react-shared'; -import * as _ from 'lodash'; -import * as React from 'react'; - -import { zIndex } from 'ts/style/z_index'; - -import { Container } from './container'; -import { Overlay } from './overlay'; -import { Text } from './text'; - -export interface SelectItemConfig { - text: string; - onClick?: () => void; -} - -export interface SelectProps { - value: string; - label?: string; - items: SelectItemConfig[]; - onOpen?: () => void; - border?: string; - fontSize?: string; - iconSize?: number; - textColor?: string; - labelColor?: string; - backgroundColor?: string; -} - -export interface SelectState { - isOpen: boolean; -} - -export class Select extends React.Component<SelectProps, SelectState> { - public static defaultProps = { - items: [] as SelectItemConfig[], - textColor: colors.black, - backgroundColor: colors.white, - fontSize: '16px', - iconSize: 25, - }; - public state: SelectState = { - isOpen: false, - }; - public render(): React.ReactNode { - const { value, label, items, border, textColor, labelColor, backgroundColor, fontSize, iconSize } = this.props; - const { isOpen } = this.state; - const hasItems = !_.isEmpty(items); - const borderRadius = isOpen ? '4px 4px 0px 0px' : '4px'; - return ( - <React.Fragment> - {isOpen && ( - <Overlay - style={{ - zIndex: zIndex.overlay, - backgroundColor: 'rgba(255, 255, 255, 0)', - }} - onClick={this._closeDropdown} - /> - )} - <Container position="relative"> - <Container - cursor={hasItems ? 'pointer' : undefined} - onClick={this._handleDropdownClick} - borderRadius={borderRadius} - hasBoxShadow={isOpen} - border={border} - backgroundColor={backgroundColor} - padding="0.5em 0.8em" - width="100%" - > - <Container className="flex justify-between"> - <Text fontSize={fontSize} fontColor={textColor}> - {value} - </Text> - <Container> - {label && ( - <Text fontSize={fontSize} fontColor={labelColor}> - {label} - </Text> - )} - {hasItems && ( - <Container marginLeft="5px" display="inline-block"> - <i - className="zmdi zmdi-chevron-down" - style={{ fontSize: iconSize, color: colors.darkGrey }} - /> - </Container> - )} - </Container> - </Container> - </Container> - {isOpen && ( - <Container - width="100%" - position="absolute" - onClick={this._closeDropdown} - zIndex={zIndex.aboveOverlay} - hasBoxShadow={true} - > - {_.map(items, (item, index) => ( - <SelectItem - key={item.text} - {...item} - isLast={index === items.length - 1} - backgroundColor={backgroundColor} - textColor={textColor} - border={border} - /> - ))} - </Container> - )} - </Container> - </React.Fragment> - ); - } - private readonly _handleDropdownClick = (): void => { - if (_.isEmpty(this.props.items)) { - return; - } - const isOpen = !this.state.isOpen; - this.setState({ - isOpen, - }); - - if (isOpen && this.props.onOpen) { - this.props.onOpen(); - } - }; - private readonly _closeDropdown = (): void => { - this.setState({ - isOpen: false, - }); - }; -} - -export interface SelectItemProps extends SelectItemConfig { - text: string; - onClick?: () => void; - isLast: boolean; - backgroundColor?: string; - border?: string; - textColor?: string; - fontSize?: string; -} - -export const SelectItem: React.StatelessComponent<SelectItemProps> = ({ - text, - onClick, - isLast, - border, - backgroundColor, - textColor, - fontSize, -}) => ( - <Container - onClick={onClick} - cursor="pointer" - backgroundColor={backgroundColor} - padding="0.8em" - borderTop="0" - border={border} - shouldDarkenOnHover={true} - borderRadius={isLast ? '0px 0px 4px 4px' : undefined} - width="100%" - > - <Text fontSize={fontSize} fontColor={textColor}> - {text} - </Text> - </Container> -); diff --git a/packages/website/ts/containers/instant.ts b/packages/website/ts/containers/instant.ts deleted file mode 100644 index 12ae7454e..000000000 --- a/packages/website/ts/containers/instant.ts +++ /dev/null @@ -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, -); diff --git a/packages/website/ts/globals.d.ts b/packages/website/ts/globals.d.ts index b953a319f..05f3c7f88 100644 --- a/packages/website/ts/globals.d.ts +++ b/packages/website/ts/globals.d.ts @@ -1,3 +1,4 @@ +declare module '@reach/dialog'; declare module 'truffle-contract'; declare module 'whatwg-fetch'; declare module 'thenby'; diff --git a/packages/website/ts/pages/instant/action_link.tsx b/packages/website/ts/pages/instant/action_link.tsx deleted file mode 100644 index c196f03ef..000000000 --- a/packages/website/ts/pages/instant/action_link.tsx +++ /dev/null @@ -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); - } - }; -} diff --git a/packages/website/ts/pages/instant/config_generator.tsx b/packages/website/ts/pages/instant/config_generator.tsx deleted file mode 100644 index fbeeeaeaf..000000000 --- a/packages/website/ts/pages/instant/config_generator.tsx +++ /dev/null @@ -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', -}; diff --git a/packages/website/ts/pages/instant/configurator.tsx b/packages/website/ts/pages/instant/configurator.tsx deleted file mode 100644 index a9dd5864c..000000000 --- a/packages/website/ts/pages/instant/configurator.tsx +++ /dev/null @@ -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 ]`; - }; -} diff --git a/packages/website/ts/pages/instant/features.tsx b/packages/website/ts/pages/instant/features.tsx deleted file mode 100644 index ed98ceb53..000000000 --- a/packages/website/ts/pages/instant/features.tsx +++ /dev/null @@ -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> - ); -}; diff --git a/packages/website/ts/pages/instant/fee_percentage_slider.tsx b/packages/website/ts/pages/instant/fee_percentage_slider.tsx deleted file mode 100644 index d76cee58f..000000000 --- a/packages/website/ts/pages/instant/fee_percentage_slider.tsx +++ /dev/null @@ -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>; - }; -} diff --git a/packages/website/ts/pages/instant/instant.tsx b/packages/website/ts/pages/instant/instant.tsx deleted file mode 100644 index d72585bfa..000000000 --- a/packages/website/ts/pages/instant/instant.tsx +++ /dev/null @@ -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); - } -} diff --git a/packages/website/tsconfig.json b/packages/website/tsconfig.json index 96bba7bbf..8fbba17bb 100644 --- a/packages/website/tsconfig.json +++ b/packages/website/tsconfig.json @@ -22,7 +22,6 @@ }, "awesomeTypescriptLoaderOptions": { "useCache": true, - "errorsAsWarnings": true, "reportFiles": ["./ts/**/*"] }, "include": ["./ts/**/*"] |