mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-25 15:42:24 +00:00
[add] Switch component
'Switch' on Web can support custom sizes and colors. To do so, Web-specific propTypes are introduced: `trackColor`, `thumbColor`, `activeTrackColor`, and `activeThumbColor`.
This commit is contained in:
@@ -93,6 +93,7 @@ Exported modules:
|
|||||||
* [`Image`](docs/components/Image.md)
|
* [`Image`](docs/components/Image.md)
|
||||||
* [`ListView`](docs/components/ListView.md)
|
* [`ListView`](docs/components/ListView.md)
|
||||||
* [`ScrollView`](docs/components/ScrollView.md)
|
* [`ScrollView`](docs/components/ScrollView.md)
|
||||||
|
* [`Switch`](docs/components/Switch.md)
|
||||||
* [`Text`](docs/components/Text.md)
|
* [`Text`](docs/components/Text.md)
|
||||||
* [`TextInput`](docs/components/TextInput.md)
|
* [`TextInput`](docs/components/TextInput.md)
|
||||||
* [`TouchableHighlight`](http://facebook.github.io/react-native/releases/0.22/docs/touchablehighlight.html) (mirrors React Native)
|
* [`TouchableHighlight`](http://facebook.github.io/react-native/releases/0.22/docs/touchablehighlight.html) (mirrors React Native)
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
# Switch
|
||||||
|
|
||||||
|
This is a controlled component that requires an `onValueChange` callback that
|
||||||
|
updates the value prop in order for the component to reflect user actions. If
|
||||||
|
the `value` prop is not updated, the component will continue to render the
|
||||||
|
supplied `value` prop instead of the expected result of any user actions.
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
[...View props](./View.md)
|
||||||
|
|
||||||
|
**disabled**: bool = false
|
||||||
|
|
||||||
|
If `true` the user won't be able to interact with the switch.
|
||||||
|
|
||||||
|
**onValueChange**: func
|
||||||
|
|
||||||
|
Invoked with the new value when the value changes.
|
||||||
|
|
||||||
|
**value**: bool = false
|
||||||
|
|
||||||
|
The value of the switch. If `true` the switch will be turned on.
|
||||||
|
|
||||||
|
(web) **activeThumbColor**: color = #009688
|
||||||
|
|
||||||
|
The color of the thumb grip when the switch is turned on.
|
||||||
|
|
||||||
|
(web) **activeTrackColor**: color = #A3D3CF
|
||||||
|
|
||||||
|
The color of the track when the switch is turned on.
|
||||||
|
|
||||||
|
(web) **thumbColor**: color = #FAFAFA
|
||||||
|
|
||||||
|
The color of the thumb grip when the switch is turned off.
|
||||||
|
|
||||||
|
(web) **trackColor**: color = #939393
|
||||||
|
|
||||||
|
The color of the track when the switch is turned off.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```js
|
||||||
|
import React, { Component } from 'react'
|
||||||
|
import { Switch, View } from 'react-native'
|
||||||
|
|
||||||
|
class ColorSwitchExample extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
colorTrueSwitchIsOn: true,
|
||||||
|
colorFalseSwitchIsOn: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Switch
|
||||||
|
activeThumbColor='#428BCA'
|
||||||
|
activeTrackColor='#A0C4E3'
|
||||||
|
onValueChange={(value) => this.setState({ colorFalseSwitchIsOn: value })}
|
||||||
|
value={this.state.colorFalseSwitchIsOn}
|
||||||
|
/>
|
||||||
|
<Switch
|
||||||
|
activeThumbColor='#5CB85C'
|
||||||
|
activeTrackColor='#ADDAAD'
|
||||||
|
onValueChange={(value) => this.setState({ colorTrueSwitchIsOn: value })}
|
||||||
|
thumbColor='#EBA9A7'
|
||||||
|
trackColor='#D9534F'
|
||||||
|
value={this.state.colorTrueSwitchIsOn}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
import { Platform, Switch, Text, View } from 'react-native'
|
||||||
|
import React from 'react';
|
||||||
|
import { storiesOf, action } from '@kadira/storybook';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2013-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* The examples provided by Facebook are for non-commercial testing and
|
||||||
|
* evaluation purposes only.
|
||||||
|
*
|
||||||
|
* Facebook reserves all rights not expressly granted.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
|
||||||
|
var BasicSwitchExample = React.createClass({
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
trueSwitchIsOn: true,
|
||||||
|
falseSwitchIsOn: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Switch
|
||||||
|
onValueChange={(value) => this.setState({falseSwitchIsOn: value})}
|
||||||
|
style={{marginBottom: 10}}
|
||||||
|
value={this.state.falseSwitchIsOn}
|
||||||
|
/>
|
||||||
|
<Switch
|
||||||
|
onValueChange={(value) => this.setState({trueSwitchIsOn: value})}
|
||||||
|
value={this.state.trueSwitchIsOn}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var DisabledSwitchExample = React.createClass({
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Switch
|
||||||
|
disabled={true}
|
||||||
|
style={{marginBottom: 10}}
|
||||||
|
value={true} />
|
||||||
|
<Switch
|
||||||
|
disabled={true}
|
||||||
|
value={false} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
var ColorSwitchExample = React.createClass({
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
colorTrueSwitchIsOn: true,
|
||||||
|
colorFalseSwitchIsOn: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Switch
|
||||||
|
activeThumbColor="#428bca"
|
||||||
|
activeTrackColor="#A0C4E3"
|
||||||
|
onValueChange={(value) => this.setState({colorFalseSwitchIsOn: value})}
|
||||||
|
style={{marginBottom: 10}}
|
||||||
|
value={this.state.colorFalseSwitchIsOn}
|
||||||
|
/>
|
||||||
|
<Switch
|
||||||
|
activeThumbColor="#5CB85C"
|
||||||
|
activeTrackColor="#ADDAAD"
|
||||||
|
onValueChange={(value) => this.setState({colorTrueSwitchIsOn: value})}
|
||||||
|
thumbColor="#EBA9A7"
|
||||||
|
trackColor="#D9534F"
|
||||||
|
value={this.state.colorTrueSwitchIsOn}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
var EventSwitchExample = React.createClass({
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
eventSwitchIsOn: false,
|
||||||
|
eventSwitchRegressionIsOn: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={{ flexDirection: 'row', justifyContent: 'space-around' }}>
|
||||||
|
<View>
|
||||||
|
<Switch
|
||||||
|
onValueChange={(value) => this.setState({eventSwitchIsOn: value})}
|
||||||
|
style={{marginBottom: 10}}
|
||||||
|
value={this.state.eventSwitchIsOn} />
|
||||||
|
<Switch
|
||||||
|
onValueChange={(value) => this.setState({eventSwitchIsOn: value})}
|
||||||
|
style={{marginBottom: 10}}
|
||||||
|
value={this.state.eventSwitchIsOn} />
|
||||||
|
<Text>{this.state.eventSwitchIsOn ? 'On' : 'Off'}</Text>
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
<Switch
|
||||||
|
onValueChange={(value) => this.setState({eventSwitchRegressionIsOn: value})}
|
||||||
|
style={{marginBottom: 10}}
|
||||||
|
value={this.state.eventSwitchRegressionIsOn} />
|
||||||
|
<Switch
|
||||||
|
onValueChange={(value) => this.setState({eventSwitchRegressionIsOn: value})}
|
||||||
|
style={{marginBottom: 10}}
|
||||||
|
value={this.state.eventSwitchRegressionIsOn} />
|
||||||
|
<Text>{this.state.eventSwitchRegressionIsOn ? 'On' : 'Off'}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var SizeSwitchExample = React.createClass({
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
trueSwitchIsOn: true,
|
||||||
|
falseSwitchIsOn: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Switch
|
||||||
|
onValueChange={(value) => this.setState({falseSwitchIsOn: value})}
|
||||||
|
style={{marginBottom: 10, height: '3rem' }}
|
||||||
|
value={this.state.falseSwitchIsOn}
|
||||||
|
/>
|
||||||
|
<Switch
|
||||||
|
onValueChange={(value) => this.setState({trueSwitchIsOn: value})}
|
||||||
|
style={{marginBottom: 10, width: 150 }}
|
||||||
|
value={this.state.trueSwitchIsOn}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var examples = [
|
||||||
|
{
|
||||||
|
title: 'set to true or false',
|
||||||
|
render(): ReactElement<any> { return <BasicSwitchExample />; }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'disabled',
|
||||||
|
render(): ReactElement<any> { return <DisabledSwitchExample />; }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'change events',
|
||||||
|
render(): ReactElement<any> { return <EventSwitchExample />; }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'custom colors',
|
||||||
|
render(): ReactElement<any> { return <ColorSwitchExample />; }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'custom size',
|
||||||
|
render(): ReactElement<any> { return <SizeSwitchExample />; }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'controlled component',
|
||||||
|
render(): ReactElement<any> { return <Switch />; }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
examples.forEach((example) => {
|
||||||
|
storiesOf('<Switch>', module)
|
||||||
|
.add(example.title, () => example.render())
|
||||||
|
})
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import I18nManager from '../I18nManager'
|
import I18nManager from '../I18nManager'
|
||||||
|
import multiplyStyleLengthValue from '../../modules/multiplyStyleLengthValue'
|
||||||
const CSS_UNIT_RE = /^[+-]?\d*(?:\.\d+)?(?:[Ee][+-]?\d+)?(\w*)/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of property names to their BiDi equivalent.
|
* Map of property names to their BiDi equivalent.
|
||||||
@@ -37,15 +36,7 @@ const PROPERTIES_SWAP_LTR_RTL = {
|
|||||||
/**
|
/**
|
||||||
* Invert the sign of a numeric-like value
|
* Invert the sign of a numeric-like value
|
||||||
*/
|
*/
|
||||||
const additiveInverse = (value: String | Number) => {
|
const additiveInverse = (value: String | Number) => multiplyStyleLengthValue(value, -1)
|
||||||
if (typeof value === 'string') {
|
|
||||||
const number = parseFloat(value, 10) * -1
|
|
||||||
const unit = getUnit(value)
|
|
||||||
return `${number}${unit}`
|
|
||||||
} else if (isNumeric(value)) {
|
|
||||||
return value * -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BiDi flip the given property.
|
* BiDi flip the given property.
|
||||||
@@ -65,15 +56,6 @@ const flipTransform = (transform: Object): Object => {
|
|||||||
return transform
|
return transform
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the CSS unit for string values
|
|
||||||
*/
|
|
||||||
const getUnit = (str) => str.match(CSS_UNIT_RE)[1]
|
|
||||||
|
|
||||||
const isNumeric = (n) => {
|
|
||||||
return !isNaN(parseFloat(n)) && isFinite(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
const swapLeftRight = (value:String): String => {
|
const swapLeftRight = (value:String): String => {
|
||||||
return value === 'left' ? 'right' : value === 'right' ? 'left' : value
|
return value === 'left' ? 'right' : value === 'right' ? 'left' : value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
|
||||||
|
suite('components/ActivityIndicator', () => {
|
||||||
|
test.skip('NO TEST COVERAGE', () => {})
|
||||||
|
})
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
import applyNativeMethods from '../../modules/applyNativeMethods'
|
||||||
|
import createDOMElement from '../../modules/createDOMElement'
|
||||||
|
import ColorPropType from '../../propTypes/ColorPropType'
|
||||||
|
import multiplyStyleLengthValue from '../../modules/multiplyStyleLengthValue'
|
||||||
|
import React, { Component, PropTypes } from 'react'
|
||||||
|
import StyleSheet from '../../apis/StyleSheet'
|
||||||
|
import UIManager from '../../apis/UIManager'
|
||||||
|
import View from '../View'
|
||||||
|
|
||||||
|
const thumbDefaultBoxShadow = '0px 1px 3px rgba(0,0,0,0.5)'
|
||||||
|
const thumbFocusedBoxShadow = `${thumbDefaultBoxShadow}, 0 0 0 10px rgba(0,0,0,0.1)`
|
||||||
|
|
||||||
|
class Switch extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
...View.propTypes,
|
||||||
|
activeThumbColor: ColorPropType,
|
||||||
|
activeTrackColor: ColorPropType,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
onValueChange: PropTypes.func,
|
||||||
|
thumbColor: ColorPropType,
|
||||||
|
trackColor: ColorPropType,
|
||||||
|
value: PropTypes.bool
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
activeThumbColor: '#009688',
|
||||||
|
activeTrackColor: '#A3D3CF',
|
||||||
|
disabled: false,
|
||||||
|
style: {},
|
||||||
|
thumbColor: '#FAFAFA',
|
||||||
|
trackColor: '#939393',
|
||||||
|
value: false
|
||||||
|
};
|
||||||
|
|
||||||
|
blur() {
|
||||||
|
UIManager.blur(this._checkbox)
|
||||||
|
}
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
UIManager.focus(this._checkbox)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
activeThumbColor,
|
||||||
|
activeTrackColor,
|
||||||
|
disabled,
|
||||||
|
onValueChange, // eslint-disable-line
|
||||||
|
style,
|
||||||
|
thumbColor,
|
||||||
|
trackColor,
|
||||||
|
value,
|
||||||
|
// remove any iOS-only props
|
||||||
|
onTintColor, // eslint-disable-line
|
||||||
|
thumbTintColor, // eslint-disable-line
|
||||||
|
tintColor, // eslint-disable-line
|
||||||
|
...other
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
const { height: styleHeight, width: styleWidth } = StyleSheet.flatten(style)
|
||||||
|
const height = styleHeight || 20
|
||||||
|
const minWidth = multiplyStyleLengthValue(height, 2)
|
||||||
|
const width = styleWidth > minWidth ? styleWidth : minWidth
|
||||||
|
const trackBorderRadius = multiplyStyleLengthValue(height, 0.5)
|
||||||
|
const trackCurrentColor = value ? activeTrackColor : trackColor
|
||||||
|
const thumbCurrentColor = value ? activeThumbColor : thumbColor
|
||||||
|
const thumbHeight = height
|
||||||
|
const thumbWidth = thumbHeight
|
||||||
|
|
||||||
|
const rootStyle = [
|
||||||
|
styles.root,
|
||||||
|
style,
|
||||||
|
{ height, width },
|
||||||
|
disabled && styles.cursorDefault
|
||||||
|
]
|
||||||
|
|
||||||
|
const trackStyle = [
|
||||||
|
styles.track,
|
||||||
|
{
|
||||||
|
backgroundColor: trackCurrentColor,
|
||||||
|
borderRadius: trackBorderRadius
|
||||||
|
},
|
||||||
|
disabled && styles.disabledTrack
|
||||||
|
]
|
||||||
|
|
||||||
|
const thumbStyle = [
|
||||||
|
styles.thumb,
|
||||||
|
{
|
||||||
|
alignSelf: value ? 'flex-end' : 'flex-start',
|
||||||
|
backgroundColor: thumbCurrentColor,
|
||||||
|
height: thumbHeight,
|
||||||
|
width: thumbWidth
|
||||||
|
},
|
||||||
|
disabled && styles.disabledThumb
|
||||||
|
]
|
||||||
|
|
||||||
|
const nativeControl = createDOMElement('label', {
|
||||||
|
children: createDOMElement('input', {
|
||||||
|
checked: value,
|
||||||
|
disabled: disabled,
|
||||||
|
onBlur: this._handleFocusState,
|
||||||
|
onChange: this._handleChange,
|
||||||
|
onFocus: this._handleFocusState,
|
||||||
|
ref: this._setCheckboxRef,
|
||||||
|
style: styles.cursorInherit,
|
||||||
|
type: 'checkbox'
|
||||||
|
}),
|
||||||
|
pointerEvents: 'none',
|
||||||
|
style: [ styles.nativeControl, styles.cursorInherit ]
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View {...other} style={rootStyle}>
|
||||||
|
<View style={trackStyle} />
|
||||||
|
<View ref={this._setThumbRef} style={thumbStyle} />
|
||||||
|
{nativeControl}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleChange = (event: Object) => {
|
||||||
|
const { onValueChange } = this.props
|
||||||
|
onValueChange && onValueChange(event.nativeEvent.target.checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleFocusState = (event: Object) => {
|
||||||
|
const isFocused = event.nativeEvent.type === 'focus'
|
||||||
|
const boxShadow = isFocused ? thumbFocusedBoxShadow : thumbDefaultBoxShadow
|
||||||
|
this._thumb.setNativeProps({ style: { boxShadow } })
|
||||||
|
}
|
||||||
|
|
||||||
|
_setCheckboxRef = (component) => {
|
||||||
|
this._checkbox = component
|
||||||
|
}
|
||||||
|
|
||||||
|
_setThumbRef = (component) => {
|
||||||
|
this._thumb = component
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
root: {
|
||||||
|
cursor: 'pointer',
|
||||||
|
userSelect: 'none'
|
||||||
|
},
|
||||||
|
cursorDefault: {
|
||||||
|
cursor: 'default'
|
||||||
|
},
|
||||||
|
cursorInherit: {
|
||||||
|
cursor: 'inherit'
|
||||||
|
},
|
||||||
|
track: {
|
||||||
|
...StyleSheet.absoluteFillObject,
|
||||||
|
height: '70%',
|
||||||
|
margin: 'auto',
|
||||||
|
transition: 'background-color 0.1s',
|
||||||
|
width: '90%'
|
||||||
|
},
|
||||||
|
disabledTrack: {
|
||||||
|
backgroundColor: '#D5D5D5'
|
||||||
|
},
|
||||||
|
thumb: {
|
||||||
|
borderRadius: '100%',
|
||||||
|
boxShadow: thumbDefaultBoxShadow,
|
||||||
|
transition: 'background-color 0.1s'
|
||||||
|
},
|
||||||
|
disabledThumb: {
|
||||||
|
backgroundColor: '#BDBDBD'
|
||||||
|
},
|
||||||
|
nativeControl: {
|
||||||
|
...StyleSheet.absoluteFillObject,
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = applyNativeMethods(Switch)
|
||||||
@@ -26,6 +26,7 @@ import ActivityIndicator from './components/ActivityIndicator'
|
|||||||
import Image from './components/Image'
|
import Image from './components/Image'
|
||||||
import ListView from './components/ListView'
|
import ListView from './components/ListView'
|
||||||
import ScrollView from './components/ScrollView'
|
import ScrollView from './components/ScrollView'
|
||||||
|
import Switch from './components/Switch'
|
||||||
import Text from './components/Text'
|
import Text from './components/Text'
|
||||||
import TextInput from './components/TextInput'
|
import TextInput from './components/TextInput'
|
||||||
import Touchable from './components/Touchable/Touchable'
|
import Touchable from './components/Touchable/Touchable'
|
||||||
@@ -67,6 +68,7 @@ const ReactNative = {
|
|||||||
PixelRatio,
|
PixelRatio,
|
||||||
Platform,
|
Platform,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
|
Switch,
|
||||||
UIManager,
|
UIManager,
|
||||||
Vibration,
|
Vibration,
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
|
||||||
|
import assert from 'assert'
|
||||||
|
import multiplyStyleLengthValue from '..'
|
||||||
|
|
||||||
|
suite('modules/multiplyStyleLengthValue', () => {
|
||||||
|
test('number', () => {
|
||||||
|
assert.equal(multiplyStyleLengthValue(2, -1), -2)
|
||||||
|
assert.equal(multiplyStyleLengthValue(2, 2), 4)
|
||||||
|
assert.equal(multiplyStyleLengthValue(2.5, 2), 5)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('length', () => {
|
||||||
|
assert.equal(multiplyStyleLengthValue('2rem', -1), '-2rem')
|
||||||
|
assert.equal(multiplyStyleLengthValue('2px', 2), '4px')
|
||||||
|
assert.equal(multiplyStyleLengthValue('2.5em', 2), '5em')
|
||||||
|
assert.equal(multiplyStyleLengthValue('2e3px', 2), '4000px')
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
const CSS_UNIT_RE = /^[+-]?\d*(?:\.\d+)?(?:[Ee][+-]?\d+)?(\w*)/
|
||||||
|
|
||||||
|
const getUnit = (str) => str.match(CSS_UNIT_RE)[1]
|
||||||
|
|
||||||
|
const isNumeric = (n) => {
|
||||||
|
return !isNaN(parseFloat(n)) && isFinite(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
const multiplyStyleLengthValue = (value: String | Number, multiple) => {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
const number = parseFloat(value, 10) * multiple
|
||||||
|
const unit = getUnit(value)
|
||||||
|
return `${number}${unit}`
|
||||||
|
} else if (isNumeric(value)) {
|
||||||
|
return value * multiple
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default multiplyStyleLengthValue
|
||||||
Reference in New Issue
Block a user