Browse Source

Merge pull request #239 from loeck/master

Add Unit selector in InputCurrency
master
Meriadec Pillet 7 years ago
committed by GitHub
parent
commit
e886e91cea
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      package.json
  2. 8
      src/components/SelectAccount/stories.js
  3. 4
      src/components/base/DropDown/index.js
  4. 48
      src/components/base/InputCurrency/index.js
  5. 43
      src/components/base/InputCurrency/stories.js
  6. 32
      src/components/base/Select/index.js
  7. 75
      src/components/modals/Send/01-step-amount.js
  8. 11
      src/components/modals/Send/index.js
  9. 11
      src/styles/theme.js
  10. 33
      yarn.lock

6
package.json

@ -57,12 +57,12 @@
"cross-env": "^5.1.4", "cross-env": "^5.1.4",
"d3": "^4.13.0", "d3": "^4.13.0",
"debug": "^3.1.0", "debug": "^3.1.0",
"downshift": "^1.30.1", "downshift": "^1.31.1",
"electron-store": "^1.3.0", "electron-store": "^1.3.0",
"electron-updater": "^2.21.1", "electron-updater": "^2.21.1",
"fuse.js": "^3.2.0", "fuse.js": "^3.2.0",
"history": "^4.7.2", "history": "^4.7.2",
"i18next": "^10.5.1", "i18next": "^10.6.0",
"i18next-node-fs-backend": "^1.0.0", "i18next-node-fs-backend": "^1.0.0",
"ledger-test-library": "KhalilBellakrid/ledger-test-library-nodejs#7d37482", "ledger-test-library": "KhalilBellakrid/ledger-test-library-nodejs#7d37482",
"lodash": "^4.17.5", "lodash": "^4.17.5",
@ -91,7 +91,7 @@
"source-map-support": "^0.5.4", "source-map-support": "^0.5.4",
"styled-components": "^3.2.3", "styled-components": "^3.2.3",
"styled-system": "^2.2.1", "styled-system": "^2.2.1",
"tippy.js": "^2.3.0", "tippy.js": "^2.4.0",
"victory": "^0.25.6" "victory": "^0.25.6"
}, },
"devDependencies": { "devDependencies": {

8
src/components/SelectAccount/stories.js

@ -1,6 +1,6 @@
// @flow // @flow
import React, { PureComponent } from 'react' import React, { Component } from 'react'
import { storiesOf } from '@storybook/react' import { storiesOf } from '@storybook/react'
import Chance from 'chance' import Chance from 'chance'
import { getCurrencyByCoinType, getDefaultUnitByCoinType } from '@ledgerhq/currencies' import { getCurrencyByCoinType, getDefaultUnitByCoinType } from '@ledgerhq/currencies'
@ -29,11 +29,7 @@ export const accounts = [...Array(20)].map(() => ({
}, },
})) }))
type State = { class Wrapper extends Component<any, any> {
value: any,
}
class Wrapper extends PureComponent<any, State> {
state = { state = {
value: '', value: '',
} }

4
src/components/base/DropDown/index.js

@ -145,7 +145,7 @@ class DropDown extends PureComponent<Props> {
itemToString={itemToString} itemToString={itemToString}
selectedItem={value} selectedItem={value}
render={({ render={({
getButtonProps, getToggleButtonProps,
getRootProps, getRootProps,
isOpen, isOpen,
openMenu, openMenu,
@ -153,7 +153,7 @@ class DropDown extends PureComponent<Props> {
...downshiftProps ...downshiftProps
}) => ( }) => (
<Box {...getRootProps({ refKey: 'innerRef' })} horizontal relative> <Box {...getRootProps({ refKey: 'innerRef' })} horizontal relative>
<Trigger {...getButtonProps()} tabIndex={0} {...props}> <Trigger {...getToggleButtonProps()} tabIndex={0} {...props}>
{children} {children}
</Trigger> </Trigger>
{isOpen && this.renderItems(items, selectedItem, downshiftProps)} {isOpen && this.renderItems(items, selectedItem, downshiftProps)}

48
src/components/base/InputCurrency/index.js

@ -1,13 +1,15 @@
// @flow // @flow
import React, { PureComponent } from 'react' import React, { PureComponent } from 'react'
import styled from 'styled-components'
import { parseCurrencyUnit, formatCurrencyUnit } from '@ledgerhq/currencies' import { parseCurrencyUnit, formatCurrencyUnit } from '@ledgerhq/currencies'
import noop from 'lodash/noop' import noop from 'lodash/noop'
import isNaN from 'lodash/isNaN' import isNaN from 'lodash/isNaN'
import Box from 'components/base/Box'
import Input from 'components/base/Input' import Input from 'components/base/Input'
import Select from 'components/base/Select'
import type { Unit } from '@ledgerhq/currencies' import type { Unit } from '@ledgerhq/currencies'
@ -35,12 +37,20 @@ function unformat(unit, value) {
return v return v
} }
const Currencies = styled(Box)`
position: relative;
top: -1px;
right: -1px;
`
type Value = string | number type Value = string | number
type Props = { type Props = {
onChange: Function, onChange: Function,
value: Value, renderRight: any,
unit: Unit, unit: Unit,
units: Array<Unit>,
value: Value,
} }
type State = { type State = {
@ -51,6 +61,8 @@ type State = {
class InputCurrency extends PureComponent<Props, State> { class InputCurrency extends PureComponent<Props, State> {
static defaultProps = { static defaultProps = {
onChange: noop, onChange: noop,
renderRight: null,
units: [],
value: 0, value: 0,
} }
@ -105,15 +117,42 @@ class InputCurrency extends PureComponent<Props, State> {
} }
emitOnChange = (v: Value) => { emitOnChange = (v: Value) => {
const { onChange } = this.props const { onChange, unit } = this.props
const { value } = this.state const { value } = this.state
if (value.toString() !== v.toString()) { if (value.toString() !== v.toString()) {
onChange(v.toString()) onChange(v.toString(), unit)
}
}
renderListUnits = () => {
const { unit, units, onChange } = this.props
const { value } = this.state
if (units.length <= 1) {
return null
} }
const renderItem = item => item.code
return (
<Currencies onClick={e => e.stopPropagation()}>
<Select
bg="lightGraphite"
keyProp="code"
flatLeft
onChange={item => onChange(unformat(item, value), item)}
items={units}
value={unit}
renderItem={renderItem}
renderSelected={renderItem}
/>
</Currencies>
)
} }
render() { render() {
const { renderRight } = this.props
const { value } = this.state const { value } = this.state
return ( return (
@ -124,6 +163,7 @@ class InputCurrency extends PureComponent<Props, State> {
onChange={this.handleChange} onChange={this.handleChange}
onFocus={this.handleFocus} onFocus={this.handleFocus}
onBlur={this.handleBlur} onBlur={this.handleBlur}
renderRight={renderRight || this.renderListUnits()}
/> />
) )
} }

43
src/components/base/InputCurrency/stories.js

@ -1,15 +1,46 @@
// @flow // @flow
import React from 'react' import React, { Component } from 'react'
import { storiesOf } from '@storybook/react' import { storiesOf } from '@storybook/react'
import { action } from '@storybook/addon-actions'
import { getDefaultUnitByCoinType } from '@ledgerhq/currencies' import { getDefaultUnitByCoinType, getFiatUnit } from '@ledgerhq/currencies'
import InputCurrency from 'components/base/InputCurrency' import InputCurrency from 'components/base/InputCurrency'
const stories = storiesOf('Components/base', module) const stories = storiesOf('Components', module)
const unit = getDefaultUnitByCoinType(1) const units = [
getDefaultUnitByCoinType(1),
getDefaultUnitByCoinType(2),
getDefaultUnitByCoinType(3),
getDefaultUnitByCoinType(6),
getFiatUnit('USD'),
]
stories.add('InputCurrency', () => <InputCurrency unit={unit} onChange={action('onChange')} />) class Wrapper extends Component<any, any> {
state = {
value: 0,
unit: units[0],
}
handleChange = (value, unit) => this.setState({ value, unit })
render() {
const { render } = this.props
const { value, unit } = this.state
return render({
onChange: this.handleChange,
unit,
value,
})
}
}
stories.add('InputCurrency', () => (
<Wrapper
render={({ value, unit, onChange }) => (
<InputCurrency value={value} unit={unit} units={units} onChange={onChange} />
)}
/>
))

32
src/components/base/Select/index.js

@ -17,6 +17,9 @@ import IconCheck from 'icons/Check'
import IconAngleDown from 'icons/AngleDown' import IconAngleDown from 'icons/AngleDown'
type Props = { type Props = {
bg?: string,
flatLeft?: boolean,
flatRight?: boolean,
fuseOptions?: Object, fuseOptions?: Object,
highlight?: boolean, highlight?: boolean,
items: Array<any>, items: Array<any>,
@ -40,15 +43,18 @@ const TriggerBtn = styled(Box).attrs({
pl: 3, pl: 3,
pr: 5, pr: 5,
})` })`
height: 40px;
${space}; ${space};
height: 40px;
background: ${p => p.bg || p.theme.colors.white};
border-bottom-left-radius: ${p => (p.flatLeft ? 0 : p.theme.radii[1])}px;
border-bottom-right-radius: ${p => (p.flatRight ? 0 : p.theme.radii[1])}px;
border-top-left-radius: ${p => (p.flatLeft ? 0 : p.theme.radii[1])}px;
border-top-right-radius: ${p => (p.flatRight ? 0 : p.theme.radii[1])}px;
border: 1px solid ${p => p.theme.colors.fog}; border: 1px solid ${p => p.theme.colors.fog};
border-radius: 3px;
display: flex;
width: 100%;
color: ${p => p.theme.colors.graphite}; color: ${p => p.theme.colors.graphite};
background: ${p => p.theme.colors.white};
cursor: pointer; cursor: pointer;
display: flex;
width: 100%;
&:focus { &:focus {
outline: none; outline: none;
box-shadow: rgba(0, 0, 0, 0.05) 0 2px 2px; box-shadow: rgba(0, 0, 0, 0.05) 0 2px 2px;
@ -103,6 +109,9 @@ const IconSelected = styled(Box).attrs({
class Select extends PureComponent<Props> { class Select extends PureComponent<Props> {
static defaultProps = { static defaultProps = {
bg: undefined,
flatLeft: false,
flatRight: false,
itemToString: (item: Object) => item && item.name, itemToString: (item: Object) => item && item.name,
keyProp: undefined, keyProp: undefined,
maxHeight: 300, maxHeight: 300,
@ -181,6 +190,8 @@ class Select extends PureComponent<Props> {
render() { render() {
const { const {
flatLeft,
flatRight,
items, items,
searchable, searchable,
itemToString, itemToString,
@ -201,7 +212,7 @@ class Select extends PureComponent<Props> {
onChange={onChange} onChange={onChange}
render={({ render={({
getInputProps, getInputProps,
getButtonProps, getToggleButtonProps,
getRootProps, getRootProps,
isOpen, isOpen,
inputValue, inputValue,
@ -229,11 +240,14 @@ class Select extends PureComponent<Props> {
</Box> </Box>
) : ( ) : (
<TriggerBtn <TriggerBtn
{...getButtonProps()} {...getToggleButtonProps()}
tabIndex={0} bg={props.bg}
horizontal
alignItems="center" alignItems="center"
flatLeft={flatLeft}
flatRight={flatRight}
flow={2} flow={2}
horizontal
tabIndex={0}
> >
<Box grow> <Box grow>
{selectedItem && renderSelected ? ( {selectedItem && renderSelected ? (

75
src/components/modals/Send/01-step-amount.js

@ -2,45 +2,47 @@
import React, { Fragment } from 'react' import React, { Fragment } from 'react'
import type { Unit } from '@ledgerhq/currencies'
import type { Account, T } from 'types/common' import type { Account, T } from 'types/common'
import type { DoubleVal } from 'components/RequestAmount' import type { DoubleVal } from 'components/RequestAmount'
import Box from 'components/base/Box' import Box from 'components/base/Box'
import SelectAccount from 'components/SelectAccount' import CheckBox from 'components/base/CheckBox'
import { Textarea } from 'components/base/Input'
import InputCurrency from 'components/base/InputCurrency'
import Label from 'components/base/Label' import Label from 'components/base/Label'
import LabelInfoTooltip from 'components/base/LabelInfoTooltip' import LabelInfoTooltip from 'components/base/LabelInfoTooltip'
import RecipientAddress from 'components/RecipientAddress' import RecipientAddress from 'components/RecipientAddress'
import RequestAmount from 'components/RequestAmount' import RequestAmount from 'components/RequestAmount'
import Select from 'components/base/Select' import Select from 'components/base/Select'
import Input, { Textarea } from 'components/base/Input' import SelectAccount from 'components/SelectAccount'
import Spoiler from 'components/base/Spoiler' import Spoiler from 'components/base/Spoiler'
import CheckBox from 'components/base/CheckBox'
type Props = { type PropsStepAmount = {
account: Account | null, account: Account | null,
onChange: Function, onChange: Function,
recipientAddress: string, recipientAddress: string,
amount: DoubleVal, amount: DoubleVal,
fees: {
value: number,
unit: Unit | null,
},
isRBF: boolean, isRBF: boolean,
t: T, t: T,
} }
function StepAmount(props: Props) { function StepAmount(props: PropsStepAmount) {
const { onChange, account, recipientAddress, t, amount, isRBF } = props const { onChange, fees, account, recipientAddress, t, amount, isRBF } = props
return ( return (
<Box flow={4}> <Box flow={4}>
{/* */}
{/* ACCOUNT SELECTION */} {/* ACCOUNT SELECTION */}
{/* */}
<Box flow={1}> <Box flow={1}>
<Label>{t('send:steps.amount.selectAccountDebit')}</Label> <Label>{t('send:steps.amount.selectAccountDebit')}</Label>
<SelectAccount onChange={onChange('account')} value={account} /> <SelectAccount onChange={onChange('account')} value={account} />
</Box> </Box>
{/* */}
{/* RECIPIENT ADDRESS */} {/* RECIPIENT ADDRESS */}
{/* */}
<Box flow={1}> <Box flow={1}>
<Label> <Label>
<span>{t('send:steps.amount.recipientAddress')}</span> <span>{t('send:steps.amount.recipientAddress')}</span>
@ -55,41 +57,31 @@ function StepAmount(props: Props) {
{account && ( {account && (
<Fragment> <Fragment>
{/* */}
{/* AMOUNT */} {/* AMOUNT */}
{/* */}
<Box flow={1}> <Box flow={1}>
<Label>{t('send:steps.amount.amount')}</Label> <Label>{t('send:steps.amount.amount')}</Label>
<RequestAmount account={account} onChange={onChange('amount')} value={amount} /> <RequestAmount account={account} onChange={onChange('amount')} value={amount} />
</Box> </Box>
{/* */}
{/* FEES */} {/* FEES */}
{/* */}
<Box flow={1}> <Box flow={1}>
<Label> <Label>
<span>{t('send:steps.amount.fees')}</span> <span>{t('send:steps.amount.fees')}</span>
<LabelInfoTooltip ml={1} text={t('send:steps.amount.fees')} /> <LabelInfoTooltip ml={1} text={t('send:steps.amount.fees')} />
</Label> </Label>
<Box horizontal flow={5}> <Box horizontal flow={5}>
<Select <Fees
style={{ width: 200 }} amount={fees.value}
items={[{ key: 'custom', name: 'Custom' }]} unit={fees.unit}
value={{ key: 'custom', name: 'Custom' }} account={account}
renderSelected={item => item.name} onChange={(value, unit) => onChange('fees')({ value, unit })}
onChange={onChange('fees')}
/> />
<Input containerProps={{ grow: true }} />
</Box> </Box>
</Box> </Box>
{/* */}
{/* ADVANCED OPTIONS */} {/* ADVANCED OPTIONS */}
{/* */}
<Spoiler title="Advanced options"> <Spoiler title="Advanced options">
{/* */}
{/* RBF transaction */} {/* RBF transaction */}
{/* */}
<Box horizontal align="center" flow={5}> <Box horizontal align="center" flow={5}>
<Box style={{ width: 200 }}> <Box style={{ width: 200 }}>
<Label> <Label>
@ -102,9 +94,7 @@ function StepAmount(props: Props) {
</Box> </Box>
</Box> </Box>
{/* */}
{/* Message */} {/* Message */}
{/* */}
<Box horizontal align="flex-start" flow={5}> <Box horizontal align="flex-start" flow={5}>
<Box style={{ width: 200 }}> <Box style={{ width: 200 }}>
<Label> <Label>
@ -122,4 +112,35 @@ function StepAmount(props: Props) {
) )
} }
type PropsFees = {
account: Account,
amount: number,
onChange: Function,
unit: Unit | null,
}
function Fees(props: PropsFees) {
const { onChange, account, unit, amount } = props
const { units } = account.currency
return (
<Fragment>
<Select
style={{ width: 200 }}
items={[{ key: 'custom', name: 'Custom' }]}
value={{ key: 'custom', name: 'Custom' }}
renderSelected={item => item.name}
onChange={() => onChange(amount, unit)}
/>
<InputCurrency
units={units}
unit={unit || units[0]}
containerProps={{ grow: true }}
value={amount}
onChange={onChange}
/>
</Fragment>
)
}
export default StepAmount export default StepAmount

11
src/components/modals/Send/index.js

@ -6,6 +6,7 @@ import { connect } from 'react-redux'
import { translate } from 'react-i18next' import { translate } from 'react-i18next'
import get from 'lodash/get' import get from 'lodash/get'
import type { Unit } from '@ledgerhq/currencies'
import type { T, Account } from 'types/common' import type { T, Account } from 'types/common'
import type { DoubleVal } from 'components/RequestAmount' import type { DoubleVal } from 'components/RequestAmount'
@ -41,7 +42,10 @@ type State = {
}, },
account: Account | null, account: Account | null,
recipientAddress: string, recipientAddress: string,
fees: number, fees: {
value: number,
unit: Unit | null,
},
isRBF: boolean, isRBF: boolean,
} }
@ -67,7 +71,10 @@ const INITIAL_STATE = {
right: 0, right: 0,
}, },
}, },
fees: 0, fees: {
value: 0,
unit: null,
},
isRBF: false, isRBF: false,
} }

11
src/styles/theme.js

@ -66,17 +66,18 @@ export const colors = {
pearl: '#ff0000', pearl: '#ff0000',
// new colors // new colors
identity: '#41ccb4',
wallet: '#4b84ff',
positiveGreen: '#96d071',
alertRed: '#fa4352', alertRed: '#fa4352',
black: '#000000', black: '#000000',
dark: '#1d2028', dark: '#1d2028',
smoke: '#666666', fog: '#d8d8d8',
graphite: '#767676', graphite: '#767676',
grey: '#999999', grey: '#999999',
fog: '#d8d8d8', identity: '#41ccb4',
lightGraphite: '#fafafa',
lightGrey: '#f9f9f9', lightGrey: '#f9f9f9',
positiveGreen: '#96d071',
smoke: '#666666',
wallet: '#4b84ff',
white: '#ffffff', white: '#ffffff',
} }

33
yarn.lock

@ -3560,9 +3560,9 @@ dotenv@^5.0.0, dotenv@^5.0.1:
version "5.0.1" version "5.0.1"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef"
downshift@^1.30.1: downshift@^1.31.1:
version "1.30.1" version "1.31.1"
resolved "https://registry.yarnpkg.com/downshift/-/downshift-1.30.1.tgz#b5a8d771e7a412afb982eacae36a00a320e8cdee" resolved "https://registry.yarnpkg.com/downshift/-/downshift-1.31.1.tgz#86760be5d2ceb9f322746458fc085ea0b923805c"
duplexer2@~0.1.4: duplexer2@~0.1.4:
version "0.1.4" version "0.1.4"
@ -3637,7 +3637,7 @@ electron-builder-lib@20.5.1, electron-builder-lib@~20.5.0:
semver "^5.5.0" semver "^5.5.0"
temp-file "^3.1.1" temp-file "^3.1.1"
electron-builder@^20.5.1: electron-builder@^20.0.4, electron-builder@^20.5.1:
version "20.5.1" version "20.5.1"
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.5.1.tgz#8e6fba76dcd65aeabab60f15bd46f294ee04dd11" resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.5.1.tgz#8e6fba76dcd65aeabab60f15bd46f294ee04dd11"
dependencies: dependencies:
@ -3801,7 +3801,7 @@ electron-webpack@1.13.0:
webpack-merge "^4.1.1" webpack-merge "^4.1.1"
yargs "^11.0.0" yargs "^11.0.0"
electron@1.8.4: electron@1.8.4, electron@^1.8.2:
version "1.8.4" version "1.8.4"
resolved "https://registry.yarnpkg.com/electron/-/electron-1.8.4.tgz#cca8d0e6889f238f55b414ad224f03e03b226a38" resolved "https://registry.yarnpkg.com/electron/-/electron-1.8.4.tgz#cca8d0e6889f238f55b414ad224f03e03b226a38"
dependencies: dependencies:
@ -5324,9 +5324,9 @@ i18next-node-fs-backend@^1.0.0:
js-yaml "3.5.4" js-yaml "3.5.4"
json5 "0.5.0" json5 "0.5.0"
i18next@^10.5.1: i18next@^10.6.0:
version "10.5.1" version "10.6.0"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-10.5.1.tgz#f8e1ca4e15c440ebc3a9a5c3d015c3a6d2887890" resolved "https://registry.yarnpkg.com/i18next/-/i18next-10.6.0.tgz#90ffd9f9bc617f34b9a12e037260f524445f7684"
iconv-lite@0.4, iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@^0.4.19, iconv-lite@~0.4.13: iconv-lite@0.4, iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@^0.4.19, iconv-lite@~0.4.13:
version "0.4.19" version "0.4.19"
@ -6385,6 +6385,9 @@ ledger-test-library@KhalilBellakrid/ledger-test-library-nodejs#7d37482:
dependencies: dependencies:
axios "^0.17.1" axios "^0.17.1"
bindings "^1.3.0" bindings "^1.3.0"
electron "^1.8.2"
electron-builder "^20.0.4"
electron-rebuild "^1.7.3"
nan "^2.6.2" nan "^2.6.2"
prebuild-install "^2.2.2" prebuild-install "^2.2.2"
@ -7692,9 +7695,9 @@ pngjs@^3.3.0:
version "3.3.2" version "3.3.2"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.2.tgz#097c3c2a75feb223eadddea6bc9f0050cf830bc3" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.2.tgz#097c3c2a75feb223eadddea6bc9f0050cf830bc3"
popper.js@^1.13.0: popper.js@^1.14.1:
version "1.13.0" version "1.14.1"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.13.0.tgz#e1e7ff65cc43f7cf9cf16f1510a75e81f84f4565" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.1.tgz#b8815e5cda6f62fc2042e47618649f75866e6753"
portfinder@^1.0.9: portfinder@^1.0.9:
version "1.0.13" version "1.0.13"
@ -9958,11 +9961,11 @@ tinycolor2@^1.4.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8" resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8"
tippy.js@^2.3.0: tippy.js@^2.4.0:
version "2.3.0" version "2.4.0"
resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-2.3.0.tgz#22505ce181f5049063c0201d310f4f0bfa794ce7" resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-2.4.0.tgz#a5e28b63f0c9b06c29cd65c0ac629953b673e35e"
dependencies: dependencies:
popper.js "^1.13.0" popper.js "^1.14.1"
tmp@^0.0.33: tmp@^0.0.33:
version "0.0.33" version "0.0.33"

Loading…
Cancel
Save