aboutsummaryrefslogtreecommitdiffstats
path: root/packages/instant/src/components
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2018-12-19 22:16:35 +0800
committerFabio Berger <me@fabioberger.com>2018-12-19 22:16:35 +0800
commit293dadc22aedcaf540f2dc17c8c38087e7ace037 (patch)
tree79f624ab03071a28da83c7bf542acfe0dd7af8cb /packages/instant/src/components
parentddf3bb7c0446f2d85b6fa55cbe0b00b227f08af7 (diff)
parent040b402b6d558d13f2f4e032297b6723cdf2aafe (diff)
downloaddexon-sol-tools-293dadc22aedcaf540f2dc17c8c38087e7ace037.tar
dexon-sol-tools-293dadc22aedcaf540f2dc17c8c38087e7ace037.tar.gz
dexon-sol-tools-293dadc22aedcaf540f2dc17c8c38087e7ace037.tar.bz2
dexon-sol-tools-293dadc22aedcaf540f2dc17c8c38087e7ace037.tar.lz
dexon-sol-tools-293dadc22aedcaf540f2dc17c8c38087e7ace037.tar.xz
dexon-sol-tools-293dadc22aedcaf540f2dc17c8c38087e7ace037.tar.zst
dexon-sol-tools-293dadc22aedcaf540f2dc17c8c38087e7ace037.zip
Merge branch 'development' into website/addPySRA
* development: (141 commits) Add missing CHANGELOG entry for OrderWatcher WS interface Bump up stale to close to 30 days Move onMessageAsync outside of tests and add comments Fix WS tests to remove race-condition and be more specific about the message expected Add temporary console.log to test failing on CI Make @0x/contracts-test-utils a dependency instead of a devDependency Fix test-publish failure in contracts packages Fixed solhint errors Added documentation to `LibAddressArray.append` and switched `if` to `require` smt Updated changelogs for new contracts Added `gas` field so tests pass on Geth; Added Changelog for new Extensions Updated comment `Execute fillOrder` -> `Execute exchange function` Explicit returns Prettier / Linter on contracts + TS Refactoring balance threshold filter Moved exchange calldata functions to separate mixin Less Assembly. More Solidity. Less Efficiency. More Readability. Run all tests for extensions Cleaned up tests for balance threshold filter ...
Diffstat (limited to 'packages/instant/src/components')
-rw-r--r--packages/instant/src/components/instant_heading.tsx15
-rw-r--r--packages/instant/src/components/order_details.tsx265
-rw-r--r--packages/instant/src/components/payment_method.tsx11
-rw-r--r--packages/instant/src/components/scaling_amount_input.tsx1
-rw-r--r--packages/instant/src/components/scaling_input.tsx93
-rw-r--r--packages/instant/src/components/section_header.tsx20
-rw-r--r--packages/instant/src/components/ui/input.tsx6
-rw-r--r--packages/instant/src/components/zero_ex_instant_provider.tsx1
8 files changed, 261 insertions, 151 deletions
diff --git a/packages/instant/src/components/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx
index 816cc5c33..5b1f9592d 100644
--- a/packages/instant/src/components/instant_heading.tsx
+++ b/packages/instant/src/components/instant_heading.tsx
@@ -113,20 +113,23 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> {
}
private readonly _renderEthAmount = (): React.ReactNode => {
+ const ethAmount = format.ethBaseUnitAmount(
+ this.props.totalEthBaseUnitAmount,
+ 4,
+ <AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />,
+ );
+
+ const fontSize = _.isString(ethAmount) && ethAmount.length >= 13 ? '14px' : '16px';
return (
<Text
- fontSize="16px"
+ fontSize={fontSize}
textAlign="right"
width="100%"
fontColor={ColorOption.white}
fontWeight={500}
noWrap={true}
>
- {format.ethBaseUnitAmount(
- this.props.totalEthBaseUnitAmount,
- 4,
- <AmountPlaceholder isPulsating={false} color={PLACEHOLDER_COLOR} />,
- )}
+ {ethAmount}
</Text>
);
};
diff --git a/packages/instant/src/components/order_details.tsx b/packages/instant/src/components/order_details.tsx
index a8e0e2513..9c10ef9e6 100644
--- a/packages/instant/src/components/order_details.tsx
+++ b/packages/instant/src/components/order_details.tsx
@@ -4,124 +4,227 @@ import * as _ from 'lodash';
import * as React from 'react';
import { oc } from 'ts-optchain';
-import { BIG_NUMBER_ZERO } from '../constants';
+import { BIG_NUMBER_ZERO, DEFAULT_UNKOWN_ASSET_NAME } from '../constants';
import { ColorOption } from '../style/theme';
+import { BaseCurrency } from '../types';
import { format } from '../util/format';
import { AmountPlaceholder } from './amount_placeholder';
+import { SectionHeader } from './section_header';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
-import { Text } from './ui/text';
+import { Text, TextProps } from './ui/text';
export interface OrderDetailsProps {
buyQuoteInfo?: BuyQuoteInfo;
selectedAssetUnitAmount?: BigNumber;
ethUsdPrice?: BigNumber;
isLoading: boolean;
+ assetName?: string;
+ baseCurrency: BaseCurrency;
+ onBaseCurrencySwitchEth: () => void;
+ onBaseCurrencySwitchUsd: () => void;
}
export class OrderDetails extends React.Component<OrderDetailsProps> {
public render(): React.ReactNode {
- const { buyQuoteInfo, ethUsdPrice, selectedAssetUnitAmount } = this.props;
- const buyQuoteAccessor = oc(buyQuoteInfo);
- const assetEthBaseUnitAmount = buyQuoteAccessor.assetEthAmount();
- const feeEthBaseUnitAmount = buyQuoteAccessor.feeEthAmount();
- const totalEthBaseUnitAmount = buyQuoteAccessor.totalEthAmount();
- const pricePerTokenEth =
- !_.isUndefined(assetEthBaseUnitAmount) &&
- !_.isUndefined(selectedAssetUnitAmount) &&
- !selectedAssetUnitAmount.eq(BIG_NUMBER_ZERO)
- ? assetEthBaseUnitAmount.div(selectedAssetUnitAmount).ceil()
- : undefined;
+ const shouldShowUsdError = this.props.baseCurrency === BaseCurrency.USD && this._hadErrorFetchingUsdPrice();
return (
<Container width="100%" flexGrow={1} padding="20px 20px 0px 20px">
- <Container marginBottom="10px">
- <Text
- letterSpacing="1px"
- fontColor={ColorOption.primaryColor}
- fontWeight={600}
- textTransform="uppercase"
- fontSize="14px"
- >
- Order Details
- </Text>
- </Container>
- <EthAmountRow
- rowLabel="Token Price"
- ethAmount={pricePerTokenEth}
- ethUsdPrice={ethUsdPrice}
- isLoading={this.props.isLoading}
+ <Container marginBottom="10px">{this._renderHeader()}</Container>
+ {shouldShowUsdError ? this._renderErrorFetchingUsdPrice() : this._renderRows()}
+ </Container>
+ );
+ }
+
+ private _renderRows(): React.ReactNode {
+ const { buyQuoteInfo } = this.props;
+ return (
+ <React.Fragment>
+ <OrderDetailsRow
+ labelText={this._assetAmountLabel()}
+ primaryValue={this._displayAmountOrPlaceholder(buyQuoteInfo && buyQuoteInfo.assetEthAmount)}
/>
- <EthAmountRow
- rowLabel="Fee"
- ethAmount={feeEthBaseUnitAmount}
- ethUsdPrice={ethUsdPrice}
- isLoading={this.props.isLoading}
+ <OrderDetailsRow
+ labelText="Fee"
+ primaryValue={this._displayAmountOrPlaceholder(buyQuoteInfo && buyQuoteInfo.feeEthAmount)}
/>
- <EthAmountRow
- rowLabel="Total Cost"
- ethAmount={totalEthBaseUnitAmount}
- ethUsdPrice={ethUsdPrice}
- shouldEmphasize={true}
- isLoading={this.props.isLoading}
+ <OrderDetailsRow
+ labelText="Total Cost"
+ isLabelBold={true}
+ primaryValue={this._displayAmountOrPlaceholder(buyQuoteInfo && buyQuoteInfo.totalEthAmount)}
+ isPrimaryValueBold={true}
+ secondaryValue={this._totalCostSecondaryValue()}
/>
- </Container>
+ </React.Fragment>
);
}
-}
-export interface EthAmountRowProps {
- rowLabel: string;
- ethAmount?: BigNumber;
- isEthAmountInBaseUnits?: boolean;
- ethUsdPrice?: BigNumber;
- shouldEmphasize?: boolean;
- isLoading: boolean;
+ private _renderErrorFetchingUsdPrice(): React.ReactNode {
+ return (
+ <Text>
+ There was an error fetching the USD price.
+ <Text
+ onClick={this.props.onBaseCurrencySwitchEth}
+ fontWeight={700}
+ fontColor={ColorOption.primaryColor}
+ >
+ Click here
+ </Text>
+ {' to view ETH prices'}
+ </Text>
+ );
+ }
+
+ private _hadErrorFetchingUsdPrice(): boolean {
+ return this.props.ethUsdPrice ? this.props.ethUsdPrice.equals(BIG_NUMBER_ZERO) : false;
+ }
+
+ private _totalCostSecondaryValue(): React.ReactNode {
+ const secondaryCurrency = this.props.baseCurrency === BaseCurrency.USD ? BaseCurrency.ETH : BaseCurrency.USD;
+
+ const canDisplayCurrency =
+ secondaryCurrency === BaseCurrency.ETH ||
+ (secondaryCurrency === BaseCurrency.USD && this.props.ethUsdPrice && !this._hadErrorFetchingUsdPrice());
+
+ if (this.props.buyQuoteInfo && canDisplayCurrency) {
+ return this._displayAmount(secondaryCurrency, this.props.buyQuoteInfo.totalEthAmount);
+ } else {
+ return undefined;
+ }
+ }
+
+ private _displayAmountOrPlaceholder(weiAmount?: BigNumber): React.ReactNode {
+ const { baseCurrency, isLoading } = this.props;
+
+ if (_.isUndefined(weiAmount)) {
+ return (
+ <Container opacity={0.5}>
+ <AmountPlaceholder color={ColorOption.lightGrey} isPulsating={isLoading} />
+ </Container>
+ );
+ }
+
+ return this._displayAmount(baseCurrency, weiAmount);
+ }
+
+ private _displayAmount(currency: BaseCurrency, weiAmount: BigNumber): React.ReactNode {
+ switch (currency) {
+ case BaseCurrency.USD:
+ return format.ethBaseUnitAmountInUsd(weiAmount, this.props.ethUsdPrice, 2, '');
+ case BaseCurrency.ETH:
+ return format.ethBaseUnitAmount(weiAmount, 4, '');
+ }
+ }
+
+ private _assetAmountLabel(): React.ReactNode {
+ const { assetName, baseCurrency } = this.props;
+ const numTokens = this.props.selectedAssetUnitAmount;
+
+ // Display as 0 if we have a selected asset
+ const displayNumTokens =
+ assetName && assetName !== DEFAULT_UNKOWN_ASSET_NAME && _.isUndefined(numTokens)
+ ? new BigNumber(0)
+ : numTokens;
+ if (!_.isUndefined(displayNumTokens)) {
+ let numTokensWithSymbol: React.ReactNode = displayNumTokens.toString();
+ if (assetName) {
+ numTokensWithSymbol += ` ${assetName}`;
+ }
+ const pricePerTokenWei = this._pricePerTokenWei();
+ if (pricePerTokenWei) {
+ const atPriceDisplay = (
+ <Text fontColor={ColorOption.lightGrey}>
+ @ {this._displayAmount(baseCurrency, pricePerTokenWei)}
+ </Text>
+ );
+ numTokensWithSymbol = (
+ <React.Fragment>
+ {numTokensWithSymbol} {atPriceDisplay}
+ </React.Fragment>
+ );
+ }
+ return numTokensWithSymbol;
+ }
+ return 'Token Amount';
+ }
+
+ private _pricePerTokenWei(): BigNumber | undefined {
+ const buyQuoteAccessor = oc(this.props.buyQuoteInfo);
+ const assetTotalInWei = buyQuoteAccessor.assetEthAmount();
+ const selectedAssetUnitAmount = this.props.selectedAssetUnitAmount;
+ return !_.isUndefined(assetTotalInWei) &&
+ !_.isUndefined(selectedAssetUnitAmount) &&
+ !selectedAssetUnitAmount.eq(BIG_NUMBER_ZERO)
+ ? assetTotalInWei.div(selectedAssetUnitAmount).ceil()
+ : undefined;
+ }
+
+ private _baseCurrencyChoice(choice: BaseCurrency): React.ReactNode {
+ const onClick =
+ choice === BaseCurrency.ETH ? this.props.onBaseCurrencySwitchEth : this.props.onBaseCurrencySwitchUsd;
+ const isSelected = this.props.baseCurrency === choice;
+
+ const textStyle: TextProps = { onClick, fontSize: '12px' };
+ if (isSelected) {
+ textStyle.fontColor = ColorOption.primaryColor;
+ textStyle.fontWeight = 700;
+ } else {
+ textStyle.fontColor = ColorOption.lightGrey;
+ }
+ return <Text {...textStyle}>{choice}</Text>;
+ }
+
+ private _renderHeader(): React.ReactNode {
+ return (
+ <Flex justify="space-between">
+ <SectionHeader>Order Details</SectionHeader>
+ <Container>
+ {this._baseCurrencyChoice(BaseCurrency.ETH)}
+ <Container marginLeft="5px" marginRight="5px" display="inline">
+ <Text fontSize="12px" fontColor={ColorOption.feintGrey}>
+ /
+ </Text>
+ </Container>
+ {this._baseCurrencyChoice(BaseCurrency.USD)}
+ </Container>
+ </Flex>
+ );
+ }
}
-export class EthAmountRow extends React.Component<EthAmountRowProps> {
- public static defaultProps = {
- shouldEmphasize: false,
- isEthAmountInBaseUnits: true,
- };
+export interface OrderDetailsRowProps {
+ labelText: React.ReactNode;
+ isLabelBold?: boolean;
+ isPrimaryValueBold?: boolean;
+ primaryValue: React.ReactNode;
+ secondaryValue?: React.ReactNode;
+}
+export class OrderDetailsRow extends React.Component<OrderDetailsRowProps, {}> {
public render(): React.ReactNode {
- const { rowLabel, ethAmount, isEthAmountInBaseUnits, shouldEmphasize, isLoading } = this.props;
-
- const fontWeight = shouldEmphasize ? 700 : 400;
- const ethFormatter = isEthAmountInBaseUnits ? format.ethBaseUnitAmount : format.ethUnitAmount;
return (
<Container padding="10px 0px" borderTop="1px dashed" borderColor={ColorOption.feintGrey}>
<Flex justify="space-between">
- <Text fontWeight={fontWeight} fontColor={ColorOption.grey}>
- {rowLabel}
+ <Text fontWeight={this.props.isLabelBold ? 700 : 400} fontColor={ColorOption.grey}>
+ {this.props.labelText}
</Text>
- <Container>
- {this._renderUsdSection()}
- <Text fontWeight={fontWeight} fontColor={ColorOption.grey}>
- {ethFormatter(
- ethAmount,
- 4,
- <Container opacity={0.5}>
- <AmountPlaceholder color={ColorOption.lightGrey} isPulsating={isLoading} />
- </Container>,
- )}
- </Text>
- </Container>
+ <Container>{this._renderValues()}</Container>
</Flex>
</Container>
);
}
- private _renderUsdSection(): React.ReactNode {
- const usdFormatter = this.props.isEthAmountInBaseUnits
- ? format.ethBaseUnitAmountInUsd
- : format.ethUnitAmountInUsd;
- const shouldHideUsdPriceSection = _.isUndefined(this.props.ethUsdPrice) || _.isUndefined(this.props.ethAmount);
- return shouldHideUsdPriceSection ? null : (
+
+ private _renderValues(): React.ReactNode {
+ const secondaryValueNode: React.ReactNode = this.props.secondaryValue && (
<Container marginRight="3px" display="inline-block">
- <Text fontColor={ColorOption.lightGrey}>
- ({usdFormatter(this.props.ethAmount, this.props.ethUsdPrice)})
- </Text>
+ <Text fontColor={ColorOption.lightGrey}>({this.props.secondaryValue})</Text>
</Container>
);
+ return (
+ <React.Fragment>
+ {secondaryValueNode}
+ <Text fontWeight={this.props.isPrimaryValueBold ? 700 : 400}>{this.props.primaryValue}</Text>
+ </React.Fragment>
+ );
}
}
diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx
index 7c93f1d1c..abadf4bd6 100644
--- a/packages/instant/src/components/payment_method.tsx
+++ b/packages/instant/src/components/payment_method.tsx
@@ -8,6 +8,7 @@ import { envUtil } from '../util/env';
import { CoinbaseWalletLogo } from './coinbase_wallet_logo';
import { MetaMaskLogo } from './meta_mask_logo';
import { PaymentMethodDropdown } from './payment_method_dropdown';
+import { SectionHeader } from './section_header';
import { Circle } from './ui/circle';
import { Container } from './ui/container';
import { Flex } from './ui/flex';
@@ -29,15 +30,7 @@ export class PaymentMethod extends React.Component<PaymentMethodProps> {
<Container width="100%" height="120px" padding="20px 20px 0px 20px">
<Container marginBottom="12px">
<Flex justify="space-between">
- <Text
- letterSpacing="1px"
- fontColor={ColorOption.primaryColor}
- fontWeight={600}
- textTransform="uppercase"
- fontSize="14px"
- >
- {this._renderTitleText()}
- </Text>
+ <SectionHeader>{this._renderTitleText()}</SectionHeader>
{this._renderTitleLabel()}
</Flex>
</Container>
diff --git a/packages/instant/src/components/scaling_amount_input.tsx b/packages/instant/src/components/scaling_amount_input.tsx
index 86aca5a65..4feb0502d 100644
--- a/packages/instant/src/components/scaling_amount_input.tsx
+++ b/packages/instant/src/components/scaling_amount_input.tsx
@@ -58,6 +58,7 @@ export class ScalingAmountInput extends React.Component<ScalingAmountInputProps,
const { textLengthThreshold, fontColor, maxFontSizePx, onFontSizeChange } = this.props;
return (
<ScalingInput
+ type="number"
maxFontSizePx={maxFontSizePx}
textLengthThreshold={textLengthThreshold}
onFontSizeChange={onFontSizeChange}
diff --git a/packages/instant/src/components/scaling_input.tsx b/packages/instant/src/components/scaling_input.tsx
index 791692257..00aea37da 100644
--- a/packages/instant/src/components/scaling_input.tsx
+++ b/packages/instant/src/components/scaling_input.tsx
@@ -1,3 +1,4 @@
+import { ObjectMap } from '@0x/types';
import * as _ from 'lodash';
import * as React from 'react';
@@ -13,10 +14,15 @@ export enum ScalingInputPhase {
export interface ScalingSettings {
percentageToReduceFontSizePerCharacter: number;
- constantPxToIncreaseWidthPerCharacter: number;
+ // 1ch = the width of the 0 chararacter.
+ // Allow to customize 'char' length for different characters.
+ characterWidthOverrides: ObjectMap<number>;
+ // How much room to leave to the right of the scaling input.
+ additionalInputSpaceInCh: number;
}
export interface ScalingInputProps {
+ type?: string;
textLengthThreshold: number;
maxFontSizePx: number;
value: string;
@@ -31,32 +37,29 @@ export interface ScalingInputProps {
hasAutofocus: boolean;
}
-export interface ScalingInputState {
- inputWidthPxAtPhaseChange?: number;
-}
-
export interface ScalingInputSnapshot {
inputWidthPx: number;
}
// These are magic numbers that were determined experimentally.
const defaultScalingSettings: ScalingSettings = {
- percentageToReduceFontSizePerCharacter: 0.125,
- constantPxToIncreaseWidthPerCharacter: 4,
+ percentageToReduceFontSizePerCharacter: 0.1,
+ characterWidthOverrides: {
+ '1': 0.7,
+ '.': 0.4,
+ },
+ additionalInputSpaceInCh: 0.4,
};
-export class ScalingInput extends React.Component<ScalingInputProps, ScalingInputState> {
+export class ScalingInput extends React.Component<ScalingInputProps> {
public static defaultProps = {
onChange: util.boundNoop,
onFontSizeChange: util.boundNoop,
- maxLength: 7,
+ maxLength: 9,
scalingSettings: defaultScalingSettings,
isDisabled: false,
hasAutofocus: false,
};
- public state: ScalingInputState = {
- inputWidthPxAtPhaseChange: undefined,
- };
private readonly _inputRef = React.createRef<HTMLInputElement>();
public static getPhase(textLengthThreshold: number, value: string): ScalingInputPhase {
if (value.length <= textLengthThreshold) {
@@ -93,36 +96,15 @@ export class ScalingInput extends React.Component<ScalingInputProps, ScalingInpu
scalingSettings.percentageToReduceFontSizePerCharacter,
);
}
- public getSnapshotBeforeUpdate(): ScalingInputSnapshot {
- return {
- inputWidthPx: this._getInputWidthInPx(),
- };
- }
public componentDidMount(): void {
// Trigger an initial notification of the calculated fontSize.
const currentPhase = ScalingInput.getPhaseFromProps(this.props);
const currentFontSize = ScalingInput.calculateFontSizeFromProps(this.props, currentPhase);
this.props.onFontSizeChange(currentFontSize);
}
- public componentDidUpdate(
- prevProps: ScalingInputProps,
- prevState: ScalingInputState,
- snapshot: ScalingInputSnapshot,
- ): void {
+ public componentDidUpdate(prevProps: ScalingInputProps): void {
const prevPhase = ScalingInput.getPhaseFromProps(prevProps);
const curPhase = ScalingInput.getPhaseFromProps(this.props);
- // if we went from fixed to scaling, save the width from the transition
- if (prevPhase !== ScalingInputPhase.ScalingFontSize && curPhase === ScalingInputPhase.ScalingFontSize) {
- this.setState({
- inputWidthPxAtPhaseChange: snapshot.inputWidthPx,
- });
- }
- // if we went from scaling to fixed, revert back to scaling using `ch`
- if (prevPhase === ScalingInputPhase.ScalingFontSize && curPhase !== ScalingInputPhase.ScalingFontSize) {
- this.setState({
- inputWidthPxAtPhaseChange: undefined,
- });
- }
const prevFontSize = ScalingInput.calculateFontSizeFromProps(prevProps, prevPhase);
const curFontSize = ScalingInput.calculateFontSizeFromProps(this.props, curPhase);
// If font size has changed, notify.
@@ -131,13 +113,14 @@ export class ScalingInput extends React.Component<ScalingInputProps, ScalingInpu
}
}
public render(): React.ReactNode {
- const { hasAutofocus, isDisabled, fontColor, onChange, placeholder, value, maxLength } = this.props;
+ const { type, hasAutofocus, isDisabled, fontColor, placeholder, value, maxLength } = this.props;
const phase = ScalingInput.getPhaseFromProps(this.props);
return (
<Input
+ type={type}
ref={this._inputRef as any}
fontColor={fontColor}
- onChange={onChange}
+ onChange={this._handleChange}
value={value}
placeholder={placeholder}
fontSize={`${this._calculateFontSize(phase)}px`}
@@ -149,32 +132,34 @@ export class ScalingInput extends React.Component<ScalingInputProps, ScalingInpu
);
}
private readonly _calculateWidth = (phase: ScalingInputPhase): string => {
- const { value, textLengthThreshold, scalingSettings } = this.props;
+ const { value, scalingSettings } = this.props;
if (_.isEmpty(value)) {
return `${this.props.emptyInputWidthCh}ch`;
}
- switch (phase) {
- case ScalingInputPhase.FixedFontSize:
- return `${value.length}ch`;
- case ScalingInputPhase.ScalingFontSize:
- const { inputWidthPxAtPhaseChange } = this.state;
- if (!_.isUndefined(inputWidthPxAtPhaseChange)) {
- const charactersOverMax = value.length - textLengthThreshold;
- const scalingAmount = scalingSettings.constantPxToIncreaseWidthPerCharacter * charactersOverMax;
- const width = inputWidthPxAtPhaseChange + scalingAmount;
- return `${width}px`;
+ const lengthInCh = _.reduce(
+ value.split(''),
+ (sum, char) => {
+ const widthOverride = scalingSettings.characterWidthOverrides[char];
+ if (!_.isUndefined(widthOverride)) {
+ // tslint is confused
+ // tslint:disable-next-line:restrict-plus-operands
+ return sum + widthOverride;
}
- return `${textLengthThreshold}ch`;
- }
+ return sum + 1;
+ },
+ scalingSettings.additionalInputSpaceInCh,
+ );
+ return `${lengthInCh}ch`;
};
private readonly _calculateFontSize = (phase: ScalingInputPhase): number => {
return ScalingInput.calculateFontSizeFromProps(this.props, phase);
};
- private readonly _getInputWidthInPx = (): number => {
- const ref = this._inputRef.current;
- if (!ref) {
- return 0;
+ private readonly _handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
+ const value = event.target.value;
+ const { maxLength } = this.props;
+ if (!_.isUndefined(value) && !_.isUndefined(maxLength) && value.length > maxLength) {
+ return;
}
- return ref.getBoundingClientRect().width;
+ this.props.onChange(event);
};
}
diff --git a/packages/instant/src/components/section_header.tsx b/packages/instant/src/components/section_header.tsx
new file mode 100644
index 000000000..d0974ebdc
--- /dev/null
+++ b/packages/instant/src/components/section_header.tsx
@@ -0,0 +1,20 @@
+import * as React from 'react';
+
+import { ColorOption } from '../style/theme';
+
+import { Text } from './ui/text';
+
+export interface SectionHeaderProps {}
+export const SectionHeader: React.StatelessComponent<SectionHeaderProps> = props => {
+ return (
+ <Text
+ letterSpacing="1px"
+ fontColor={ColorOption.primaryColor}
+ fontWeight={600}
+ textTransform="uppercase"
+ fontSize="12px"
+ >
+ {props.children}
+ </Text>
+ );
+};
diff --git a/packages/instant/src/components/ui/input.tsx b/packages/instant/src/components/ui/input.tsx
index 62c70f9e1..53c43ea0b 100644
--- a/packages/instant/src/components/ui/input.tsx
+++ b/packages/instant/src/components/ui/input.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import { ColorOption, styled } from '../../style/theme';
-export interface InputProps {
+export interface InputProps extends React.HTMLAttributes<HTMLInputElement> {
tabIndex?: number;
className?: string;
value?: string;
@@ -32,6 +32,10 @@ export const Input =
color: ${props => props.theme[props.fontColor || 'white']} !important;
opacity: 0.5 !important;
}
+ &::-webkit-outer-spin-button, &::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+ }
}
`;
diff --git a/packages/instant/src/components/zero_ex_instant_provider.tsx b/packages/instant/src/components/zero_ex_instant_provider.tsx
index 204115fa9..2de327cd7 100644
--- a/packages/instant/src/components/zero_ex_instant_provider.tsx
+++ b/packages/instant/src/components/zero_ex_instant_provider.tsx
@@ -122,6 +122,7 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider
window,
state.selectedAsset,
this.props.affiliateInfo,
+ state.baseCurrency,
),
);
analytics.trackInstantOpened();