Compare commits

...

78 Commits

Author SHA1 Message Date
Nicolas Gallagher
f391031fb1 0.0.74 2017-02-27 14:55:34 -08:00
Matthias Le Brun
77799abf9b [fix] Touchable support for 'Enter' keypress event
Close #375
2017-02-27 14:53:27 -08:00
Nicolas Gallagher
2cfd09ecdb [fix] server-side rendering
e1fc253 added deferred image loading but didn't guard the
'requestIdleFallback' shim for use in Node.js

Fix #376
2017-02-27 14:50:29 -08:00
Nicolas Gallagher
89eea2b366 Remove unused style in 'View' 2017-02-27 14:41:47 -08:00
Nicolas Gallagher
18440158b3 Add comparative performance benchmarks
Includes a 'css-modules' implementation of the nested trees to act as a
baseline for comparison.
2017-02-26 17:19:43 -08:00
Nicolas Gallagher
24eda7c4ad 0.0.73 2017-02-24 12:35:18 -08:00
Nicolas Gallagher
44ebd8f5a3 [change] modality-specific focus styles
Remove the default focus ring when the keyboard is not being used. This
provides a superior UX when using touch or mouse.

Fix #310
2017-02-18 13:39:25 -08:00
Matthias Le Brun
a3ed8f05e6 [add] resize 'TextInput' style
Fix #363
2017-02-18 12:49:25 -08:00
Nicolas Gallagher
b653fe0bd3 [add] fontFeatureSettings 'Text' style
Fix #331
2017-02-18 12:18:28 -08:00
Nicolas Gallagher
30da226e4d Update component style docs 2017-02-18 12:07:30 -08:00
Nicolas Gallagher
f1f39bfabd 0.0.72 2017-02-18 11:34:33 -08:00
Nicolas Gallagher
267c5aab7e Allow benchmark to run in Safari
Performing teardown in a new frame was causing Safari to hang on the 2nd
benchmark run.
2017-02-18 11:34:33 -08:00
Nicolas Gallagher
fe71c7efe5 [fix] Image browser context menu
Fix #368
2017-02-18 11:34:28 -08:00
Nicolas Gallagher
eb59875bed [change] defer Image loading
x4 faster render benchmark
2017-02-18 09:46:10 -08:00
Nicolas Gallagher
e1fc253277 Add image benchmark 2017-02-18 09:46:10 -08:00
Nicolas Gallagher
40b03aca52 [change] improve 'View' render performance
1. Register the 'pointerEvents' styles to enable memoization
2. Don't flatten styles in render; move flex reset to 'expandStyle'

Reduces benchmark render times by ~10% on early 2011 MacBook Pro
2017-02-18 09:46:04 -08:00
Nicolas Gallagher
418a1a9516 [change] depend on animated@0.2.0 2017-02-17 13:28:51 -08:00
Nicolas Gallagher
8762f8e9c8 [change] depend on inline-style-prefixer@3.0.0 2017-02-17 13:28:49 -08:00
Nicolas Gallagher
10ef2bfe20 [fix] i18n styles
1. Fix auto-flipping of styles

The StyleRegistry didn't account for LTR/RTL when caching the results of
style resolution. The 'writingDirection' style is no longer flipped; no
clear use case for it.

2. Remove experimental '$noI18n' style prop suffix

This feature is essentially unused, and less likely to be used with the
introduction of 'dir=auto' on 'Text'. Removing also marginally improves
render performance.
2017-02-17 13:25:54 -08:00
Nicolas Gallagher
6d2ae4597e Update babel packages 2017-02-17 12:04:30 -08:00
Nicolas Gallagher
a34b8b149f [fix] V8 deopt in compiled 'createDOMElement'
Fixes V8 "deopt" warning: "Bad value context for arguments value".

This deopt was caused by the babel-compiled output of the ES6 argument
default value for 'rnProps':

    var t = arguments.length > 1 && void 0 !== arguments[1]
      ? arguments[1]
      : l

Not relying on ES6 default arguments avoids the function 'deopt'.
2017-02-17 10:23:59 -08:00
Nicolas Gallagher
6166024d15 [fix] NODE_ENV check in 'flattenStyle' 2017-02-17 09:59:56 -08:00
Nicolas Gallagher
701ecb7c52 0.0.71 2017-02-17 08:54:33 -08:00
Li Hau Tan
75042093c2 [fix] add 'State' static to 'TextInput'
Fix #365
Close #366
2017-02-17 08:51:22 -08:00
Nathan Tran
bb417900a9 [add] willChange style prop type
Close #367
2017-02-17 08:44:12 -08:00
Nicolas Gallagher
89e0a15d1b [fix] add 'timeStamp' to scroll and layout events 2017-02-16 08:18:56 -08:00
Nicolas Gallagher
b2e0a3702f [fix] Linking methods return promises 2017-02-11 14:13:25 -08:00
Rodrigo Moyle
a4644c204d [fix] add shadow style props to Image styles
Fix #357
Close #358
2017-02-11 11:21:45 -08:00
Nicolas Gallagher
1e9536b611 0.0.70 2017-02-06 17:15:43 -08:00
Nicolas Gallagher
d15dafc108 Build UMD bundle from source 2017-02-06 13:14:48 -08:00
Nicolas Gallagher
c9c1aab97e Rearrange propType imports 2017-02-05 16:50:06 -08:00
Nicolas Gallagher
a2903f9d30 Move TextPropTypes to TextStylePropTypes 2017-02-05 16:37:54 -08:00
Nicolas Gallagher
c7771ac64f [change] avoid 'react-dom/lib/*' where possible 2017-02-05 16:36:26 -08:00
Nicolas Gallagher
c8129c2a99 Remove NODE_ENV wrappers 2017-02-05 16:35:04 -08:00
Matthias Le Brun
b793737393 [fix] onLayout calculation
The 0.0.69 release introduced a regression in UIManager's measurement
calculations.

Using `offset` properties returns the offset relative to the closest
positioned ancestor. Make `getRect` iterate over the ancestor chain.

Fix #341
Close #345
2017-02-05 12:09:42 -08:00
Nicolas Gallagher
2a4d1c81d8 0.0.69 2017-01-28 11:01:23 -08:00
Nicolas Gallagher
a8a25d66ea [fix] measure CSS layout independent of transforms
Fix #332
2017-01-28 10:37:49 -08:00
Gethin Webster
e06d7a9650 [fix] Prevent props warnings from ScrollView in ListView 2017-01-28 10:01:16 -08:00
Nicolas Gallagher
c2501f2bc2 Add documentation for webpack@2 *.web.js resolving
Fix #334
2017-01-28 09:57:14 -08:00
Nicolas Gallagher
c51e7f1965 [fix] Linking method names
Fix #339
2017-01-28 09:50:15 -08:00
Nicolas Gallagher
dfff6b3780 [fix] StyleSheet resolving for 'number' style 2017-01-16 14:36:20 -08:00
Nicolas Gallagher
5f6b4a746a Update webpack-bundler-analyzer 2017-01-13 13:21:23 -08:00
Nicolas Gallagher
f077907dd4 Fix AppRegistry/renderApplication snapshot 2017-01-11 13:15:07 -08:00
Nicolas Gallagher
a94367bdcb 0.0.68 2017-01-11 13:12:25 -08:00
Nicolas Gallagher
65febbbc52 [fix] error in setNativeProps when no style
Close #325
Close #327
2017-01-11 13:08:10 -08:00
Nicolas Gallagher
b14d2e5bd8 [fix] CSS pointer event selectors 2017-01-11 12:47:24 -08:00
Nicolas Gallagher
7c83ba162d 0.0.67 2017-01-08 18:40:02 -08:00
Nicolas Gallagher
3ffc005a7b [fix] setNativeProps resolving logic
Since styles are set using both class names and inline styles,
'setNativeProps' needs an additional resolving step that accounts for
the pre-existing state of RN-managed styles on the DOM node.

Fix #321
2017-01-08 18:25:39 -08:00
Nicolas Gallagher
50a70ad02f 0.0.66 2017-01-07 19:05:54 -08:00
Nicolas Gallagher
768e895701 [fix] View transforms; add perspective styles
Fixes a regression introduced by
5db300df35

The `perspective` function is distinct from the `perspective` property.
This patch reverts the regression and adds support for `perspective`,
`perspectiveOrigin`, and `transformOrigin`.

Fix #208
2017-01-07 19:02:57 -08:00
Nicolas Gallagher
af5fde994d Fix yarn.lock 2017-01-07 18:25:54 -08:00
Paul Le Cam
c3d0763944 [fix] ListView imports and 'getRowAndSectionCount'
Close #316
2017-01-07 18:22:47 -08:00
Nicolas Gallagher
0aba506725 Fix UIManager tests 2017-01-07 18:18:56 -08:00
Nicolas Gallagher
91032d8565 [change] allow 'display' in ViewStylePropTypes
Fix #296
2017-01-07 18:15:16 -08:00
Nicolas Gallagher
0696721488 Document transition and animation View styles 2017-01-07 18:12:26 -08:00
Nicolas Gallagher
fe18830ce6 [change] use classList in UIManager
Prevent setting the same class multiple times
2017-01-07 18:03:51 -08:00
Nicolas Gallagher
1b86d02300 [change] wrap layout measurement in 'asap' 2017-01-07 18:03:03 -08:00
Nicolas Gallagher
c56b472258 [change] depend on normalize-css-color
Fix #308
2017-01-07 18:00:17 -08:00
Nicolas Gallagher
b00132f007 [fix] TouchableOpacity transition duration 2017-01-07 17:50:59 -08:00
Nicolas Gallagher
8b8f8f0374 [fix] CSS properties that support unitless numbers 2017-01-05 14:47:10 -08:00
Nicolas Gallagher
8e94af34e1 Remove use of 'keyOf' 2017-01-05 14:47:10 -08:00
Nicolas Gallagher
7ffaf592d5 [fix] Text automatic writing direction detection 2017-01-05 14:47:08 -08:00
Nicolas Gallagher
a1017fa785 0.0.65 2017-01-04 18:25:39 -08:00
Nicolas Gallagher
5db300df35 [fix] transform perspective resolution 2017-01-04 18:04:15 -08:00
Nicolas Gallagher
214d862e61 [add] ScrollView to Animated 2017-01-04 18:04:05 -08:00
Nicolas Gallagher
4ef5453b33 0.0.64 2017-01-04 10:58:15 -08:00
Nicolas Gallagher
a27671d7cf [fix] passing on RN style props in createDOMElement
The 'createDOMElement' function wasn't pulling 'style' out of the
props. A change to the logic that sets DOM props meant that if
'StyleRegistry.resolve' didn't return a 'style' object, the React Native
styles would be passed through to the underlying DOM node.

Fix #315
2017-01-04 10:43:19 -08:00
Nicolas Gallagher
8d2a650670 [fix] StyleSheet selector escaping
Values that contain '*' (e.g. 'calc(2 * 2)') were not properly escaped,
resulting in broken selectors.
2017-01-03 14:25:39 -08:00
Nicolas Gallagher
4cc1c983e8 0.0.63 2017-01-02 23:44:10 -08:00
Nicolas Gallagher
37413fd55f Update Text snapshot 2017-01-02 23:43:39 -08:00
Nicolas Gallagher
07ff0ea104 Use setNativeProps to update ProgressBar 2017-01-02 23:28:14 -08:00
Nicolas Gallagher
1a87657500 [fix] Switch thumb positioning 2017-01-02 23:25:15 -08:00
Nicolas Gallagher
5e4c8e520a [fix] StyleSheet registry key check 2017-01-02 23:24:24 -08:00
Nicolas Gallagher
236121e32c Add unregistered styles benchmark 2017-01-02 22:46:38 -08:00
Nicolas Gallagher
39c76ca50c Minor StyleSheet/injector refactor; small fixes 2017-01-02 15:07:05 -08:00
Nicolas Gallagher
e65f91d849 [change] simplify CSS generation 2017-01-02 13:15:38 -08:00
Nicolas Gallagher
a535c558d8 [change] Move 'onResponderRelease' cancel to 'Touchable'
Moves a fix for double-firing Touchables into 'Touchable'
2017-01-02 13:12:13 -08:00
Nicolas Gallagher
a74be91b7c Minor documentation changes 2017-01-02 11:27:46 -08:00
122 changed files with 2976 additions and 1773 deletions

7
.gitignore vendored
View File

@@ -1,4 +1,3 @@
/dist
/dist-examples
/dist-performance
/node_modules
node_modules
dist
dist-examples

View File

@@ -82,6 +82,7 @@ Exported modules:
* [`Vibration`](docs/apis/Vibration.md)
<span id="#why"></span>
## Why?
There are many different teams at Twitter building web applications with React.

View File

@@ -63,27 +63,27 @@ Lets the user select the text.
+ ...[View#style](View.md)
+ `color`
+ `fontFamily`
+ `fontFeatureSettings`
+ `fontSize`
+ `fontStyle`
+ `fontWeight`
+ `letterSpacing`
+ `lineHeight`
+ `textAlign`
+ `textAlign`
+ `textAlignVertical`
+ `textDecorationLine`
+ `textOverflow`
+ `textRendering`
+ `textOverflow`
+ `textRendering`
+ `textShadowColor`
+ `textShadowOffset`
+ `textShadowOffset`
+ `textShadowRadius`
+ `textTransform`
+ `unicodeBidi`
+ `textTransform`
+ `unicodeBidi`
+ `whiteSpace`
+ `wordWrap`
+ `writingDirection`
+ `wordWrap`
+ `writingDirection`
This property can be suffixed with `$noI18n` to prevent automatic
bidi-flipping in RTL mode. This is only supported if `Platform.OS === 'web'`.
web only.
**testID**: string

View File

@@ -144,7 +144,9 @@ If `true`, all text will automatically be selected on focus.
**style**: style
+ ...[Text#style](./Text.md)
+ `outline`
+ `resize`
‡ web only.
**testID**: string

View File

@@ -99,39 +99,48 @@ from `style`.
+ `alignContent`
+ `alignItems`
+ `alignSelf`
+ `animationDelay`
+ `animationDirection`
+ `animationDuration`
+ `animationFillMode`
+ `animationIterationCount`
+ `animationName`
+ `animationPlayState`
+ `animationTimingFunction`
+ `backfaceVisibility`
+ `backgroundAttachment`
+ `backgroundClip`
+ `backgroundAttachment`
+ `backgroundClip`
+ `backgroundColor`
+ `backgroundImage`
+ `backgroundOrigin`
+ `backgroundPosition`
+ `backgroundRepeat`
+ `backgroundSize`
+ `backgroundImage`
+ `backgroundOrigin`
+ `backgroundPosition`
+ `backgroundRepeat`
+ `backgroundSize`
+ `borderColor` (single value)
+ `borderTopColor`
+ `borderBottomColor`
+ `borderRightColor`
+ `borderLeftColor`
+ `borderRightColor`
+ `borderLeftColor`
+ `borderRadius` (single value)
+ `borderTopLeftRadius`
+ `borderTopRightRadius`
+ `borderBottomLeftRadius`
+ `borderBottomRightRadius`
+ `borderTopLeftRadius`
+ `borderTopRightRadius`
+ `borderBottomLeftRadius`
+ `borderBottomRightRadius`
+ `borderStyle` (single value)
+ `borderTopStyle`
+ `borderRightStyle`
+ `borderRightStyle`
+ `borderBottomStyle`
+ `borderLeftStyle`
+ `borderLeftStyle`
+ `borderWidth` (single value)
+ `borderBottomWidth`
+ `borderLeftWidth`
+ `borderRightWidth`
+ `borderLeftWidth`
+ `borderRightWidth`
+ `borderTopWidth`
+ `bottom`
+ `boxShadow`
+ `boxSizing`
+ `cursor`
+ `cursor`
+ `display`
+ `flex` (number)
+ `flexBasis`
+ `flexDirection`
@@ -140,12 +149,12 @@ from `style`.
+ `flexWrap`
+ `height`
+ `justifyContent`
+ `left`
+ `left`
+ `margin` (single value)
+ `marginBottom`
+ `marginHorizontal`
+ `marginLeft`
+ `marginRight`
+ `marginLeft`
+ `marginRight`
+ `marginTop`
+ `marginVertical`
+ `maxHeight`
@@ -154,27 +163,35 @@ from `style`.
+ `minWidth`
+ `opacity`
+ `order`
+ `outline`
+ `overflow`
+ `overflowX`
+ `overflowY`
+ `overflowX`
+ `overflowY`
+ `padding` (single value)
+ `paddingBottom`
+ `paddingHorizontal`
+ `paddingLeft`
+ `paddingRight`
+ `paddingLeft`
+ `paddingRight`
+ `paddingTop`
+ `paddingVertical`
+ `perspective`
+ `perspectiveOrigin`
+ `position`
+ `right`
+ `right`
+ `top`
+ `transform`
+ `userSelect`
+ `visibility`
+ `transformOrigin`
+ `transitionDelay`
+ `transitionDuration`
+ `transitionProperty`
+ `transitionTimingFunction`
+ `userSelect`
+ `visibility`
+ `width`
+ `willChange`
+ `zIndex`
This property can be suffixed with `$noI18n` to prevent automatic
bidi-flipping in RTL mode. This is only supported if `Platform.OS === 'web'`.
web only.
Default:

View File

@@ -4,7 +4,7 @@ It is sometimes necessary to make changes directly to a component without using
state/props to trigger a re-render of the entire subtree in the browser, this
is done by directly modifying a DOM node. `setNativeProps` is the React Native
equivalent to setting properties directly on a DOM node. Use direct
manipulation when frequent re-rendering creates a performance bottleneck Direct
manipulation when frequent re-rendering creates a performance bottleneck. Direct
manipulation will not be a tool that you reach for frequently.
## `setNativeProps` and `shouldComponentUpdate`

View File

@@ -4,11 +4,6 @@ To support right-to-left languages, application layout can be automatically
flipped from LTR to RTL. The `I18nManager` API can be used to help with more
fine-grained control and testing of RTL layouts.
React Native for Web provides an experimental feature to support "true left"
and "true right" styles. For example, `left` will be flipped to `right` in RTL
mode, but `left$noI18n` will not. More information is available in the `Text`
and `View` documentation.
## Working with icons and images
Icons and images that must match the LTR or RTL layout of the app need to be manually flipped.

View File

@@ -86,7 +86,19 @@ if (Platform.OS === 'web') {
```
More substantial Web-specific implementation code should be written in files
with the extension `.web.js`, which webpack will automatically resolve.
with the extension `.web.js`. Webpack@1 will automatically resolve these files.
Webpack@2 requires additional configuration.
```js
// webpack.config.js
module.exports = {
// ...
resolve: {
extensions: [ '.web.js', '.js' ]
}
};
```
## Optimizations

View File

@@ -65,6 +65,10 @@ AppRegistry.runApplication('App', {
})
```
Setting `process.env.__REACT_NATIVE_DEBUG_ENABLED__` to `true` will expose some
debugging logs. This can help track down when you're rendering without the
performance benefit of cached styles.
## Server-side rendering
Rendering using the `AppRegistry`:

View File

@@ -31,10 +31,9 @@ const styles = StyleSheet.create({
})
```
Using `StyleSheet.create` is optional but provides some key advantages: styles
are immutable in development, certain declarations are automatically converted
to CSS rather than applied as inline styles, and styles are only created once
for the application and not on every render.
Using `StyleSheet.create` is optional but provides the best performance
(`style` is resolved to CSS stylesheets). Avoid creating unregistered style
objects.
The attribute names and values are a subset of CSS. See the `style`
documentation of individual components.
@@ -56,12 +55,6 @@ A common pattern is to conditionally add style based on a condition:
styles.base,
this.state.active && styles.active
]} />
// or
<View style={{
...styles.base,
...(this.state.active && styles.active)
}} />
```
## Composing styles

View File

@@ -14,14 +14,22 @@ class I18nManagerExample extends Component {
LTR/RTL layout example!
</Text>
<Text style={styles.text}>
This is sample text. The writing direction can be changed by pressing the button below.
</Text>
<Text style={[ styles.text, styles.ltrText ]}>
This is text that will always display LTR.
The writing direction of text is automatically determined by the browser, independent of the global writing direction of the app.
</Text>
<Text style={[ styles.text, styles.rtlText ]}>
This is text that will always display RTL.
أحب اللغة العربية
</Text>
<Text style={[ styles.text, styles.textAlign ]}>
textAlign toggles
</Text>
<View style={styles.horizontal}>
<View style={[ styles.box, { backgroundColor: 'lightblue' } ]}>
<Text>One</Text>
</View>
<View style={[ styles.box ]}>
<Text>Two</Text>
</View>
</View>
<TouchableHighlight
onPress={this._handleToggle}
style={styles.toggle}
@@ -34,8 +42,8 @@ class I18nManagerExample extends Component {
}
_handleToggle = () => {
this._isRTL = !this._isRTL
I18nManager.setPreferredLanguageRTL(this._isRTL)
I18nManager.setPreferredLanguageRTL(!I18nManager.isRTL)
this.forceUpdate();
}
}
@@ -55,13 +63,16 @@ const styles = StyleSheet.create({
fontSize: 18,
marginBottom: 5
},
ltrText: {
textAlign$noI18n: 'left',
writingDirection$noI18n: 'ltr'
textAlign: {
textAlign: 'left'
},
rtlText: {
textAlign$noI18n: 'right',
writingDirection$noI18n: 'rtl'
horizontal: {
flexDirection: 'row',
marginVertical: 10
},
box: {
borderWidth: 1,
flex: 1
},
toggle: {
alignSelf: 'center',

View File

@@ -2,11 +2,19 @@ import { Linking, StyleSheet, Text, View } from 'react-native'
import React, { Component } from 'react';
import { storiesOf, action } from '@kadira/storybook';
const url = 'https://mathiasbynens.github.io/rel-noopener/malicious.html';
class LinkingExample extends Component {
handlePress() {
Linking.canOpenURL(url).then((supported) => {
return Linking.openURL(url);
});
}
render() {
return (
<View>
<Text onPress={() => { Linking.openURL('https://mathiasbynens.github.io/rel-noopener/malicious.html'); }} style={styles.text}>
<Text onPress={this.handlePress} style={styles.text}>
Linking.openURL (Expect: "The previous tab is safe and intact")
</Text>
<Text accessibilityRole='link' href='https://mathiasbynens.github.io/rel-noopener/malicious.html' style={styles.text} target='_blank'>

View File

@@ -271,7 +271,7 @@ const examples = [
<Text>
auto (default) - english LTR
</Text>
<Text style={{ writingDirection$noI18n: 'rtl' }}>
<Text>
أحب اللغة العربية auto (default) - arabic RTL
</Text>
<Text style={{textAlign: 'left'}}>

View File

@@ -113,7 +113,7 @@ var Cell = React.createClass({
case 2:
return styles.cellTextO;
default:
return {};
return null;
}
},

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-web",
"version": "0.0.62",
"version": "0.0.74",
"description": "React Native for Web",
"main": "dist/index.js",
"files": [
@@ -11,36 +11,37 @@
"scripts": {
"build": "del ./dist && mkdir dist && babel src -d dist --ignore **/__tests__",
"build:examples": "build-storybook -o dist-examples -c ./examples/.storybook",
"build:performance": "cd performance && webpack",
"build:performance": "cd performance && yarn && webpack",
"build:umd": "webpack --config webpack.config.js --sort-assets-by --progress",
"deploy:examples": "git checkout gh-pages && rm -rf ./storybook && mv dist-examples storybook && git add -A && git commit -m \"Storybook deploy\" && git push origin gh-pages && git checkout -",
"examples": "start-storybook -p 9001 -c ./examples/.storybook --dont-track",
"lint": "eslint performance src",
"lint": "eslint performance src --ignore-path .gitignore",
"prepublish": "npm run build && npm run build:umd",
"test": "npm run lint && npm run test:jest",
"test:jest": "jest",
"test:watch": "npm run test:jest -- --watch"
},
"dependencies": {
"animated": "^0.1.5",
"animated": "^0.2.0",
"array-find-index": "^1.0.2",
"asap": "^2.0.5",
"babel-runtime": "^6.20.0",
"babel-runtime": "^6.23.0",
"debounce": "^1.0.0",
"deep-assign": "^2.0.0",
"fbjs": "^0.8.8",
"inline-style-prefixer": "^2.0.5",
"inline-style-prefixer": "^3.0.0",
"normalize-css-color": "^1.0.2",
"react-dom": "~15.4.1",
"react-textarea-autosize": "^4.0.4",
"react-timer-mixin": "^0.13.3"
},
"devDependencies": {
"@kadira/storybook": "^2.5.1",
"babel-cli": "^6.14.0",
"babel-core": "^6.21.0",
"babel-cli": "^6.23.0",
"babel-core": "^6.23.1",
"babel-eslint": "^7.1.1",
"babel-loader": "^6.2.10",
"babel-plugin-transform-react-remove-prop-types": "^0.2.11",
"babel-loader": "^6.3.2",
"babel-plugin-transform-react-remove-prop-types": "^0.3.2",
"babel-preset-react-native": "^1.9.1",
"del-cli": "^0.2.1",
"enzyme": "^2.4.1",
@@ -50,14 +51,13 @@
"eslint-plugin-react": "^6.1.2",
"file-loader": "^0.9.0",
"jest": "^16.0.2",
"marky": "^1.1.1",
"node-libs-browser": "^0.5.3",
"react": "~15.4.1",
"react-addons-test-utils": "~15.4.1",
"react-test-renderer": "~15.4.1",
"url-loader": "^0.5.7",
"webpack": "^1.13.2",
"webpack-bundle-analyzer": "^1.5.3"
"webpack-bundle-analyzer": "^2.2.1"
},
"peerDependencies": {
"react": "~15.4.1"

36
performance/README.md Normal file
View File

@@ -0,0 +1,36 @@
# Performance
To run these benchmarks:
```
npm run build:performance
open ./performance/index.html
```
## Notes
The components used in the render benchmarks are simple enough to be
implemented by multiple styling libraries. The implementations are not
equivalent but are useful for framing the relative performance of
`react-native-web` against these tests.
The implementations are not equivalent. For example, the `react-native-web`
implementation of `View` does more than just styling. The
`react-native-web/lite` variant implements a minimal `View` that allows for a
more direct comparison with the `css-modules` baseline.
## Benchmark results
Typical render timings*: mean / two standard deviations
Version: 0.0.73
| Implementation | Deep tree (ms) | Wide tree (ms) |
| :--- | ---: | ---: |
| css-modules | `80.47` `±18.04` | `166.91` `±19.90` |
| react-native-web/lite | `87.91` `±13.37` | `181.45` `±20.06` |
| react-native-web | `113.45` `±09.27` | `237.33` `±38.77` |
| styled-components | `170.86` `±15.67` | `378.83` `±36.11` |
| glamor | `275.41` `±19.56` | `474.76` `±29.02` |
*MacBook Pro (13-inch, Early 2011); 2.7 GHz Intel Core i7; 16 GB 1600 MHz DDR3. Google Chrome 56.

View File

@@ -1,65 +0,0 @@
import * as marky from 'marky';
const fmt = (time) => `${Math.round(time * 100) / 100}ms`;
const measure = (name, fn) => {
marky.mark(name);
fn();
const performanceMeasure = marky.stop(name);
return performanceMeasure;
};
const benchmark = ({ name, description, setup, teardown, task, runs }) => {
return new Promise((resolve) => {
const performanceMeasures = [];
let i = 0;
setup();
const first = measure('first', task);
teardown();
const done = () => {
const mean = performanceMeasures.reduce((sum, performanceMeasure) => {
return sum + performanceMeasure.duration;
}, 0) / runs;
const firstDuration = fmt(first.duration);
const meanDuration = fmt(mean);
console.log(`First: ${firstDuration}`);
console.log(`Mean: ${meanDuration}`);
console.groupEnd();
resolve(mean);
};
const a = () => {
setup();
window.requestAnimationFrame(b);
};
const b = () => {
performanceMeasures.push(measure('mean', task));
window.requestAnimationFrame(c);
};
const c = () => {
teardown();
window.requestAnimationFrame(d);
};
const d = () => {
i += 1;
if (i < runs) {
window.requestAnimationFrame(a);
} else {
window.requestAnimationFrame(done);
}
};
console.group();
console.log(`[benchmark] ${name}: ${description}`);
window.requestAnimationFrame(a);
});
};
module.exports = benchmark;

View File

@@ -1,85 +0,0 @@
import React, { Component, PropTypes } from 'react';
const createDeepTree = ({ StyleSheet, View }) => {
class DeepTree extends Component {
static propTypes = {
breadth: PropTypes.number.isRequired,
depth: PropTypes.number.isRequired,
id: PropTypes.number.isRequired,
wrap: PropTypes.number.isRequired
};
render() {
const { breadth, depth, id, wrap } = this.props;
let result = (
<View
style={[
styles.outer,
depth % 2 === 0 ? styles.even : styles.odd,
styles[`custom${id % 3}`]
]}
>
{depth === 0 && (
<View
style={[
styles.terminal,
styles[`terminal${id % 3}`]
]}
/>
)}
{depth !== 0 && Array.from({ length: breadth }).map((el, i) => (
<DeepTree
breadth={breadth}
depth={depth - 1}
id={i}
key={i}
wrap={wrap}
/>
))}
</View>
);
for (let i = 0; i < wrap; i++) {
result = <View>{result}</View>;
}
return result;
}
}
const styles = StyleSheet.create({
outer: {
padding: 4
},
odd: {
flexDirection: 'row'
},
even: {
flexDirection: 'column'
},
custom0: {
backgroundColor: '#222'
},
custom1: {
backgroundColor: '#666'
},
custom2: {
backgroundColor: '#999'
},
terminal: {
width: 20,
height: 20
},
terminal0: {
backgroundColor: 'blue'
},
terminal1: {
backgroundColor: 'orange'
},
terminal2: {
backgroundColor: 'red'
}
});
return DeepTree;
};
module.exports = createDeepTree;

View File

@@ -1,24 +0,0 @@
import benchmark from '../../benchmark';
import createDeepTree from './createDeepTree';
import React from 'react';
import ReactDOM from 'react-dom';
import ReactNative from 'react-native';
// React Native for Web implementation of the tree
const DeepTree = createDeepTree(ReactNative);
const deepTreeBenchmark = ({ breadth, depth, wrap, runs }, node) => () => {
const setup = () => { };
const teardown = () => ReactDOM.unmountComponentAtNode(node);
return benchmark({
name: 'DeepTree',
description: `depth=${depth}, breadth=${breadth}, wrap=${wrap})`,
runs,
setup,
teardown,
task: () => ReactDOM.render(<DeepTree breadth={breadth} depth={depth} id={0} wrap={wrap} />, node)
});
};
module.exports = deepTreeBenchmark;

View File

@@ -0,0 +1,21 @@
/* eslint-disable react/prop-types */
import classnames from 'classnames';
import React from 'react';
import View from '../View';
import styles from './styles.css';
const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other }) => (
<View
{...other}
className={classnames(
styles[`color${color}`],
{
[styles.fixed]: fixed,
[styles.outer]: outer,
[styles.row]: layout === 'row'
}
)}
/>
);
module.exports = Box;

View File

@@ -0,0 +1,36 @@
.outer {
padding: 4px;
}
.row {
flex-direction: row;
}
.color0 {
background-color: #222;
}
.color1 {
background-color: #666;
}
.color2 {
background-color: #999;
}
.color3 {
background-color: blue;
}
.color4 {
background-color: orange;
}
.color5 {
background-color: red;
}
.fixed {
width: 20px;
height: 20px;
}

View File

@@ -0,0 +1,8 @@
/* eslint-disable react/prop-types */
import classnames from 'classnames';
import React from 'react';
import styles from './styles.css';
const View = (props) => <div {...props} className={classnames(styles.initial, props.className)} />;
module.exports = View;

View File

@@ -0,0 +1,21 @@
.initial {
align-items: stretch;
border-width: 0;
border-style: solid;
box-sizing: border-box;
display: flex;
flex-basis: auto;
flex-direction: column;
flex-shrink: 0;
margin: 0;
padding: 0;
position: relative;
background-color: transparent;
color: inherit;
font: inherit;
text-align: inherit;
text-decoration: none;
list-style: none;
min-height: 0;
min-width: 0;
};

View File

@@ -0,0 +1,7 @@
import Box from './Box';
import View from './View';
export default {
Box,
View
};

View File

@@ -0,0 +1,49 @@
/* eslint-disable react/prop-types */
import { css } from 'glamor';
import React from 'react';
import View from '../View';
const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other }) => (
<View
{...other}
style={[
styles[`color${color}`],
fixed && styles.fixed,
layout === 'row' && styles.row,
outer && styles.outer
]}
/>
);
const styles = {
outer: css({
padding: 4
}),
row: css({
flexDirection: 'row'
}),
color0: css({
backgroundColor: '#222'
}),
color1: css({
backgroundColor: '#666'
}),
color2: css({
backgroundColor: '#999'
}),
color3: css({
backgroundColor: 'blue'
}),
color4: css({
backgroundColor: 'orange'
}),
color5: css({
backgroundColor: 'red'
}),
fixed: css({
width: 20,
height: 20
})
};
module.exports = Box;

View File

@@ -0,0 +1,32 @@
/* eslint-disable react/prop-types */
import { css } from 'glamor';
import React from 'react';
const View = (props) => <div {...props} className={css(viewStyle, props.style)} />;
const viewStyle = {
alignItems: 'stretch',
borderWidth: 0,
borderStyle: 'solid',
boxSizing: 'border-box',
display: 'flex',
flexBasis: 'auto',
flexDirection: 'column',
flexShrink: 0,
margin: 0,
padding: 0,
position: 'relative',
// button and anchor reset
backgroundColor: 'transparent',
color: 'inherit',
font: 'inherit',
textAlign: 'inherit',
textDecorationLine: 'none',
// list reset
listStyle: 'none',
// fix flexbox bugs
minHeight: 0,
minWidth: 0
};
module.exports = View;

View File

@@ -0,0 +1,7 @@
import Box from './Box';
import View from './View';
export default {
Box,
View
};

View File

@@ -0,0 +1,49 @@
/* eslint-disable react/prop-types */
import React from 'react';
import StyleSheet from 'react-native/apis/StyleSheet';
import View from '../View';
const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other }) => (
<View
{...other}
style={[
styles[`color${color}`],
fixed && styles.fixed,
layout === 'row' && styles.row,
outer && styles.outer
]}
/>
);
const styles = StyleSheet.create({
outer: {
padding: 4
},
row: {
flexDirection: 'row'
},
color0: {
backgroundColor: '#222'
},
color1: {
backgroundColor: '#666'
},
color2: {
backgroundColor: '#999'
},
color3: {
backgroundColor: 'blue'
},
color4: {
backgroundColor: 'orange'
},
color5: {
backgroundColor: 'red'
},
fixed: {
width: 20,
height: 20
}
});
module.exports = Box;

View File

@@ -0,0 +1,49 @@
/* eslint-disable react/prop-types */
import React from 'react';
import StyleSheet from 'react-native/apis/StyleSheet';
import View from '../View/lite';
const Box = ({ color, fixed = false, layout = 'column', outer = false, ...other }) => (
<View
{...other}
style={[
styles[`color${color}`],
fixed && styles.fixed,
layout === 'row' && styles.row,
outer && styles.outer
]}
/>
);
const styles = StyleSheet.create({
outer: {
padding: 4
},
row: {
flexDirection: 'row'
},
color0: {
backgroundColor: '#222'
},
color1: {
backgroundColor: '#666'
},
color2: {
backgroundColor: '#999'
},
color3: {
backgroundColor: 'blue'
},
color4: {
backgroundColor: 'orange'
},
color5: {
backgroundColor: 'red'
},
fixed: {
width: 20,
height: 20
}
});
module.exports = Box;

View File

@@ -0,0 +1,2 @@
import View from 'react-native/components/View';
export default View;

View File

@@ -0,0 +1,32 @@
import createDOMElement from 'react-native/modules/createDOMElement';
import StyleSheet from 'react-native/apis/StyleSheet';
const View = (props) => createDOMElement('div', { ...props, style: [ styles.initial, props.style ] });
const styles = StyleSheet.create({
initial: {
alignItems: 'stretch',
borderWidth: 0,
borderStyle: 'solid',
boxSizing: 'border-box',
display: 'flex',
flexBasis: 'auto',
flexDirection: 'column',
margin: 0,
padding: 0,
position: 'relative',
// button and anchor reset
backgroundColor: 'transparent',
color: 'inherit',
font: 'inherit',
textAlign: 'inherit',
textDecorationLine: 'none',
// list reset
listStyle: 'none',
// fix flexbox bugs
minHeight: 0,
minWidth: 0
}
});
module.exports = View;

View File

@@ -0,0 +1,7 @@
import Box from './Box';
import View from './View';
export default {
Box,
View
};

View File

@@ -0,0 +1,7 @@
import Box from './Box/lite';
import View from './View/lite';
export default {
Box,
View
};

View File

@@ -0,0 +1,31 @@
import styled from 'styled-components';
import View from '../View';
const getColor = (color) => {
switch (color) {
case 0:
return '#222';
case 1:
return '#666';
case 2:
return '#999';
case 3:
return 'blue';
case 4:
return 'orange';
case 5:
return 'red';
default:
return 'transparent';
}
};
const Box = styled(View)`
flex-direction: ${(props) => props.layout === 'column' ? 'column' : 'row'};
padding: ${(props) => props.outer ? '4px' : '0'};
height: ${(props) => props.fixed ? '20px' : 'auto'};
width: ${(props) => props.fixed ? '20px' : 'auto'};
background-color: ${(props) => getColor(props.color)};
`;
module.exports = Box;

View File

@@ -0,0 +1,25 @@
import styled from 'styled-components';
const View = styled.div`
align-items: stretch;
border-width: 0;
border-style: solid;
box-sizing: border-box;
display: flex;
flex-basis: auto;
flex-direction: column;
flex-shrink: 0;
margin: 0;
padding: 0;
position: relative;
background-color: transparent;
color: inherit;
font: inherit;
text-align: inherit;
text-decoration: none;
list-style: none;
min-height: 0;
min-width: 0;
`;
module.exports = View;

View File

@@ -0,0 +1,7 @@
import Box from './Box';
import View from './View';
export default {
Box,
View
};

View File

@@ -6,6 +6,6 @@
</head>
<body>
<div class="root"></div>
<script src="../dist-performance/performance.bundle.js"></script>
<script src="dist/performance.bundle.js"></script>
</body>
</html>

View File

@@ -1,11 +1,28 @@
import deepTree from './benchmarks/deepTree';
import React from 'react';
import ReactDOM from 'react-dom';
import cssModules from './implementations/css-modules';
import glamor from './implementations/glamor';
import reactNative from './implementations/react-native-web';
import reactNativeLite from './implementations/react-native-web/lite';
import styledComponents from './implementations/styled-components';
const node = document.querySelector('.root');
import renderDeepTree from './tests/renderDeepTree';
import renderWideTree from './tests/renderWideTree';
Promise.resolve()
.then(deepTree({ wrap: 4, depth: 3, breadth: 10, runs: 10 }, node))
.then(deepTree({ wrap: 1, depth: 5, breadth: 3, runs: 20 }, node))
.then(() => ReactDOM.render(<div>Complete</div>, node));
const tests = [
// deep tree
() => renderDeepTree('css-modules', cssModules),
() => renderDeepTree('react-native-web/lite', reactNativeLite),
() => renderDeepTree('react-native-web', reactNative),
() => renderDeepTree('styled-components', styledComponents),
() => renderDeepTree('glamor', glamor),
// wide tree
() => renderWideTree('css-modules', cssModules),
() => renderWideTree('react-native-web/lite', reactNativeLite),
() => renderWideTree('react-native-web', reactNative),
() => renderWideTree('styled-components', styledComponents),
() => renderWideTree('glamor', glamor)
];
// run benchmarks
tests.reduce((promise, test) => {
return promise.then(test());
}, Promise.resolve());

View File

@@ -0,0 +1,49 @@
import React, { Component, PropTypes } from 'react';
class DeepTree extends Component {
static propTypes = {
breadth: PropTypes.number.isRequired,
components: PropTypes.object,
depth: PropTypes.number.isRequired,
id: PropTypes.number.isRequired,
wrap: PropTypes.number.isRequired
};
render() {
const { breadth, components, depth, id, wrap } = this.props;
const { Box } = components;
let result = (
<Box
color={id % 3}
components={components}
layout={depth % 2 === 0 ? 'column' : 'row'}
outer
>
{depth === 0 && (
<Box
color={(id % 3) + 3}
components={components}
fixed
/>
)}
{depth !== 0 && Array.from({ length: breadth }).map((el, i) => (
<DeepTree
breadth={breadth}
components={components}
depth={depth - 1}
id={i}
key={i}
wrap={wrap}
/>
))}
</Box>
);
for (let i = 0; i < wrap; i++) {
result = <Box components={components}>{result}</Box>;
}
return result;
}
}
module.exports = DeepTree;

View File

@@ -0,0 +1,93 @@
import * as marky from 'marky';
const fmt = (time) => `${Math.round(time * 100) / 100}ms`;
const measure = (name, fn) => {
marky.mark(name);
fn();
const performanceMeasure = marky.stop(name);
return performanceMeasure.duration;
};
const mean = (values) => {
const sum = values.reduce((sum, value) => sum + value, 0);
return sum / values.length;
};
const median = (values) => {
if (!Array.isArray(values)) { return 0; }
if (values.length === 1) { return values[0]; }
const numbers = [ ...values ].sort((a, b) => a - b);
return (numbers[(numbers.length - 1) >> 1] + numbers[numbers.length >> 1]) / 2;
};
const standardDeviation = (values) => {
const avg = mean(values);
const squareDiffs = values.map((value) => {
const diff = value - avg;
return diff * diff;
});
const meanSquareDiff = mean(squareDiffs);
return Math.sqrt(meanSquareDiff);
};
const benchmark = ({ name, description, setup, teardown, task, runs }) => {
return new Promise((resolve) => {
const durations = [];
let i = 0;
setup();
const first = measure('first', task);
teardown();
const done = () => {
const stdDev = standardDeviation(durations);
const formattedFirst = fmt(first);
const formattedMean = fmt(mean(durations));
const formattedMedian = fmt(median(durations));
const formattedStdDev = fmt(stdDev);
console.groupCollapsed(`${name}\n${formattedMean} ±${fmt(2 * stdDev)}`);
description && console.log(description);
console.log(`First: ${formattedFirst}`);
console.log(`Median: ${formattedMedian}`);
console.log(`Mean: ${formattedMean}`);
console.log(`Standard deviation: ${formattedStdDev}`);
console.log(durations);
console.groupEnd();
resolve();
};
const a = () => {
setup();
window.requestAnimationFrame(b);
};
const b = () => {
const duration = measure('mean', task);
durations.push(duration);
window.requestAnimationFrame(c);
};
const c = () => {
teardown();
window.requestAnimationFrame(d);
};
const d = () => {
i += 1;
if (i < runs) {
window.requestAnimationFrame(a);
} else {
window.requestAnimationFrame(done);
}
};
window.requestAnimationFrame(a);
});
};
export default benchmark;

View File

@@ -0,0 +1,20 @@
import benchmark from './benchmark';
import ReactDOM from 'react-dom';
const node = document.querySelector('.root');
const createRenderBenchmark = ({ description, getElement, name, runs }) => () => {
const setup = () => {};
const teardown = () => ReactDOM.unmountComponentAtNode(node);
return benchmark({
name,
description,
runs,
setup,
teardown,
task: () => ReactDOM.render(getElement(), node)
});
};
export default createRenderBenchmark;

14
performance/package.json Normal file
View File

@@ -0,0 +1,14 @@
{
"name": "performance",
"private": true,
"dependencies": {
"classnames": "^2.2.5",
"glamor": "^2.20.24",
"marky": "^1.1.3",
"styled-components": "^1.4.3"
},
"devDependencies": {
"css-loader": "^0.26.2",
"style-loader": "^0.13.2"
}
}

View File

@@ -0,0 +1,21 @@
import createRenderBenchmark from '../modules/createRenderBenchmark';
import NestedTree from '../modules/NestedTree';
import React from 'react';
const renderDeepTree = (label, components) => createRenderBenchmark({
name: `Deep tree [${label}]`,
runs: 20,
getElement() {
return (
<NestedTree
breadth={3}
components={components}
depth={6}
id={0}
wrap={1}
/>
);
}
});
export default renderDeepTree;

View File

@@ -0,0 +1,21 @@
import createRenderBenchmark from '../modules/createRenderBenchmark';
import NestedTree from '../modules/NestedTree';
import React from 'react';
const renderWideTree = (label, components) => createRenderBenchmark({
name: `Wide tree [${label}]`,
runs: 20,
getElement() {
return (
<NestedTree
breadth={10}
components={components}
depth={3}
id={0}
wrap={4}
/>
);
}
});
export default renderWideTree;

View File

@@ -1,17 +1,20 @@
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const path = require('path');
const webpack = require('webpack');
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
entry: {
performance: './index'
},
context: __dirname,
entry: './index',
output: {
path: path.resolve(__dirname, '../dist-performance'),
path: path.resolve(__dirname, 'dist'),
filename: 'performance.bundle.js'
},
module: {
loaders: [
{
test: /\.css$/,
loader: 'style-loader!css-loader?module&localIdentName=[hash:base64:8]'
},
{
test: /\.js$/,
exclude: /node_modules/,
@@ -21,13 +24,12 @@ module.exports = {
]
},
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false
}),
new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }),
new webpack.optimize.DedupePlugin(),
// https://github.com/animatedjs/animated/issues/40
new webpack.NormalModuleReplacementPlugin(
/es6-set/,
path.join(__dirname, '../src/modules/polyfills/Set.js')
),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: {

970
performance/yarn.lock Normal file
View File

@@ -0,0 +1,970 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
alphanum-sort@^1.0.1, alphanum-sort@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
argparse@^1.0.7:
version "1.0.9"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
dependencies:
sprintf-js "~1.0.2"
asap@~2.0.3:
version "2.0.5"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"
autoprefixer@^6.3.1:
version "6.7.5"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.5.tgz#50848f39dc08730091d9495023487e7cc21f518d"
dependencies:
browserslist "^1.7.5"
caniuse-db "^1.0.30000624"
normalize-range "^0.1.2"
num2fraction "^1.2.2"
postcss "^5.2.15"
postcss-value-parser "^3.2.3"
babel-code-frame@^6.11.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
dependencies:
chalk "^1.1.0"
esutils "^2.0.2"
js-tokens "^3.0.0"
babel-runtime@^6.18.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b"
dependencies:
core-js "^2.4.0"
regenerator-runtime "^0.10.0"
balanced-match@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
base64-js@^1.0.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.0.tgz#a39992d723584811982be5e290bb6a53d86700f1"
big.js@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.1.3.tgz#4cada2193652eb3ca9ec8e55c9015669c9806978"
bowser@^1.0.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.6.0.tgz#37fc387b616cb6aef370dab4d6bd402b74c5c54d"
browserslist@^1.0.1, browserslist@^1.5.2, browserslist@^1.7.5:
version "1.7.5"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.5.tgz#eca4713897b51e444283241facf3985de49a9e2b"
dependencies:
caniuse-db "^1.0.30000624"
electron-to-chromium "^1.2.3"
buffer@^5.0.2:
version "5.0.5"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.5.tgz#35c9393244a90aff83581063d16f0882cecc9418"
dependencies:
base64-js "^1.0.2"
ieee754 "^1.1.4"
caniuse-api@^1.5.2:
version "1.5.3"
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.5.3.tgz#5018e674b51c393e4d50614275dc017e27c4a2a2"
dependencies:
browserslist "^1.0.1"
caniuse-db "^1.0.30000346"
lodash.memoize "^4.1.0"
lodash.uniq "^4.3.0"
caniuse-db@^1.0.30000346, caniuse-db@^1.0.30000624:
version "1.0.30000628"
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000628.tgz#3d010e2a8e2537a8d135792e90e4f2ce0eb838cc"
chalk@^1.1.0, chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
dependencies:
ansi-styles "^2.2.1"
escape-string-regexp "^1.0.2"
has-ansi "^2.0.0"
strip-ansi "^3.0.0"
supports-color "^2.0.0"
clap@^1.0.9:
version "1.1.2"
resolved "https://registry.yarnpkg.com/clap/-/clap-1.1.2.tgz#316545bf22229225a2cecaa6824cd2f56a9709ed"
dependencies:
chalk "^1.1.3"
classnames@^2.2.5:
version "2.2.5"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
clone@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149"
coa@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.1.tgz#7f959346cfc8719e3f7233cd6852854a7c67d8a3"
dependencies:
q "^1.1.2"
color-convert@^1.3.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a"
dependencies:
color-name "^1.1.1"
color-name@^1.0.0, color-name@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689"
color-string@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991"
dependencies:
color-name "^1.0.0"
color@^0.11.0:
version "0.11.4"
resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764"
dependencies:
clone "^1.0.2"
color-convert "^1.3.0"
color-string "^0.3.0"
colormin@^1.0.5:
version "1.1.2"
resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133"
dependencies:
color "^0.11.0"
css-color-names "0.0.4"
has "^1.0.1"
colors@0.5.x:
version "0.5.1"
resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774"
colors@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
core-js@^2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
css-color-list@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/css-color-list/-/css-color-list-0.0.1.tgz#8718e8695ae7a2cc8787be8715f1c008a7f28b15"
dependencies:
css-color-names "0.0.1"
css-color-names@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.1.tgz#5d0548fa256456ede4a9a0c2ac7ab19d3eb1ad81"
css-color-names@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
css-loader@^0.26.2:
version "0.26.2"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.26.2.tgz#a9cd4c2b1a559b45d8efc04fc311ab5d2aaccb9d"
dependencies:
babel-code-frame "^6.11.0"
css-selector-tokenizer "^0.7.0"
cssnano ">=2.6.1 <4"
loader-utils "^1.0.2"
lodash.camelcase "^4.3.0"
object-assign "^4.0.1"
postcss "^5.0.6"
postcss-modules-extract-imports "^1.0.0"
postcss-modules-local-by-default "^1.0.1"
postcss-modules-scope "^1.0.0"
postcss-modules-values "^1.1.0"
source-list-map "^0.1.7"
css-selector-tokenizer@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.6.0.tgz#6445f582c7930d241dcc5007a43d6fcb8f073152"
dependencies:
cssesc "^0.1.0"
fastparse "^1.1.1"
regexpu-core "^1.0.0"
css-selector-tokenizer@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86"
dependencies:
cssesc "^0.1.0"
fastparse "^1.1.1"
regexpu-core "^1.0.0"
css-to-react-native@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-1.0.6.tgz#728c7e774e56536558a0ecaa990d9507c43a4ac4"
dependencies:
css-color-list "0.0.1"
fbjs "^0.8.5"
nearley "^2.7.7"
cssesc@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
"cssnano@>=2.6.1 <4":
version "3.10.0"
resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38"
dependencies:
autoprefixer "^6.3.1"
decamelize "^1.1.2"
defined "^1.0.0"
has "^1.0.1"
object-assign "^4.0.1"
postcss "^5.0.14"
postcss-calc "^5.2.0"
postcss-colormin "^2.1.8"
postcss-convert-values "^2.3.4"
postcss-discard-comments "^2.0.4"
postcss-discard-duplicates "^2.0.1"
postcss-discard-empty "^2.0.1"
postcss-discard-overridden "^0.1.1"
postcss-discard-unused "^2.2.1"
postcss-filter-plugins "^2.0.0"
postcss-merge-idents "^2.1.5"
postcss-merge-longhand "^2.0.1"
postcss-merge-rules "^2.0.3"
postcss-minify-font-values "^1.0.2"
postcss-minify-gradients "^1.0.1"
postcss-minify-params "^1.0.4"
postcss-minify-selectors "^2.0.4"
postcss-normalize-charset "^1.1.0"
postcss-normalize-url "^3.0.7"
postcss-ordered-values "^2.1.0"
postcss-reduce-idents "^2.2.2"
postcss-reduce-initial "^1.0.0"
postcss-reduce-transforms "^1.0.3"
postcss-svgo "^2.1.1"
postcss-unique-selectors "^2.0.2"
postcss-value-parser "^3.2.3"
postcss-zindex "^2.0.1"
csso@~2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.1.tgz#4f8d91a156f2f1c2aebb40b8fb1b5eb83d94d3b9"
dependencies:
clap "^1.0.9"
source-map "^0.5.3"
decamelize@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
defined@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
discontinuous-range@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
electron-to-chromium@^1.2.3:
version "1.2.4"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.2.4.tgz#9751cbea89fa120bf88c226ba41eb8d0b6f1b597"
emojis-list@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
encoding@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
dependencies:
iconv-lite "~0.4.13"
escape-string-regexp@^1.0.2:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
esprima@^2.6.0:
version "2.7.3"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
fastparse@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"
fbjs@^0.8.5, fbjs@^0.8.7, fbjs@^0.8.8:
version "0.8.9"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.9.tgz#180247fbd347dcc9004517b904f865400a0c8f14"
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"
flatten@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
function-bind@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
glamor@^2.20.12, glamor@^2.20.24:
version "2.20.24"
resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.24.tgz#a299af2eec687322634ba38e4a0854d8743d2041"
dependencies:
babel-runtime "^6.18.0"
fbjs "^0.8.8"
object-assign "^4.1.0"
has-ansi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
dependencies:
ansi-regex "^2.0.0"
has-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
has@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
dependencies:
function-bind "^1.0.2"
html-comment-regex@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e"
hyphenate-style-name@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b"
iconv-lite@~0.4.13:
version "0.4.15"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
icss-replace-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.0.2.tgz#cb0b6054eb3af6edc9ab1d62d01933e2d4c8bfa5"
ieee754@^1.1.4:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
indexes-of@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
inline-style-prefixer@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz#c153c7e88fd84fef5c602e95a8168b2770671fe7"
dependencies:
bowser "^1.0.0"
hyphenate-style-name "^1.0.1"
is-absolute-url@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
is-function@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5"
is-plain-obj@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
is-plain-object@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.1.tgz#4d7ca539bc9db9b737b8acb612f2318ef92f294f"
dependencies:
isobject "^1.0.0"
is-stream@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
is-svg@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9"
dependencies:
html-comment-regex "^1.1.0"
isobject@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/isobject/-/isobject-1.0.2.tgz#f0f9b8ce92dd540fa0740882e3835a2e022ec78a"
isomorphic-fetch@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
dependencies:
node-fetch "^1.0.1"
whatwg-fetch ">=0.10.0"
js-base64@^2.1.9:
version "2.1.9"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce"
js-tokens@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
js-yaml@~3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
dependencies:
argparse "^1.0.7"
esprima "^2.6.0"
jsesc@~0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
json5@^0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
loader-utils@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.0.2.tgz#a9f923c865a974623391a8602d031137fad74830"
dependencies:
big.js "^3.1.3"
emojis-list "^2.0.0"
json5 "^0.5.0"
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
lodash.memoize@^4.1.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
lodash.uniq@^4.3.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
loose-envify@^1.0.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
dependencies:
js-tokens "^3.0.0"
macaddress@^0.2.8:
version "0.2.8"
resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12"
marky@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/marky/-/marky-1.1.3.tgz#b5b914c661f73355862a77acf21aadfc60745e37"
math-expression-evaluator@^1.2.14:
version "1.2.16"
resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.16.tgz#b357fa1ca9faefb8e48d10c14ef2bcb2d9f0a7c9"
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
mkdirp@~0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
dependencies:
minimist "0.0.8"
nearley@^2.7.7:
version "2.7.13"
resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.7.13.tgz#ae19927cc821a4b517de91962db9ed0e90d991fa"
dependencies:
nomnom "~1.6.2"
railroad-diagrams "^1.0.0"
randexp "^0.4.2"
node-fetch@^1.0.1:
version "1.6.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
dependencies:
encoding "^0.1.11"
is-stream "^1.0.1"
nomnom@~1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.6.2.tgz#84a66a260174408fc5b77a18f888eccc44fb6971"
dependencies:
colors "0.5.x"
underscore "~1.4.4"
normalize-range@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
normalize-url@^1.4.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.0.tgz#c2bb50035edee62cd81edb2d45da68dc25e3423e"
dependencies:
object-assign "^4.0.1"
prepend-http "^1.0.0"
query-string "^4.1.0"
sort-keys "^1.0.0"
num2fraction@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
object-assign@^4.0.1, object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
postcss-calc@^5.2.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e"
dependencies:
postcss "^5.0.2"
postcss-message-helpers "^2.0.0"
reduce-css-calc "^1.2.6"
postcss-colormin@^2.1.8:
version "2.2.2"
resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b"
dependencies:
colormin "^1.0.5"
postcss "^5.0.13"
postcss-value-parser "^3.2.3"
postcss-convert-values@^2.3.4:
version "2.6.1"
resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d"
dependencies:
postcss "^5.0.11"
postcss-value-parser "^3.1.2"
postcss-discard-comments@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d"
dependencies:
postcss "^5.0.14"
postcss-discard-duplicates@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.0.2.tgz#02be520e91571ffb10738766a981d5770989bb32"
dependencies:
postcss "^5.0.4"
postcss-discard-empty@^2.0.1:
version "2.1.0"
resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5"
dependencies:
postcss "^5.0.14"
postcss-discard-overridden@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58"
dependencies:
postcss "^5.0.16"
postcss-discard-unused@^2.2.1:
version "2.2.3"
resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433"
dependencies:
postcss "^5.0.14"
uniqs "^2.0.0"
postcss-filter-plugins@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz#6d85862534d735ac420e4a85806e1f5d4286d84c"
dependencies:
postcss "^5.0.4"
uniqid "^4.0.0"
postcss-merge-idents@^2.1.5:
version "2.1.7"
resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270"
dependencies:
has "^1.0.1"
postcss "^5.0.10"
postcss-value-parser "^3.1.1"
postcss-merge-longhand@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658"
dependencies:
postcss "^5.0.4"
postcss-merge-rules@^2.0.3:
version "2.1.2"
resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721"
dependencies:
browserslist "^1.5.2"
caniuse-api "^1.5.2"
postcss "^5.0.4"
postcss-selector-parser "^2.2.2"
vendors "^1.0.0"
postcss-message-helpers@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e"
postcss-minify-font-values@^1.0.2:
version "1.0.5"
resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69"
dependencies:
object-assign "^4.0.1"
postcss "^5.0.4"
postcss-value-parser "^3.0.2"
postcss-minify-gradients@^1.0.1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1"
dependencies:
postcss "^5.0.12"
postcss-value-parser "^3.3.0"
postcss-minify-params@^1.0.4:
version "1.2.2"
resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3"
dependencies:
alphanum-sort "^1.0.1"
postcss "^5.0.2"
postcss-value-parser "^3.0.2"
uniqs "^2.0.0"
postcss-minify-selectors@^2.0.4:
version "2.1.1"
resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf"
dependencies:
alphanum-sort "^1.0.2"
has "^1.0.1"
postcss "^5.0.14"
postcss-selector-parser "^2.0.0"
postcss-modules-extract-imports@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.0.1.tgz#8fb3fef9a6dd0420d3f6d4353cf1ff73f2b2a341"
dependencies:
postcss "^5.0.4"
postcss-modules-local-by-default@^1.0.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.1.1.tgz#29a10673fa37d19251265ca2ba3150d9040eb4ce"
dependencies:
css-selector-tokenizer "^0.6.0"
postcss "^5.0.4"
postcss-modules-scope@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.0.2.tgz#ff977395e5e06202d7362290b88b1e8cd049de29"
dependencies:
css-selector-tokenizer "^0.6.0"
postcss "^5.0.4"
postcss-modules-values@^1.1.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.2.2.tgz#f0e7d476fe1ed88c5e4c7f97533a3e772ad94ca1"
dependencies:
icss-replace-symbols "^1.0.2"
postcss "^5.0.14"
postcss-normalize-charset@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1"
dependencies:
postcss "^5.0.5"
postcss-normalize-url@^3.0.7:
version "3.0.8"
resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222"
dependencies:
is-absolute-url "^2.0.0"
normalize-url "^1.4.0"
postcss "^5.0.14"
postcss-value-parser "^3.2.3"
postcss-ordered-values@^2.1.0:
version "2.2.3"
resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d"
dependencies:
postcss "^5.0.4"
postcss-value-parser "^3.0.1"
postcss-reduce-idents@^2.2.2:
version "2.4.0"
resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3"
dependencies:
postcss "^5.0.4"
postcss-value-parser "^3.0.2"
postcss-reduce-initial@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea"
dependencies:
postcss "^5.0.4"
postcss-reduce-transforms@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1"
dependencies:
has "^1.0.1"
postcss "^5.0.8"
postcss-value-parser "^3.0.1"
postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2:
version "2.2.3"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90"
dependencies:
flatten "^1.0.2"
indexes-of "^1.0.1"
uniq "^1.0.1"
postcss-svgo@^2.1.1:
version "2.1.6"
resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d"
dependencies:
is-svg "^2.0.0"
postcss "^5.0.14"
postcss-value-parser "^3.2.3"
svgo "^0.7.0"
postcss-unique-selectors@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d"
dependencies:
alphanum-sort "^1.0.1"
postcss "^5.0.4"
uniqs "^2.0.0"
postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15"
postcss-zindex@^2.0.1:
version "2.2.0"
resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22"
dependencies:
has "^1.0.1"
postcss "^5.0.4"
uniqs "^2.0.0"
postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.15:
version "5.2.15"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.15.tgz#a9e8685e50e06cc5b3fdea5297273246c26f5b30"
dependencies:
chalk "^1.1.3"
js-base64 "^2.1.9"
source-map "^0.5.6"
supports-color "^3.2.3"
prepend-http@^1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
promise@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf"
dependencies:
asap "~2.0.3"
q@^1.1.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e"
query-string@^4.1.0:
version "4.3.2"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.2.tgz#ec0fd765f58a50031a3968c2431386f8947a5cdd"
dependencies:
object-assign "^4.1.0"
strict-uri-encode "^1.0.0"
railroad-diagrams@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
randexp@^0.4.2:
version "0.4.4"
resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.4.tgz#ba68265f4a9f9e85f5814d34e160291f939f168e"
dependencies:
discontinuous-range "1.0.0"
ret "~0.1.10"
reduce-css-calc@^1.2.6:
version "1.3.0"
resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716"
dependencies:
balanced-match "^0.4.2"
math-expression-evaluator "^1.2.14"
reduce-function-call "^1.0.1"
reduce-function-call@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99"
dependencies:
balanced-match "^0.4.2"
regenerate@^1.2.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
regenerator-runtime@^0.10.0:
version "0.10.3"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz#8c4367a904b51ea62a908ac310bf99ff90a82a3e"
regexpu-core@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b"
dependencies:
regenerate "^1.2.1"
regjsgen "^0.2.0"
regjsparser "^0.1.4"
regjsgen@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
regjsparser@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
dependencies:
jsesc "~0.5.0"
ret@~0.1.10:
version "0.1.13"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.13.tgz#38c2702ece654978941edd8b7dfac6aeeef4067d"
sax@~1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828"
setimmediate@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
sort-keys@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
dependencies:
is-plain-obj "^1.0.0"
source-list-map@^0.1.7:
version "0.1.8"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
source-map@^0.5.3, source-map@^0.5.6:
version "0.5.6"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
strict-uri-encode@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
strip-ansi@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
dependencies:
ansi-regex "^2.0.0"
style-loader@^0.13.2:
version "0.13.2"
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.13.2.tgz#74533384cf698c7104c7951150b49717adc2f3bb"
dependencies:
loader-utils "^1.0.2"
styled-components@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-1.4.3.tgz#83fa44e553882aaa3ddc4363ccc435814d690706"
dependencies:
buffer "^5.0.2"
css-to-react-native "^1.0.6"
fbjs "^0.8.7"
glamor "^2.20.12"
inline-style-prefixer "^2.0.5"
is-function "^1.0.1"
is-plain-object "^2.0.1"
supports-color "^3.1.2"
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
supports-color@^3.1.2, supports-color@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
dependencies:
has-flag "^1.0.0"
svgo@^0.7.0:
version "0.7.2"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5"
dependencies:
coa "~1.0.1"
colors "~1.1.2"
csso "~2.3.1"
js-yaml "~3.7.0"
mkdirp "~0.5.1"
sax "~1.2.1"
whet.extend "~0.9.9"
ua-parser-js@^0.7.9:
version "0.7.12"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
underscore@~1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604"
uniq@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
uniqid@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/uniqid/-/uniqid-4.1.1.tgz#89220ddf6b751ae52b5f72484863528596bb84c1"
dependencies:
macaddress "^0.2.8"
uniqs@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02"
vendors@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22"
whatwg-fetch@>=0.10.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.2.tgz#fe294d1d89e36c5be8b3195057f2e4bc74fc980e"
whet.extend@~0.9.9:
version "0.9.9"
resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1"

View File

@@ -1,5 +1,6 @@
import Animated from 'animated';
import Image from '../../components/Image';
import ScrollView from '../../components/ScrollView';
import StyleSheet from '../StyleSheet';
import Text from '../../components/Text';
import View from '../../components/View';
@@ -9,6 +10,7 @@ Animated.inject.FlattenStyle(StyleSheet.flatten);
module.exports = {
...Animated,
Image: Animated.createAnimatedComponent(Image),
ScrollView: Animated.createAnimatedComponent(ScrollView),
Text: Animated.createAnimatedComponent(Text),
View: Animated.createAnimatedComponent(View)
};

View File

@@ -7,42 +7,46 @@ button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit-search-cancel-button,input::-webkit-search-decoration,input::-webkit-search-results-button,input::-webkit-search-results-decoration{display:none}
@keyframes rn-ActivityIndicator-animation{0%{-webkit-transform: rotate(0deg); transform: rotate(0deg);}100%{-webkit-transform: rotate(360deg); transform: rotate(360deg);}}
@keyframes rn-ProgressBar-animation{0%{-webkit-transform: translateX(-100%); transform: translateX(-100%);}100%{-webkit-transform: translateX(400%); transform: translateX(400%);}}
.rn_pointerEvents\\:auto,.rn_pointerEvents\\:box-only,.rn_pointerEvents\\:box-none *{pointer-events:auto}.rn_pointerEvents\\:none,.rn_pointerEvents\\:box-only *,.rn_pointerEvents\\:box-none{pointer-events:none}
.rn-bottom\\:0px{bottom:0px;}
.rn-left\\:0px{left:0px;}
.rn-position\\:absolute{position:absolute;}
.rn-right\\:0px{right:0px;}
.rn-top\\:0px{top:0px;}
.rn-alignItems\\:stretch{-webkit-align-items:stretch;-ms-flex-align:stretch;-webkit-box-align:stretch;align-items:stretch;}
.rn-backgroundColor\\:transparent{background-color:transparent;}
.rn-borderTopStyle\\:solid{border-top-style:solid;}
.rn-borderRightStyle\\:solid{border-right-style:solid;}
.rn-borderBottomStyle\\:solid{border-bottom-style:solid;}
.rn-borderLeftStyle\\:solid{border-left-style:solid;}
.rn-borderTopWidth\\:0px{border-top-width:0px;}
.rn-borderRightWidth\\:0px{border-right-width:0px;}
.rn-borderBottomWidth\\:0px{border-bottom-width:0px;}
.rn-borderLeftWidth\\:0px{border-left-width:0px;}
.rn-boxSizing\\:border-box{-moz-box-sizing:border-box;box-sizing:border-box;}
.rn-color\\:inherit{color:inherit;}
.rn-display\\:flex{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;}
.rn-flexBasis\\:auto{-webkit-flex-basis:auto;-ms-preferred-size:auto;flex-basis:auto;}
.rn-flexDirection\\:column{-webkit-flex-direction:column;-ms-flex-direction:column;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column;}
.rn-font\\:inherit{font:inherit;}
.rn-listStyle\\:none{list-style:none;}
.rn-marginTop\\:0px{margin-top:0px;}
.rn-marginRight\\:0px{margin-right:0px;}
.rn-marginBottom\\:0px{margin-bottom:0px;}
.rn-marginLeft\\:0px{margin-left:0px;}
.rn-minHeight\\:0px{min-height:0px;}
.rn-minWidth\\:0px{min-width:0px;}
.rn-paddingTop\\:0px{padding-top:0px;}
.rn-paddingRight\\:0px{padding-right:0px;}
.rn-paddingBottom\\:0px{padding-bottom:0px;}
.rn-paddingLeft\\:0px{padding-left:0px;}
.rn-position\\:relative{position:relative;}
.rn-textAlign\\:inherit{text-align:inherit;}
.rn-textDecoration\\:none{text-decoration:none;}
.rn-flexShrink\\:0{-webkit-flex-shrink:0px;-ms-flex-negative:0px;flex-shrink:0;}
.rn-pointerEvents\\:auto,.rn-pointerEvents\\:box-only,.rn-pointerEvents\\:box-none *{pointer-events:auto}.rn-pointerEvents\\:none,.rn-pointerEvents\\:box-only *,.rn-pointerEvents\\:box-none{pointer-events:none}
.rn-bottom\\:0px{bottom:0px}
.rn-left\\:0px{left:0px}
.rn-position\\:absolute{position:absolute}
.rn-right\\:0px{right:0px}
.rn-top\\:0px{top:0px}
.rn-alignItems\\:stretch{-webkit-align-items:stretch;-webkit-box-align:stretch;align-items:stretch}
.rn-backgroundColor\\:transparent{background-color:transparent}
.rn-borderTopStyle\\:solid{border-top-style:solid}
.rn-borderRightStyle\\:solid{border-right-style:solid}
.rn-borderBottomStyle\\:solid{border-bottom-style:solid}
.rn-borderLeftStyle\\:solid{border-left-style:solid}
.rn-borderTopWidth\\:0px{border-top-width:0px}
.rn-borderRightWidth\\:0px{border-right-width:0px}
.rn-borderBottomWidth\\:0px{border-bottom-width:0px}
.rn-borderLeftWidth\\:0px{border-left-width:0px}
.rn-boxSizing\\:border-box{box-sizing:border-box}
.rn-color\\:inherit{color:inherit}
.rn-display\\:flex{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}
.rn-flexShrink\\:0{-webkit-flex-shrink:0px;flex-shrink:0}
.rn-flexBasis\\:auto{-webkit-flex-basis:auto;flex-basis:auto}
.rn-flexDirection\\:column{-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column}
.rn-font\\:inherit{font:inherit}
.rn-listStyle\\:none{list-style:none}
.rn-marginTop\\:0px{margin-top:0px}
.rn-marginRight\\:0px{margin-right:0px}
.rn-marginBottom\\:0px{margin-bottom:0px}
.rn-marginLeft\\:0px{margin-left:0px}
.rn-minHeight\\:0px{min-height:0px}
.rn-minWidth\\:0px{min-width:0px}
.rn-paddingTop\\:0px{padding-top:0px}
.rn-paddingRight\\:0px{padding-right:0px}
.rn-paddingBottom\\:0px{padding-bottom:0px}
.rn-paddingLeft\\:0px{padding-left:0px}
.rn-position\\:relative{position:relative}
.rn-textAlign\\:inherit{text-align:inherit}
.rn-textDecoration\\:none{text-decoration:none}
.rn-pointerEvents\\:auto{pointer-events:auto}
.rn-pointerEvents\\:box-none{pointer-events:box-none}
.rn-pointerEvents\\:box-only{pointer-events:box-only}
.rn-pointerEvents\\:none{pointer-events:none}
</style>"
`;

View File

@@ -8,7 +8,7 @@
import { Component } from 'react';
import invariant from 'fbjs/lib/invariant';
import { unmountComponentAtNode } from 'react-dom/lib/ReactMount';
import { unmountComponentAtNode } from 'react-dom';
import renderApplication, { getApplication } from './renderApplication';
const emptyObject = {};

View File

@@ -1,10 +1,19 @@
const Linking = {
addEventListener() {},
removeEventListener() {},
canOpenUrl() { return true; },
getInitialUrl() { return ''; },
canOpenURL() {
return Promise.resolve(true);
},
getInitialURL() {
return Promise.resolve('');
},
openURL(url) {
iframeOpen(url);
try {
iframeOpen(url);
return Promise.resolve();
} catch (e) {
return Promise.reject(e);
}
}
};

View File

@@ -11,6 +11,7 @@ import { PropTypes } from 'react'
import ImageStylePropTypes from '../../components/Image/ImageStylePropTypes'
import ReactPropTypeLocations from 'react-dom/lib/ReactPropTypeLocations'
import ReactPropTypesSecret from 'react-dom/lib/ReactPropTypesSecret'
import TextInputStylePropTypes from '../../components/TextInput/TextInputStylePropTypes'
import TextStylePropTypes from '../../components/Text/TextStylePropTypes'
import ViewStylePropTypes from '../../components/View/ViewStylePropTypes'
import warning from 'fbjs/lib/warning'
@@ -66,16 +67,16 @@ var allStylePropTypes = {};
StyleSheetValidation.addValidStylePropTypes(ImageStylePropTypes)
StyleSheetValidation.addValidStylePropTypes(TextStylePropTypes)
StyleSheetValidation.addValidStylePropTypes(TextInputStylePropTypes)
StyleSheetValidation.addValidStylePropTypes(ViewStylePropTypes)
StyleSheetValidation.addValidStylePropTypes({
appearance: PropTypes.string,
clear: PropTypes.string,
cursor: PropTypes.string,
display: PropTypes.string,
float: PropTypes.oneOf([ 'left', 'none', 'right' ]),
font: PropTypes.string, /* @private */
listStyle: PropTypes.string,
WebkitOverflowScrolling: PropTypes.string /* @private */
pointerEvents: PropTypes.string
})
module.exports = StyleSheetValidation

View File

@@ -8,6 +8,7 @@ Object {
"borderWidthRight": "3px",
"boxShadow": "1px 1px 1px 1px #000, 1px 2px 0px rgba(255,0,0,1)",
"display": "flex",
"flexShrink": 0,
"marginBottom": "0px",
"marginTop": "0px",
"opacity": 0,

View File

@@ -1 +1 @@
exports[`apis/StyleSheet/generateCss generates correct css 1`] = `"-webkit-transition-duration:0.1s;transition-duration:0.1s;position:absolute;border-width-right:3px;border-width-left:2px;box-shadow:1px 1px 1px 1px #000;"`;
exports[`apis/StyleSheet/generateCss generates correct css 1`] = `"-webkit-transition-duration:0.1s;border-width-left:2px;border-width-right:3px;box-shadow:1px 1px 1px 1px #000;position:absolute;transition-duration:0.1s"`;

View File

@@ -21,34 +21,6 @@ Object {
"height": 10,
"width": "1rem",
},
"writingDirection": "ltr",
}
`;
exports[`apis/StyleSheet/i18nStyle LTR mode normalizes properties 1`] = `
Object {
"borderBottomLeftRadius": 20,
"borderBottomRightRadius": "2rem",
"borderLeftColor": "red",
"borderLeftStyle": "solid",
"borderLeftWidth": 5,
"borderRightColor": "blue",
"borderRightStyle": "dotted",
"borderRightWidth": 6,
"borderTopLeftRadius": 10,
"borderTopRightRadius": "1rem",
"left": 1,
"marginLeft": 7,
"marginRight": 8,
"paddingLeft": 9,
"paddingRight": 10,
"right": 2,
"textAlign": "left",
"textShadowOffset": Object {
"height": 10,
"width": "1rem",
},
"writingDirection": "ltr",
}
`;
@@ -75,33 +47,5 @@ Object {
"height": 10,
"width": "-1rem",
},
"writingDirection": "rtl",
}
`;
exports[`apis/StyleSheet/i18nStyle RTL mode normalizes properties 1`] = `
Object {
"borderBottomLeftRadius": 20,
"borderBottomRightRadius": "2rem",
"borderLeftColor": "red",
"borderLeftStyle": "solid",
"borderLeftWidth": 5,
"borderRightColor": "blue",
"borderRightStyle": "dotted",
"borderRightWidth": 6,
"borderTopLeftRadius": 10,
"borderTopRightRadius": "1rem",
"left": 1,
"marginLeft": 7,
"marginRight": 8,
"paddingLeft": 9,
"paddingRight": 10,
"right": 2,
"textAlign": "left",
"textShadowOffset": Object {
"height": 10,
"width": "-1rem",
},
"writingDirection": "ltr",
}
`;

View File

@@ -1,14 +1,14 @@
exports[`apis/StyleSheet renderToString 1`] = `
"<style id=\"react-native-stylesheet\">
.rn-borderTopColor\\:red{border-top-color:red;}
.rn-borderRightColor\\:red{border-right-color:red;}
.rn-borderBottomColor\\:red{border-bottom-color:red;}
.rn-borderLeftColor\\:red{border-left-color:red;}
.rn-borderTopWidth\\:0px{border-top-width:0px;}
.rn-borderRightWidth\\:0px{border-right-width:0px;}
.rn-borderBottomWidth\\:0px{border-bottom-width:0px;}
.rn-borderLeftWidth\\:0px{border-left-width:0px;}
.rn-left\\:50px{left:50px;}
.rn-position\\:absolute{position:absolute;}
.rn-borderTopColor\\:red{border-top-color:red}
.rn-borderRightColor\\:red{border-right-color:red}
.rn-borderBottomColor\\:red{border-bottom-color:red}
.rn-borderLeftColor\\:red{border-left-color:red}
.rn-borderTopWidth\\:0px{border-top-width:0px}
.rn-borderRightWidth\\:0px{border-right-width:0px}
.rn-borderBottomWidth\\:0px{border-bottom-width:0px}
.rn-borderLeftWidth\\:0px{border-left-width:0px}
.rn-left\\:50px{left:50px}
.rn-position\\:absolute{position:absolute}
</style>"
`;

View File

@@ -1,4 +1,4 @@
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to className 1`] = `
exports[`apis/StyleSheet/registry resolve with register, resolves to className 1`] = `
Object {
"className": "
rn-borderTopColor:red
@@ -17,7 +17,7 @@ rn-width:100px",
}
`;
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to className 2`] = `
exports[`apis/StyleSheet/registry resolve with register, resolves to className 2`] = `
Object {
"className": "
rn-borderTopColor:red
@@ -36,7 +36,7 @@ rn-width:200px",
}
`;
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to className 3`] = `
exports[`apis/StyleSheet/registry resolve with register, resolves to className 3`] = `
Object {
"className": "
rn-borderTopColor:red
@@ -55,7 +55,7 @@ rn-width:100px",
}
`;
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to mixed 1`] = `
exports[`apis/StyleSheet/registry resolve with register, resolves to mixed 1`] = `
Object {
"className": "
rn-left:50px
@@ -75,7 +75,7 @@ rn-position:absolute",
}
`;
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to mixed 2`] = `
exports[`apis/StyleSheet/registry resolve with register, resolves to mixed 2`] = `
Object {
"className": "
rn-left:50px
@@ -95,7 +95,7 @@ rn-width:200px",
}
`;
exports[`apis/StyleSheet/registry resolve with stylesheet, resolves to mixed 3`] = `
exports[`apis/StyleSheet/registry resolve with register, resolves to mixed 3`] = `
Object {
"className": "
rn-left:50px
@@ -115,7 +115,7 @@ rn-position:absolute",
}
`;
exports[`apis/StyleSheet/registry resolve without stylesheet, resolves to inline styles 1`] = `
exports[`apis/StyleSheet/registry resolve without register, resolves to inline styles 1`] = `
Object {
"className": "
",
@@ -136,7 +136,7 @@ Object {
}
`;
exports[`apis/StyleSheet/registry resolve without stylesheet, resolves to inline styles 2`] = `
exports[`apis/StyleSheet/registry resolve without register, resolves to inline styles 2`] = `
Object {
"className": "
",
@@ -157,7 +157,7 @@ Object {
}
`;
exports[`apis/StyleSheet/registry resolve without stylesheet, resolves to inline styles 3`] = `
exports[`apis/StyleSheet/registry resolve without register, resolves to inline styles 3`] = `
Object {
"className": "
",

View File

@@ -45,4 +45,21 @@ describe('apis/StyleSheet/expandStyle', () => {
expect(expandStyle(initial)).toEqual(expected);
});
test('flex', () => {
expect(expandStyle({ display: 'flex' }))
.toEqual({ display: 'flex', flexShrink: 0 });
expect(expandStyle({ display: 'flex', flex: 1 }))
.toEqual({ display: 'flex', flexGrow: 1, flexShrink: 1, flexBasis: 'auto' });
expect(expandStyle({ display: 'flex', flex: 10 }))
.toEqual({ display: 'flex', flexGrow: 10, flexShrink: 1, flexBasis: 'auto' });
expect(expandStyle({ display: 'flex', flexShrink: 1 }))
.toEqual({ display: 'flex', flexShrink: 1 });
expect(expandStyle({ display: 'flex', flex: 1, flexShrink: 2 }))
.toEqual({ display: 'flex', flexGrow: 1, flexShrink: 2, flexBasis: 'auto' });
});
});

View File

@@ -21,16 +21,9 @@ const style = {
paddingRight: 10,
right: 2,
textAlign: 'left',
textShadowOffset: { width: '1rem', height: 10 },
writingDirection: 'ltr'
textShadowOffset: { width: '1rem', height: 10 }
};
const styleNoI18n = Object.keys(style).reduce((acc, prop) => {
const newProp = `${prop}$noI18n`;
acc[newProp] = style[prop];
return acc;
}, {});
describe('apis/StyleSheet/i18nStyle', () => {
describe('LTR mode', () => {
beforeEach(() => {
@@ -44,9 +37,6 @@ describe('apis/StyleSheet/i18nStyle', () => {
test('does not auto-flip', () => {
expect(i18nStyle(style)).toMatchSnapshot();
});
test('normalizes properties', () => {
expect(i18nStyle(styleNoI18n)).toMatchSnapshot();
});
});
describe('RTL mode', () => {
@@ -61,8 +51,5 @@ describe('apis/StyleSheet/i18nStyle', () => {
test('does auto-flip', () => {
expect(i18nStyle(style)).toMatchSnapshot();
});
test('normalizes properties', () => {
expect(i18nStyle(styleNoI18n)).toMatchSnapshot();
});
});
});

View File

@@ -2,7 +2,7 @@
import injector from '../injector';
describe('apis/StyleSheet', () => {
describe('apis/StyleSheet/injector', () => {
beforeEach(() => {
document.head.insertAdjacentHTML('afterbegin', `
<style id="react-native-stylesheet">
@@ -13,10 +13,10 @@ describe('apis/StyleSheet', () => {
});
test('hydrates from SSR', () => {
const classList = injector.getAvailableClassNames();
expect(classList).toEqual([
'rn-alignItems\\:stretch',
'rn-position\\:top'
]);
const classList = injector.getClassNames();
expect(classList).toEqual({
'rn-alignItems\\:stretch': true,
'rn-position\\:top': true
});
});
});

View File

@@ -33,21 +33,21 @@ describe('apis/StyleSheet/registry', () => {
expect(resolve3).not.toEqual(resolve4);
};
test('with stylesheet, resolves to className', () => {
test('with register, resolves to className', () => {
const a = StyleRegistry.register(styleA);
const b = StyleRegistry.register(styleB);
const c = StyleRegistry.register(styleC);
testResolve(a, b, c);
});
test('with stylesheet, resolves to mixed', () => {
test('with register, resolves to mixed', () => {
const a = styleA;
const b = StyleRegistry.register(styleB);
const c = StyleRegistry.register(styleC);
testResolve(a, b, c);
});
test('without stylesheet, resolves to inline styles', () => {
test('without register, resolves to inline styles', () => {
testResolve(styleA, styleB, styleC);
});
});

View File

@@ -7,6 +7,7 @@ describe('apis/StyleSheet/resolveTransform', () => {
const resolvedStyle = {};
const style = {
transform: [
{ perspective: 50 },
{ scaleX: 20 },
{ translateX: 20 },
{ rotate: '20deg' }
@@ -15,7 +16,7 @@ describe('apis/StyleSheet/resolveTransform', () => {
resolveTransform(resolvedStyle, style);
expect(resolvedStyle).toEqual({
transform: 'scaleX(20) translateX(20px) rotate(20deg)'
transform: 'perspective(50px) scaleX(20) translateX(20px) rotate(20deg)'
});
});

View File

@@ -37,18 +37,27 @@ const alphaSortProps = (propsArray) => propsArray.sort((a, b) => {
return 0;
});
const expandStyle = (style) => {
if (!style) { return emptyObject; }
const styleProps = Object.keys(style);
const sortedStyleProps = alphaSortProps(styleProps);
const createReducer = (style, styleProps) => {
let hasResolvedBoxShadow = false;
let hasResolvedTextShadow = false;
const reducer = (resolvedStyle, prop) => {
return (resolvedStyle, prop) => {
const value = normalizeValue(prop, style[prop]);
if (value == null) { return resolvedStyle; }
switch (prop) {
case 'display': {
resolvedStyle.display = value;
// default of 'flexShrink:0' has lowest precedence
if (
style.display === 'flex' &&
style.flex == null &&
style.flexShrink == null
) {
resolvedStyle.flexShrink = 0;
}
break;
}
// ignore React Native styles
case 'elevation':
case 'resizeMode': {
@@ -105,7 +114,13 @@ const expandStyle = (style) => {
return resolvedStyle;
};
};
const expandStyle = (style) => {
if (!style) { return emptyObject; }
const styleProps = Object.keys(style);
const sortedStyleProps = alphaSortProps(styleProps);
const reducer = createReducer(style, styleProps);
const resolvedStyle = sortedStyleProps.reduce(reducer, {});
return resolvedStyle;
};

View File

@@ -24,7 +24,7 @@ function flattenStyle(style) {
return undefined;
}
if (process.env.NODE !== 'production') {
if (process.env.NODE_ENV !== 'production') {
invariant(style !== true, 'style may be false but not true');
}

View File

@@ -3,36 +3,21 @@ import mapKeyValue from '../../modules/mapKeyValue';
import normalizeValue from './normalizeValue';
import prefixAll from 'inline-style-prefixer/static';
const RE_VENDOR = /^-/;
const sortVendorPrefixes = (a, b) => {
const vendorA = RE_VENDOR.test(a);
const vendorB = RE_VENDOR.test(b);
if (vendorA && vendorB || vendorA) {
return -1;
} else {
return 1;
}
};
const mapDeclaration = (prop, val) => {
const createDeclarationString = (prop, val) => {
const name = hyphenate(prop);
const value = normalizeValue(prop, val);
if (Array.isArray(val)) {
return val.map((v) => `${name}:${v};`).join('');
return val.map((v) => `${name}:${v}`).join(';');
}
return `${name}:${value};`;
return `${name}:${value}`;
};
/**
* Generates valid CSS rule body from a JS object
*
* generateCss({ width: 20, color: 'blue' });
* // => 'width:20px;color:blue;'
* // => 'color:blue;width:20px'
*/
const generateCss = (style) => {
const prefixed = prefixAll(style);
return mapKeyValue(prefixed, mapDeclaration).sort(sortVendorPrefixes).join('');
};
const generateCss = (style) => mapKeyValue(prefixAll(style), createDeclarationString).sort().join(';');
module.exports = generateCss;

View File

@@ -31,10 +31,6 @@ const PROPERTIES_SWAP_LEFT_RIGHT = {
'textAlign': true
};
const PROPERTIES_SWAP_LTR_RTL = {
'writingDirection': true
};
/**
* Invert the sign of a numeric-like value
*/
@@ -43,7 +39,7 @@ const additiveInverse = (value: String | Number) => multiplyStyleLengthValue(val
/**
* BiDi flip the given property.
*/
const flipProperty = (prop:String): String => {
const flipProperty = (prop: String): String => {
return PROPERTIES_TO_SWAP.hasOwnProperty(prop) ? PROPERTIES_TO_SWAP[prop] : prop;
};
@@ -62,49 +58,35 @@ const swapLeftRight = (value:String): String => {
return value === 'left' ? 'right' : value === 'right' ? 'left' : value;
};
const swapLtrRtl = (value:String): String => {
return value === 'ltr' ? 'rtl' : value === 'rtl' ? 'ltr' : value;
};
const i18nStyle = (originalStyle) => {
if (!I18nManager.isRTL) {
return originalStyle;
}
const style = originalStyle || emptyObject;
const nextStyle = {};
const i18nStyle = (style = emptyObject) => {
const newStyle = {};
for (const prop in style) {
if (!Object.prototype.hasOwnProperty.call(style, prop)) {
continue;
}
const indexOfNoFlip = prop.indexOf('$noI18n');
if (I18nManager.isRTL) {
if (PROPERTIES_TO_SWAP[prop]) {
const newProp = flipProperty(prop);
newStyle[newProp] = style[prop];
} else if (PROPERTIES_SWAP_LEFT_RIGHT[prop]) {
newStyle[prop] = swapLeftRight(style[prop]);
} else if (PROPERTIES_SWAP_LTR_RTL[prop]) {
newStyle[prop] = swapLtrRtl(style[prop]);
} else if (prop === 'textShadowOffset') {
newStyle[prop] = style[prop];
newStyle[prop].width = additiveInverse(style[prop].width);
} else if (prop === 'transform') {
newStyle[prop] = style[prop].map(flipTransform);
} else if (indexOfNoFlip > -1) {
const newProp = prop.substring(0, indexOfNoFlip);
newStyle[newProp] = style[prop];
} else {
newStyle[prop] = style[prop];
}
if (PROPERTIES_TO_SWAP[prop]) {
const newProp = flipProperty(prop);
nextStyle[newProp] = style[prop];
} else if (PROPERTIES_SWAP_LEFT_RIGHT[prop]) {
nextStyle[prop] = swapLeftRight(style[prop]);
} else if (prop === 'textShadowOffset') {
nextStyle[prop] = style[prop];
nextStyle[prop].width = additiveInverse(style[prop].width);
} else if (prop === 'transform') {
nextStyle[prop] = style[prop].map(flipTransform);
} else {
if (indexOfNoFlip > -1) {
const newProp = prop.substring(0, indexOfNoFlip);
newStyle[newProp] = style[prop];
} else {
newStyle[prop] = style[prop];
}
nextStyle[prop] = style[prop];
}
}
return newStyle;
return nextStyle;
};
module.exports = i18nStyle;

View File

@@ -28,11 +28,12 @@ const initialize = () => {
);
injector.addRule(
'pointer-events',
'.rn_pointerEvents\\:auto,.rn_pointerEvents\\:box-only,.rn_pointerEvents\\:box-none *{pointer-events:auto}' +
'.rn_pointerEvents\\:none,.rn_pointerEvents\\:box-only *,.rn_pointerEvents\\:box-none{pointer-events:none}'
'.rn-pointerEvents\\:auto,.rn-pointerEvents\\:box-only,.rn-pointerEvents\\:box-none *{pointer-events:auto}' +
'.rn-pointerEvents\\:none,.rn-pointerEvents\\:box-only *,.rn-pointerEvents\\:box-none{pointer-events:none}'
);
StyleRegistry.initialize();
const classNames = injector.getClassNames();
StyleRegistry.initialize(classNames);
};
export default initialize;

View File

@@ -5,14 +5,31 @@
import asap from 'asap';
const emptyObject = {};
const hasOwnProperty = Object.prototype.hasOwnProperty;
const CLASSNAME_REXEP = /\.rn-([^{;\s]+)/g;
const STYLE_ELEMENT_ID = 'react-native-stylesheet';
let registry = {};
let isDirty = false;
let styleNode = null;
/**
* Registers a rule and requests an update to the style sheet
*/
const addRule = (key, rule) => {
if (!registry[key]) {
registry[key] = rule;
isDirty = true;
if (global.document) {
asap(frame);
}
}
};
/**
* Returns a string of the registered rules
*/
const getStyleText = () => {
/* eslint prefer-template:0 */
let result = '\n';
@@ -24,66 +41,66 @@ const getStyleText = () => {
return result;
};
// TODO: SSR support
const getAvailableClassNames = () => {
/**
* Returns an HTML string for server rendering
*/
const getStyleSheetHtml = () => `<style id="${STYLE_ELEMENT_ID}">${getStyleText()}</style>`;
const reset = () => { registry = {}; };
/**
* Finds or injects the style sheet when in a browser environment
*/
let styleNode = null;
const getStyleNode = () => {
if (global.document) {
if (!styleNode) {
// look for existing style sheet (could also be server-rendered)
styleNode = document.getElementById(STYLE_ELEMENT_ID);
if (!styleNode) {
// if there is no existing stylesheet, inject it style sheet
document.head.insertAdjacentHTML('afterbegin', getStyleSheetHtml());
styleNode = document.getElementById(STYLE_ELEMENT_ID);
}
}
if (styleNode) {
const text = styleNode.textContent;
return text.match(CLASSNAME_REXEP).map((name) => name.slice(1));
} else {
return [];
}
} else {
return [];
return styleNode;
}
};
const createStyleHTML = (text) => `<style id="${STYLE_ELEMENT_ID}">${text}</style>`;
/**
* Determines which classes are available in the existing document. Doesn't
* rely on the registry so it can be used to read class names from a SSR style
* sheet.
*/
const getClassNames = () => {
const styleNode = getStyleNode();
if (styleNode) {
const text = styleNode.textContent;
const matches = text.match(CLASSNAME_REXEP);
if (matches) {
return matches.map((name) => name.slice(1)).reduce((classMap, className) => {
classMap[className] = true;
return classMap;
}, {});
}
}
return emptyObject;
};
const frame = () => {
if (!isDirty || !global.document) { return; }
isDirty = false;
styleNode = styleNode || document.getElementById(STYLE_ELEMENT_ID);
if (!styleNode) {
document.head.insertAdjacentHTML('afterbegin', createStyleHTML());
styleNode = document.getElementById(STYLE_ELEMENT_ID);
}
const css = getStyleText();
if (styleNode.styleSheet) {
styleNode.styleSheet.cssText = css;
} else {
/* eslint no-cond-assign:0 */
let last;
while (last = styleNode.lastChild) {
styleNode.removeChild(last);
}
styleNode.appendChild(document.createTextNode(css));
const styleNode = getStyleNode();
if (styleNode) {
const css = getStyleText();
styleNode.textContent = css;
}
};
const addRule = (key, rule) => {
if (!registry[key]) {
registry[key] = rule;
if (!isDirty) {
isDirty = true;
if (global.document) {
asap(frame);
}
}
}
};
const getStyleSheetHtml = () => createStyleHTML(getStyleText());
module.exports = {
addRule,
getAvailableClassNames,
getClassNames,
getStyleSheetHtml,
reset: () => { registry = {}; }
reset
};

View File

@@ -1,23 +1,36 @@
const unitlessNumbers = {
animationIterationCount: true,
borderImageOutset: true,
borderImageSlice: true,
borderImageWidth: true,
boxFlex: true,
boxFlexGroup: true,
boxOrdinalGroup: true,
columnCount: true,
flex: true,
flexGrow: true,
flexOrder: true,
flexPositive: true,
flexShrink: true,
flexNegative: true,
fontWeight: true,
gridRow: true,
gridColumn: true,
lineClamp: true,
opacity: true,
order: true,
orphans: true,
tabSize: true,
widows: true,
zIndex: true,
zoom: true,
// SVG-related
fillOpacity: true,
floodOpacity: true,
stopOpacity: true,
strokeDasharray: true,
strokeDashoffset: true,
strokeMiterlimit: true,
strokeOpacity: true,
strokeWidth: true,
// transform types

View File

@@ -7,14 +7,19 @@ import createReactDOMStyle from './createReactDOMStyle';
import flattenArray from '../../modules/flattenArray';
import flattenStyle from './flattenStyle';
import generateCss from './generateCss';
import I18nManager from '../I18nManager';
import injector from './injector';
import mapKeyValue from '../../modules/mapKeyValue';
import prefixInlineStyles from './prefixInlineStyles';
import ReactNativePropRegistry from '../../modules/ReactNativePropRegistry';
const prefix = 'r';
const SPACE_REGEXP = /\s/g;
const ESCAPE_SELECTOR_CHARS_REGEXP = /[(),":?.%\\$#]/g;
const ESCAPE_SELECTOR_CHARS_REGEXP = /[(),":?.%\\$#*]/g;
const createCacheKey = (id) => {
const prefix = I18nManager.isRTL ? 'rtl' : 'ltr';
return `${prefix}-${id}`;
};
/**
* Creates an HTML class name for use on elements
@@ -24,6 +29,14 @@ const createClassName = (prop, value) => {
return `rn-${prop}:${val}`;
};
/**
* Formatting improves debugging in devtools and snapshot
*/
const mapDeclarationsToClassName = (style, fn) => {
const result = mapKeyValue(style, fn).join('\n').trim();
return `\n${result}`;
};
/**
* Inject a CSS rule for a given declaration and record the availability of the
* resulting class name.
@@ -50,13 +63,13 @@ const injectClassNameIfNeeded = (prop, value) => {
let resolvedPropsCache = {};
const registerStyle = (id, flatStyle) => {
const style = createReactDOMStyle(flatStyle);
const className = mapKeyValue(style, (prop, value) => {
const className = mapDeclarationsToClassName(style, (prop, value) => {
if (value != null) {
return injectClassNameIfNeeded(prop, value);
}
}).join(' ').trim();
});
const key = `${prefix}${id}`;
const key = createCacheKey(id);
resolvedPropsCache[key] = { className };
return id;
@@ -67,41 +80,39 @@ const registerStyle = (id, flatStyle) => {
*/
const resolveProps = (reactNativeStyle) => {
const flatStyle = flattenStyle(reactNativeStyle);
if (process.env.__REACT_NATIVE_DEBUG_ENABLED__) {
console.groupCollapsed('[render] deoptimized: resolving uncached styles');
console.log('source style\n', reactNativeStyle);
console.log('flattened style\n', flatStyle);
}
const domStyle = createReactDOMStyle(flatStyle);
const style = {};
const _className = mapKeyValue(domStyle, (prop, value) => {
const className = mapDeclarationsToClassName(domStyle, (prop, value) => {
if (value != null) {
const singleClassName = createClassName(prop, value);
if (injectedClassNames[singleClassName]) {
return singleClassName;
} else {
// 4x slower render
style[prop] = value;
}
}
})
// improves debugging in devtools and snapshots
.join('\n')
.trim();
const className = `\n${_className}`;
});
const props = {
className,
style: prefixInlineStyles(style)
};
/*
if (process.env.__REACT_NATIVE_DEBUG_ENABLED__) {
console.log('DOM props\n', props);
console.groupCollapsed('[StyleSheet] resolving uncached styles');
console.log(
'Slow operation. Resolving style objects (uncached result). ' +
'Occurs on first render and when using styles not registered with "StyleSheet.create"'
);
console.log('source => \n', reactNativeStyle);
console.log('flatten => \n', flatStyle);
console.log('resolve => \n', props);
console.groupEnd();
}
*/
return props;
};
@@ -110,20 +121,36 @@ const resolveProps = (reactNativeStyle) => {
* Caching layer over 'resolveProps'
*/
const resolvePropsIfNeeded = (key, style) => {
if (!key || !resolvedPropsCache[key]) {
// slow: convert style object to props and cache
resolvedPropsCache[key] = resolveProps(style);
if (key) {
if (!resolvedPropsCache[key]) {
// slow: convert style object to props and cache
resolvedPropsCache[key] = resolveProps(style);
}
return resolvedPropsCache[key];
}
return resolvedPropsCache[key];
return resolveProps(style);
};
/**
* Web style registry
*/
const StyleRegistry = {
initialize() {
const classNames = injector.getAvailableClassNames();
classNames.forEach((className) => { injectedClassNames[className] = true; });
initialize(classNames) {
injectedClassNames = classNames;
/*
if (process.env.__REACT_NATIVE_DEBUG_ENABLED__) {
if (global.__REACT_NATIVE_DEBUG_ENABLED__styleRegistryTimer) {
clearInterval(global.__REACT_NATIVE_DEBUG_ENABLED__styleRegistryTimer);
}
global.__REACT_NATIVE_DEBUG_ENABLED__styleRegistryTimer = setInterval(() => {
const entryCount = Object.keys(resolvedPropsCache).length;
console.groupCollapsed('[StyleSheet] resolved props cache snapshot:', entryCount, 'entries');
console.log(resolvedPropsCache);
console.groupEnd();
}, 30000);
}
*/
},
reset() {
@@ -144,7 +171,7 @@ const StyleRegistry = {
// fast and cachable
if (typeof reactNativeStyle === 'number') {
const key = `${prefix}${reactNativeStyle}`;
const key = createCacheKey(reactNativeStyle);
return resolvePropsIfNeeded(key, reactNativeStyle);
}
@@ -156,6 +183,7 @@ const StyleRegistry = {
// flatten the array
// [ 1, [ 2, 3 ], { prop: value }, 4, 5 ] => [ 1, 2, 3, { prop: value }, 4, 5 ];
const flatArray = flattenArray(reactNativeStyle);
let isArrayOfNumbers = true;
for (let i = 0; i < flatArray.length; i++) {
if (typeof flatArray[i] !== 'number') {
@@ -164,14 +192,10 @@ const StyleRegistry = {
}
}
if (isArrayOfNumbers) {
// cache resolved props
const key = `${prefix}${flatArray.join('-')}`;
return resolvePropsIfNeeded(key, flatArray);
} else {
// resolve
return resolveProps(flatArray);
}
// cache resolved props when all styles are registered
const key = isArrayOfNumbers ? createCacheKey(flatArray.join('-')) : null;
return resolvePropsIfNeeded(key, flatArray);
}
};

View File

@@ -1,4 +1,4 @@
import normalizeColor from '../../modules/normalizeColor';
import normalizeColor from 'normalize-css-color';
import normalizeValue from './normalizeValue';
const defaultOffset = { height: 0, width: 0 };
@@ -6,11 +6,9 @@ const defaultOffset = { height: 0, width: 0 };
const applyOpacity = (color, opacity = 1) => {
const nullableColor = normalizeColor(color);
const colorInt = nullableColor === null ? 0x00000000 : nullableColor;
const r = Math.round(((colorInt & 0xff000000) >>> 24));
const g = Math.round(((colorInt & 0x00ff0000) >>> 16));
const b = Math.round(((colorInt & 0x0000ff00) >>> 8));
const a = (((colorInt & 0x000000ff) >>> 0) / 255).toFixed(2);
return `rgba(${r},${g},${b},${a * opacity})`;
const { r, g, b, a } = normalizeColor.rgba(colorInt);
const alpha = a.toFixed(2);
return `rgba(${r},${g},${b},${alpha * opacity})`;
};
// TODO: add inset and spread support

View File

@@ -1,7 +1,7 @@
import normalizeValue from './normalizeValue';
// { scale: 2 } => 'scale(2)'
// { translateX: 20 } => 'translateX(20px)'
// { translateX: 20 } => 'translateX(20px)'
const mapTransform = (transform) => {
const type = Object.keys(transform)[0];
const value = normalizeValue(type, transform[type]);

View File

@@ -10,107 +10,7 @@ const createNode = (style = {}) => {
return root;
};
let defaultBodyMargin;
describe('apis/UIManager', () => {
beforeEach(() => {
// remove default body margin so we can predict the measured offsets
defaultBodyMargin = document.body.style.margin;
document.body.style.margin = 0;
});
afterEach(() => {
document.body.style.margin = defaultBodyMargin;
});
describe('measure', () => {
test('provides correct layout to callback', () => {
const node = createNode({ height: '5000px', left: '100px', position: 'relative', top: '100px', width: '5000px' });
document.body.appendChild(node);
node.getBoundingClientRect = jest.fn(() => ({ width: 5000, height: 5000, top: 100, left: 100 }));
UIManager.measure(node, (x, y, width, height, pageX, pageY) => {
expect(x).toEqual(100);
expect(y).toEqual(100);
expect(width).toEqual(5000);
expect(height).toEqual(5000);
expect(pageX).toEqual(100);
expect(pageY).toEqual(100);
});
// test values account for scroll position
window.scrollTo(200, 200);
node.getBoundingClientRect = jest.fn(() => ({ width: 5000, height: 5000, top: -100, left: -100 }));
node.parentNode.getBoundingClientRect = jest.fn(() => ({ top: -200, left: -200 }));
UIManager.measure(node, (x, y, width, height, pageX, pageY) => {
expect(x).toEqual(100);
expect(y).toEqual(100);
expect(width).toEqual(5000);
expect(height).toEqual(5000);
expect(pageX).toEqual(-100);
expect(pageY).toEqual(-100);
});
document.body.removeChild(node);
});
});
describe('measureLayout', () => {
test('provides correct layout to onSuccess callback', () => {
const node = createNode({ height: '10px', width: '10px' });
const middle = createNode({ padding: '20px' });
const context = createNode({ padding: '20px' });
middle.appendChild(node);
context.appendChild(middle);
document.body.appendChild(context);
node.getBoundingClientRect = jest.fn(() => ({
width: 10,
height: 10,
top: 40,
left: 40
}));
UIManager.measureLayout(node, context, () => {}, (x, y, width, height) => {
expect(x).toEqual(40);
expect(y).toEqual(40);
expect(width).toEqual(10);
expect(height).toEqual(10);
});
document.body.removeChild(context);
});
});
describe('measureInWindow', () => {
test('provides correct layout to callback', () => {
const node = createNode({ height: '10px', width: '10px' });
const middle = createNode({ padding: '20px' });
const context = createNode({ padding: '20px' });
middle.appendChild(node);
context.appendChild(middle);
document.body.appendChild(context);
node.getBoundingClientRect = jest.fn(() => ({
width: 10,
height: 10,
top: 40,
left: 40
}));
UIManager.measureInWindow(node, (x, y, width, height) => {
expect(x).toEqual(40);
expect(y).toEqual(40);
expect(width).toEqual(10);
expect(height).toEqual(10);
});
document.body.removeChild(context);
});
});
describe('updateView', () => {
const componentStub = {
_reactInternalInstance: {
@@ -119,17 +19,16 @@ describe('apis/UIManager', () => {
}
};
test('add new className to existing className', () => {
test('supports className alias for class', () => {
const node = createNode();
node.className = 'existing';
const props = { className: 'extra' };
UIManager.updateView(node, props, componentStub);
expect(node.getAttribute('class')).toEqual('existing extra');
expect(node.getAttribute('class')).toEqual('extra');
});
test('adds correct DOM styles to existing style', () => {
const node = createNode({ color: 'red' });
const props = { style: { marginVertical: 0, opacity: 0 } };
const props = { style: { marginTop: 0, marginBottom: 0, opacity: 0 } };
UIManager.updateView(node, props, componentStub);
expect(node.getAttribute('style')).toEqual('color: red; margin-top: 0px; margin-bottom: 0px; opacity: 0;');
});

View File

@@ -1,15 +1,28 @@
import createReactDOMStyle from '../StyleSheet/createReactDOMStyle';
import flattenStyle from '../StyleSheet/flattenStyle';
import asap from 'asap';
import CSSPropertyOperations from 'react-dom/lib/CSSPropertyOperations';
import prefixInlineStyles from '../StyleSheet/prefixInlineStyles';
const _measureLayout = (node, relativeToNativeNode, callback) => {
const relativeNode = relativeToNativeNode || node.parentNode;
const relativeRect = relativeNode.getBoundingClientRect();
const { height, left, top, width } = node.getBoundingClientRect();
const x = left - relativeRect.left;
const y = top - relativeRect.top;
callback(x, y, width, height, left, top);
const getRect = (node) => {
const height = node.offsetHeight;
const width = node.offsetWidth;
let left = 0;
let top = 0;
while (node && node.nodeType === 1 /* Node.ELEMENT_NODE */) {
left += node.offsetLeft;
top += node.offsetTop;
node = node.offsetParent;
}
return { height, left, top, width };
};
const measureLayout = (node, relativeToNativeNode, callback) => {
asap(() => {
const relativeNode = relativeToNativeNode || node.parentNode;
const relativeRect = getRect(relativeNode);
const { height, left, top, width } = getRect(node);
const x = left - relativeRect.left;
const y = top - relativeRect.top;
callback(x, y, width, height, left, top);
});
};
const UIManager = {
@@ -22,17 +35,17 @@ const UIManager = {
},
measure(node, callback) {
_measureLayout(node, null, callback);
measureLayout(node, null, callback);
},
measureInWindow(node, callback) {
const { height, left, top, width } = node.getBoundingClientRect();
const { height, left, top, width } = getRect(node);
callback(left, top, width, height);
},
measureLayout(node, relativeToNativeNode, onFail, onSuccess) {
const relativeTo = relativeToNativeNode || node.parentNode;
_measureLayout(node, relativeTo, onSuccess);
measureLayout(node, relativeTo, onSuccess);
},
updateView(node, props, component /* only needed to surpress React errors in development */) {
@@ -44,16 +57,12 @@ const UIManager = {
const value = props[prop];
switch (prop) {
case 'style': {
const style = prefixInlineStyles(createReactDOMStyle(flattenStyle(value)));
CSSPropertyOperations.setValueForStyles(node, style, component._reactInternalInstance);
CSSPropertyOperations.setValueForStyles(node, value, component._reactInternalInstance);
break;
}
case 'class':
case 'className': {
const nativeProp = 'class';
// prevent class names managed by React Native from being replaced
const className = `${node.getAttribute(nativeProp)} ${value}`;
node.setAttribute(nativeProp, className);
node.setAttribute('class', value);
break;
}
case 'text':

View File

@@ -16,9 +16,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-justifyContent:center
rn-listStyle:none
@@ -56,9 +56,9 @@ rn-textDecoration:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-height:20px
rn-listStyle:none
@@ -129,9 +129,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-justifyContent:center
rn-listStyle:none
@@ -170,9 +170,9 @@ rn-textDecoration:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-height:36px
rn-listStyle:none

View File

@@ -1,13 +1,14 @@
import applyNativeMethods from '../../modules/applyNativeMethods';
import StyleSheet from '../../apis/StyleSheet';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import React, { Component, PropTypes } from 'react';
class ActivityIndicator extends Component {
static displayName = 'ActivityIndicator';
static propTypes = {
...View.propTypes,
...ViewPropTypes,
animating: PropTypes.bool,
color: PropTypes.string,
hidesWhenStopped: PropTypes.bool,

View File

@@ -3,13 +3,15 @@ import ColorPropType from '../../propTypes/ColorPropType';
import ImageResizeMode from './ImageResizeMode';
import LayoutPropTypes from '../../propTypes/LayoutPropTypes';
import { PropTypes } from 'react';
import ShadowPropTypes from '../../propTypes/ShadowPropTypes';
import TransformPropTypes from '../../propTypes/TransformPropTypes';
const hiddenOrVisible = PropTypes.oneOf([ 'hidden', 'visible' ]);
module.exports = process.env.NODE_ENV !== 'production' ? {
module.exports = {
...BorderPropTypes,
...LayoutPropTypes,
...ShadowPropTypes,
...TransformPropTypes,
backfaceVisibility: hiddenOrVisible,
backgroundColor: ColorPropType,
@@ -24,4 +26,4 @@ module.exports = process.env.NODE_ENV !== 'production' ? {
* @platform web
*/
visibility: hiddenOrVisible
} : {};
};

View File

@@ -17,9 +17,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -34,9 +34,9 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
rn-textDecoration:none
rn-zIndex:0"
onResponderGrant={[Function]}
role="img"
style={Object {}} />
`;
@@ -60,9 +60,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -77,8 +77,8 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={Object {}} />
`;
@@ -102,9 +102,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -119,8 +119,8 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={Object {}} />
`;
@@ -143,9 +143,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -160,8 +160,8 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={Object {}}>
<div
className="unique" />
@@ -173,7 +173,6 @@ exports[`components/Image prop "defaultSource" does not override "height" and "w
className="
rn-alignItems:stretch
rn-backgroundColor:transparent
rn-backgroundPosition:center
rn-backgroundRepeat:no-repeat
rn-backgroundSize:cover
@@ -188,11 +187,10 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
@@ -206,15 +204,29 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={
Object {
"backgroundImage": "url(\"https://google.com/favicon.ico\")",
"height": "20px",
"width": "40px",
}
} />
}>
<img
className="
rn-bottom:0px
rn-height:100%
rn-left:0px
rn-opacity:0
rn-position:absolute
rn-right:0px
rn-top:0px
rn-width:100%
rn-zIndex:-1"
src="https://google.com/favicon.ico"
style={Object {}} />
</div>
`;
exports[`components/Image prop "defaultSource" sets "height" and "width" styles if missing 1`] = `
@@ -222,7 +234,6 @@ exports[`components/Image prop "defaultSource" sets "height" and "width" styles
className="
rn-alignItems:stretch
rn-backgroundColor:transparent
rn-backgroundPosition:center
rn-backgroundRepeat:no-repeat
rn-backgroundSize:cover
@@ -237,11 +248,10 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
@@ -255,15 +265,29 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={
Object {
"backgroundImage": "url(\"https://google.com/favicon.ico\")",
"height": "10px",
"width": "20px",
}
} />
}>
<img
className="
rn-bottom:0px
rn-height:100%
rn-left:0px
rn-opacity:0
rn-position:absolute
rn-right:0px
rn-top:0px
rn-width:100%
rn-zIndex:-1"
src="https://google.com/favicon.ico"
style={Object {}} />
</div>
`;
exports[`components/Image prop "defaultSource" sets background image when value is a string 1`] = `
@@ -271,7 +295,6 @@ exports[`components/Image prop "defaultSource" sets background image when value
className="
rn-alignItems:stretch
rn-backgroundColor:transparent
rn-backgroundPosition:center
rn-backgroundRepeat:no-repeat
rn-backgroundSize:cover
@@ -286,9 +309,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -303,13 +326,27 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={
Object {
"backgroundImage": "url(\"https://google.com/favicon.ico\")",
}
} />
}>
<img
className="
rn-bottom:0px
rn-height:100%
rn-left:0px
rn-opacity:0
rn-position:absolute
rn-right:0px
rn-top:0px
rn-width:100%
rn-zIndex:-1"
src="https://google.com/favicon.ico"
style={Object {}} />
</div>
`;
exports[`components/Image prop "defaultSource" sets background image when value is an object 1`] = `
@@ -317,7 +354,6 @@ exports[`components/Image prop "defaultSource" sets background image when value
className="
rn-alignItems:stretch
rn-backgroundColor:transparent
rn-backgroundPosition:center
rn-backgroundRepeat:no-repeat
rn-backgroundSize:cover
@@ -332,9 +368,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -349,13 +385,27 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={
Object {
"backgroundImage": "url(\"https://google.com/favicon.ico\")",
}
} />
}>
<img
className="
rn-bottom:0px
rn-height:100%
rn-left:0px
rn-opacity:0
rn-position:absolute
rn-right:0px
rn-top:0px
rn-width:100%
rn-zIndex:-1"
src="https://google.com/favicon.ico"
style={Object {}} />
</div>
`;
exports[`components/Image prop "resizeMode" value "contain" 1`] = `
@@ -377,9 +427,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -394,8 +444,8 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={Object {}} />
`;
@@ -418,9 +468,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -435,8 +485,8 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={Object {}} />
`;
@@ -459,9 +509,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -476,8 +526,8 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={Object {}} />
`;
@@ -500,9 +550,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -517,8 +567,8 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={Object {}} />
`;
@@ -541,9 +591,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -558,8 +608,8 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={Object {}} />
`;
@@ -582,9 +632,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -599,8 +649,8 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={Object {}} />
`;
@@ -623,9 +673,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -640,9 +690,9 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
rn-textDecoration:none
rn-zIndex:0"
data-testid="testID"
role="img"
style={Object {}} />
`;
@@ -665,9 +715,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -682,7 +732,7 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="img"
rn-textDecoration:none
rn-zIndex:0"
style={Object {}} />
`;

View File

@@ -1,12 +1,14 @@
/* global window */
import applyNativeMethods from '../../modules/applyNativeMethods';
import createDOMElement from '../../modules/createDOMElement';
import ImageResizeMode from './ImageResizeMode';
import ImageLoader from '../../modules/ImageLoader';
import ImageStylePropTypes from './ImageStylePropTypes';
import requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
import requestIdleCallback, { cancelIdleCallback } from '../../modules/requestIdleCallback';
import StyleSheet from '../../apis/StyleSheet';
import StyleSheetPropType from '../../propTypes/StyleSheetPropType';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import React, { Component, PropTypes } from 'react';
const emptyObject = {};
@@ -41,7 +43,7 @@ class Image extends Component {
static displayName = 'Image';
static propTypes = {
...View.propTypes,
...ViewPropTypes,
children: PropTypes.any,
defaultSource: ImageSourcePropType,
onError: PropTypes.func,
@@ -137,28 +139,42 @@ class Image extends Component {
// View doesn't support 'resizeMode' as a style
delete style.resizeMode;
// Allows users to trigger the browser's image context menu
const hiddenImage = displayImage ? createDOMElement('img', {
src: displayImage,
style: [ StyleSheet.absoluteFill, styles.img ]
}) : null;
return (
<View
{...other}
accessibilityLabel={accessibilityLabel}
accessibilityRole='img'
accessible={accessible}
children={children}
onLayout={onLayout}
style={style}
testID={testID}
/>
>
{hiddenImage}
{children}
</View>
);
}
_createImageLoader() {
this._destroyImageLoader();
const uri = resolveAssetSource(this.props.source);
this._imageRequestId = ImageLoader.load(uri, this._onLoad, this._onError);
this._onLoadStart();
this._loadRequest = requestIdleCallback(() => {
this._destroyImageLoader();
const uri = resolveAssetSource(this.props.source);
this._imageRequestId = ImageLoader.load(uri, this._onLoad, this._onError);
this._onLoadStart();
});
}
_destroyImageLoader() {
if (this._loadRequest) {
cancelIdleCallback(this._loadRequest);
this._loadRequest = null;
}
if (this._imageRequestId) {
ImageLoader.abort(this._imageRequestId);
this._imageRequestId = null;
@@ -203,11 +219,9 @@ class Image extends Component {
const shouldDisplaySource = this._imageState === STATUS_LOADED || this._imageState === STATUS_LOADING;
// only triggers a re-render when the image is loading (to support PJEG), loaded, or failed
if (shouldDisplaySource !== this.state.shouldDisplaySource) {
requestAnimationFrame(() => {
if (this._isMounted) {
this.setState({ shouldDisplaySource });
}
});
if (this._isMounted) {
this.setState(() => ({ shouldDisplaySource }));
}
}
}
}
@@ -217,7 +231,14 @@ const styles = StyleSheet.create({
backgroundColor: 'transparent',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
backgroundSize: 'cover',
zIndex: 0
},
img: {
height: '100%',
opacity: 0,
width: '100%',
zIndex: -1
}
});

View File

@@ -222,6 +222,10 @@ class ListViewDataSource {
return this._cachedRowCount;
}
getRowAndSectionCount(): number {
return (this._cachedRowCount + this.sectionIdentities.length);
}
/**
* Returns if the row is dirtied and needs to be rerendered
*/

View File

@@ -3,7 +3,8 @@ import ListViewDataSource from './ListViewDataSource';
import ListViewPropTypes from './ListViewPropTypes';
import ScrollView from '../ScrollView';
import StaticRenderer from '../StaticRenderer';
import React, { Component, isEmpty, merge } from 'react';
import React, { Component } from 'react';
import isEmpty from 'fbjs/lib/isEmpty';
import requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
const DEFAULT_PAGE_SIZE = 1;
@@ -106,20 +107,42 @@ class ListView extends Component {
render() {
const children = [];
const dataSource = this.props.dataSource;
const {
dataSource,
enableEmptySections,
renderFooter,
renderHeader,
renderScrollComponent,
renderSectionHeader,
renderSeparator,
/* eslint-disable */
initialListSize,
onEndReachedThreshold,
onKeyboardDidHide,
onKeyboardDidShow,
onKeyboardWillHide,
onKeyboardWillShow,
pageSize,
renderRow,
scrollRenderAheadDistance,
stickyHeaderIndices,
/* eslint-enable */
...scrollProps
} = this.props;
const allRowIDs = dataSource.rowIdentities;
let rowCount = 0;
const sectionHeaderIndices = [];
const header = this.props.renderHeader && this.props.renderHeader();
const footer = this.props.renderFooter && this.props.renderFooter();
const header = renderHeader && renderHeader();
const footer = renderFooter && renderFooter();
let totalIndex = header ? 1 : 0;
for (let sectionIdx = 0; sectionIdx < allRowIDs.length; sectionIdx++) {
const sectionID = dataSource.sectionIdentities[sectionIdx];
const rowIDs = allRowIDs[sectionIdx];
if (rowIDs.length === 0) {
if (this.props.enableEmptySections === undefined) {
if (enableEmptySections === undefined) {
const warning = require('fbjs/lib/warning');
warning(false, 'In next release empty section headers will be rendered.' +
' In this release you can use \'enableEmptySections\' flag to render empty section headers.');
@@ -127,7 +150,7 @@ class ListView extends Component {
} else {
const invariant = require('fbjs/lib/invariant');
invariant(
this.props.enableEmptySections,
enableEmptySections,
'In next release \'enableEmptySections\' flag will be deprecated,' +
' empty section headers will always be rendered. If empty section headers' +
' are not desirable their indices should be excluded from sectionIDs object.' +
@@ -136,7 +159,7 @@ class ListView extends Component {
}
}
if (this.props.renderSectionHeader) {
if (renderSectionHeader) {
const shouldUpdateHeader = rowCount >= this._prevRenderedRowsCount &&
dataSource.sectionHeaderShouldUpdate(sectionIdx);
children.push(
@@ -170,14 +193,14 @@ class ListView extends Component {
children.push(row);
totalIndex++;
if (this.props.renderSeparator &&
if (renderSeparator &&
(rowIdx !== rowIDs.length - 1 || sectionIdx === allRowIDs.length - 1)) {
const adjacentRowHighlighted =
this.state.highlightedRow.sectionID === sectionID && (
this.state.highlightedRow.rowID === rowID ||
this.state.highlightedRow.rowID === rowIDs[rowIdx + 1]
);
const separator = this.props.renderSeparator(
const separator = renderSeparator(
sectionID,
rowID,
adjacentRowHighlighted
@@ -195,24 +218,9 @@ class ListView extends Component {
break;
}
}
scrollProps.onScroll = this._onScroll;
const {
renderScrollComponent,
...props
} = this.props;
Object.assign(props, {
onScroll: this._onScroll,
stickyHeaderIndices: this.props.stickyHeaderIndices.concat(sectionHeaderIndices),
// Do not pass these events downstream to ScrollView since they will be
// registered in ListView's own ScrollResponder.Mixin
onKeyboardWillShow: undefined,
onKeyboardWillHide: undefined,
onKeyboardDidShow: undefined,
onKeyboardDidHide: undefined
});
return React.cloneElement(renderScrollComponent(props), {
return React.cloneElement(renderScrollComponent(scrollProps), {
ref: this._setScrollViewRef,
onContentSizeChange: this._onContentSizeChange,
onLayout: this._onLayout
@@ -245,7 +253,7 @@ class ListView extends Component {
}
if (updatedFrames) {
updatedFrames.forEach((newFrame) => {
this._childFrames[newFrame.index] = merge(newFrame);
this._childFrames[newFrame.index] = Object.assign({}, newFrame);
});
}
const isVertical = !this.props.horizontal;

View File

@@ -2,13 +2,14 @@ import applyNativeMethods from '../../modules/applyNativeMethods';
import ColorPropType from '../../propTypes/ColorPropType';
import StyleSheet from '../../apis/StyleSheet';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import React, { Component, PropTypes } from 'react';
class ProgressBar extends Component {
static displayName = 'ProgressBar';
static propTypes = {
...View.propTypes,
...ViewPropTypes,
color: ColorPropType,
indeterminate: PropTypes.bool,
progress: PropTypes.number,
@@ -22,6 +23,14 @@ class ProgressBar extends Component {
trackColor: 'transparent'
};
componentDidMount() {
this._updateProgressWidth();
}
componentDidUpdate() {
this._updateProgressWidth();
}
render() {
const {
color,
@@ -32,7 +41,7 @@ class ProgressBar extends Component {
...other
} = this.props;
const percentageProgress = indeterminate ? 50 : progress * 100;
const percentageProgress = progress * 100;
return (
<View {...other}
@@ -47,15 +56,29 @@ class ProgressBar extends Component {
]}
>
<View
ref={this._setProgressRef}
style={[
styles.progress,
indeterminate ? styles.indeterminate : { width: `${percentageProgress}%` },
indeterminate && styles.animation,
{ backgroundColor: color }
]}
/>
</View>
);
}
_setProgressRef = (component) => {
this._progressRef = component;
}
_updateProgressWidth = () => {
const { indeterminate, progress } = this.props;
const percentageProgress = indeterminate ? 50 : progress * 100;
const width = indeterminate ? '25%' : `${percentageProgress}%`;
this._progressRef.setNativeProps({
style: { width }
});
}
}
const styles = StyleSheet.create({
@@ -67,12 +90,11 @@ const styles = StyleSheet.create({
progress: {
height: '100%'
},
indeterminate: {
animation: {
animationDuration: '1s',
animationName: 'rn-ProgressBar-animation',
animationTimingFunction: 'linear',
animationIterationCount: 'infinite',
width: '25%'
animationIterationCount: 'infinite'
}
});

View File

@@ -8,6 +8,7 @@
import debounce from 'debounce';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import React, { Component, PropTypes } from 'react';
const normalizeScrollEvent = (e) => ({
@@ -36,7 +37,8 @@ const normalizeScrollEvent = (e) => ({
return e.target.offsetWidth;
}
}
}
},
timeStamp: Date.now()
});
/**
@@ -44,7 +46,7 @@ const normalizeScrollEvent = (e) => ({
*/
export default class ScrollViewBase extends Component {
static propTypes = {
...View.propTypes,
...ViewPropTypes,
onMomentumScrollBegin: PropTypes.func,
onMomentumScrollEnd: PropTypes.func,
onScroll: PropTypes.func,

View File

@@ -14,6 +14,7 @@ import ScrollViewBase from './ScrollViewBase';
import StyleSheet from '../../apis/StyleSheet';
import StyleSheetPropType from '../../propTypes/StyleSheetPropType';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import ViewStylePropTypes from '../View/ViewStylePropTypes';
import React, { Component, PropTypes } from 'react';
@@ -22,7 +23,7 @@ const emptyObject = {};
/* eslint-disable react/prefer-es6-class */
const ScrollView = React.createClass({
propTypes: {
...View.propTypes,
...ViewPropTypes,
contentContainerStyle: StyleSheetPropType(ViewStylePropTypes),
horizontal: PropTypes.bool,
keyboardDismissMode: PropTypes.oneOf([ 'none', 'interactive', 'on-drag' ]),

View File

@@ -15,11 +15,10 @@ rn-boxSizing:border-box
rn-color:inherit
rn-cursor:pointer
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
@@ -44,11 +43,6 @@ rn-userSelect:none"
<div
className="
rn-alignItems:stretch
rn-borderTopStyle:solid
rn-borderRightStyle:solid
rn-borderBottomStyle:solid
@@ -61,9 +55,9 @@ rn-userSelect:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-height:70%
rn-left:0px
@@ -98,7 +92,6 @@ rn-userSelect:none"
className="
rn-alignItems:stretch
rn-alignSelf:flex-start
rn-borderTopLeftRadius:100%
rn-borderTopRightRadius:100%
rn-borderBottomRightRadius:100%
@@ -115,11 +108,11 @@ rn-userSelect:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-left:0%
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
@@ -134,15 +127,12 @@ rn-userSelect:none"
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none
rn-transform:translateZ(0px)
rn-transitionDuration:0.1s"
style={
Object {
"WebkitTransform": "translateX(0%)",
"backgroundColor": "#FAFAFA",
"height": "20px",
"msTransform": "translateX(0%)",
"transform": "translateX(0%)",
"width": "20px",
}
} />
@@ -192,11 +182,10 @@ rn-boxSizing:border-box
rn-color:inherit
rn-cursor:default
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
@@ -222,10 +211,6 @@ rn-userSelect:none"
className="
rn-alignItems:stretch
rn-backgroundColor:#D5D5D5
rn-borderTopStyle:solid
rn-borderRightStyle:solid
rn-borderBottomStyle:solid
@@ -238,9 +223,9 @@ rn-userSelect:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-height:70%
rn-left:0px
@@ -291,11 +276,11 @@ rn-userSelect:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-left:0%
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
@@ -310,14 +295,11 @@ rn-userSelect:none"
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none
rn-transform:translateZ(0px)
rn-transitionDuration:0.1s"
style={
Object {
"WebkitTransform": "translateX(0%)",
"height": "20px",
"msTransform": "translateX(0%)",
"transform": "translateX(0%)",
"width": "20px",
}
} />
@@ -367,11 +349,10 @@ rn-boxSizing:border-box
rn-color:inherit
rn-cursor:pointer
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
@@ -396,11 +377,6 @@ rn-userSelect:none"
<div
className="
rn-alignItems:stretch
rn-borderTopStyle:solid
rn-borderRightStyle:solid
rn-borderBottomStyle:solid
@@ -413,9 +389,9 @@ rn-userSelect:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-height:70%
rn-left:0px
@@ -450,7 +426,6 @@ rn-userSelect:none"
className="
rn-alignItems:stretch
rn-alignSelf:flex-start
rn-borderTopLeftRadius:100%
rn-borderTopRightRadius:100%
rn-borderBottomRightRadius:100%
@@ -467,11 +442,11 @@ rn-userSelect:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-left:0%
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
@@ -486,15 +461,12 @@ rn-userSelect:none"
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none
rn-transform:translateZ(0px)
rn-transitionDuration:0.1s"
style={
Object {
"WebkitTransform": "translateX(0%)",
"backgroundColor": "#FAFAFA",
"height": "20px",
"msTransform": "translateX(0%)",
"transform": "translateX(0%)",
"width": "20px",
}
} />
@@ -544,11 +516,10 @@ rn-boxSizing:border-box
rn-color:inherit
rn-cursor:pointer
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
@@ -573,11 +544,6 @@ rn-userSelect:none"
<div
className="
rn-alignItems:stretch
rn-borderTopStyle:solid
rn-borderRightStyle:solid
rn-borderBottomStyle:solid
@@ -590,9 +556,9 @@ rn-userSelect:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-height:70%
rn-left:0px
@@ -627,7 +593,6 @@ rn-userSelect:none"
className="
rn-alignItems:stretch
rn-alignSelf:flex-start
rn-borderTopLeftRadius:100%
rn-borderTopRightRadius:100%
rn-borderBottomRightRadius:100%
@@ -644,16 +609,15 @@ rn-userSelect:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-left:100%
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
rn-marginBottom:0px
rn-marginLeft:0px
rn-minHeight:0px
rn-minWidth:0px
rn-paddingTop:0px
@@ -663,15 +627,13 @@ rn-userSelect:none"
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none
rn-transform:translateZ(0px)
rn-transitionDuration:0.1s"
style={
Object {
"WebkitTransform": "translateX(100%)",
"backgroundColor": "#009688",
"height": "20px",
"msTransform": "translateX(100%)",
"transform": "translateX(100%)",
"marginLeft": "-20px",
"width": "20px",
}
} />

View File

@@ -5,6 +5,7 @@ import multiplyStyleLengthValue from '../../modules/multiplyStyleLengthValue';
import StyleSheet from '../../apis/StyleSheet';
import UIManager from '../../apis/UIManager';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import React, { Component, PropTypes } from 'react';
const emptyObject = {};
@@ -15,7 +16,7 @@ class Switch extends Component {
static displayName = 'Switch';
static propTypes = {
...View.propTypes,
...ViewPropTypes,
activeThumbColor: ColorPropType,
activeTrackColor: ColorPropType,
disabled: PropTypes.bool,
@@ -91,7 +92,6 @@ class Switch extends Component {
{
backgroundColor: thumbCurrentColor,
height: thumbHeight,
transform: [ { translateX: value ? '100%' : '0%' } ],
width: thumbWidth
},
disabled && styles.disabledThumb
@@ -111,7 +111,16 @@ class Switch extends Component {
return (
<View {...other} style={rootStyle}>
<View style={trackStyle} />
<View ref={this._setThumbRef} style={thumbStyle} />
<View
ref={this._setThumbRef}
style={[
thumbStyle,
value && styles.thumbOn,
{
marginLeft: value ? multiplyStyleLengthValue(thumbWidth, -1) : 0
}
]}
/>
{nativeControl}
</View>
);
@@ -162,8 +171,15 @@ const styles = StyleSheet.create({
alignSelf: 'flex-start',
borderRadius: '100%',
boxShadow: thumbDefaultBoxShadow,
left: '0%',
transform: [
{ translateZ: 0 }
],
transitionDuration: '0.1s'
},
thumbOn: {
left: '100%'
},
disabledThumb: {
backgroundColor: '#BDBDBD'
},

View File

@@ -1,7 +1,42 @@
import TextPropTypes from '../../propTypes/TextPropTypes';
import ColorPropType from '../../propTypes/ColorPropType';
import { PropTypes } from 'react';
import ViewStylePropTypes from '../View/ViewStylePropTypes';
module.exports = process.env.NODE_ENV !== 'production' ? {
const { number, oneOf, oneOfType, shape, string } = PropTypes;
const numberOrString = oneOfType([ number, string ]);
const ShadowOffsetPropType = shape({ width: number, height: number });
const TextAlignPropType = oneOf([ 'center', 'inherit', 'justify', 'justify-all', 'left', 'right' ]);
const WritingDirectionPropType = oneOf([ 'auto', 'ltr', 'rtl' ]);
const TextOnlyStylePropTypes = {
color: ColorPropType,
fontFamily: string,
fontFeatureSettings: string,
fontSize: numberOrString,
fontStyle: string,
fontWeight: string,
letterSpacing: numberOrString,
lineHeight: numberOrString,
textAlign: TextAlignPropType,
textAlignVertical: oneOf([ 'auto', 'bottom', 'center', 'top' ]),
textDecorationLine: string,
textShadowColor: ColorPropType,
textShadowOffset: ShadowOffsetPropType,
textShadowRadius: number,
writingDirection: WritingDirectionPropType,
/* @platform web */
textOverflow: string,
textRendering: oneOf([ 'auto', 'geometricPrecision', 'optimizeLegibility', 'optimizeSpeed' ]),
textTransform: oneOf([ 'capitalize', 'lowercase', 'none', 'uppercase' ]),
unicodeBidi: oneOf([ 'normal', 'bidi-override', 'embed', 'isolate', 'isolate-override', 'plaintext' ]),
whiteSpace: string,
wordWrap: string,
MozOsxFontSmoothing: string,
WebkitFontSmoothing: string
};
module.exports = {
...ViewStylePropTypes,
...TextPropTypes
} : {};
...TextOnlyStylePropTypes
};

View File

@@ -1,15 +1,25 @@
exports[`components/Text prop "children" 1`] = `
<span
className="rn-borderTopWidth:0px rn-borderRightWidth:0px rn-borderBottomWidth:0px rn-borderLeftWidth:0px rn-color:inherit rn-display:inline rn-font:inherit rn-marginTop:0px rn-marginRight:0px rn-marginBottom:0px rn-marginLeft:0px rn-paddingTop:0px rn-paddingRight:0px rn-paddingBottom:0px rn-paddingLeft:0px rn-textDecoration:none rn-whiteSpace:pre-wrap rn-wordWrap:break-word"
style={
Array [
3,
undefined,
false,
false,
undefined,
]
}>
className="
rn-borderTopWidth:0px
rn-borderRightWidth:0px
rn-borderBottomWidth:0px
rn-borderLeftWidth:0px
rn-color:inherit
rn-display:inline
rn-font:inherit
rn-marginTop:0px
rn-marginRight:0px
rn-marginBottom:0px
rn-marginLeft:0px
rn-paddingTop:0px
rn-paddingRight:0px
rn-paddingBottom:0px
rn-paddingLeft:0px
rn-textDecoration:none
rn-whiteSpace:pre-wrap
rn-wordWrap:break-word"
dir="auto">
children
</span>
`;
@@ -36,6 +46,7 @@ rn-paddingLeft:0px
rn-textDecoration:none
rn-whiteSpace:pre-wrap
rn-wordWrap:break-word"
dir="auto"
onClick={[Function]}
onKeyDown={[Function]}
style={Object {}}
@@ -44,16 +55,26 @@ rn-wordWrap:break-word"
exports[`components/Text prop "selectable" 1`] = `
<span
className="rn-borderTopWidth:0px rn-borderRightWidth:0px rn-borderBottomWidth:0px rn-borderLeftWidth:0px rn-color:inherit rn-display:inline rn-font:inherit rn-marginTop:0px rn-marginRight:0px rn-marginBottom:0px rn-marginLeft:0px rn-paddingTop:0px rn-paddingRight:0px rn-paddingBottom:0px rn-paddingLeft:0px rn-textDecoration:none rn-whiteSpace:pre-wrap rn-wordWrap:break-word"
style={
Array [
3,
undefined,
false,
false,
undefined,
]
} />
className="
rn-borderTopWidth:0px
rn-borderRightWidth:0px
rn-borderBottomWidth:0px
rn-borderLeftWidth:0px
rn-color:inherit
rn-display:inline
rn-font:inherit
rn-marginTop:0px
rn-marginRight:0px
rn-marginBottom:0px
rn-marginLeft:0px
rn-paddingTop:0px
rn-paddingRight:0px
rn-paddingBottom:0px
rn-paddingLeft:0px
rn-textDecoration:none
rn-whiteSpace:pre-wrap
rn-wordWrap:break-word"
dir="auto" />
`;
exports[`components/Text prop "selectable" 2`] = `
@@ -78,5 +99,6 @@ rn-textDecoration:none
rn-userSelect:none
rn-whiteSpace:pre-wrap
rn-wordWrap:break-word"
dir="auto"
style={Object {}} />
`;

View File

@@ -56,6 +56,8 @@ class Text extends Component {
numberOfLines === 1 && styles.singleLineStyle,
onPress && styles.pressable
];
// allow browsers to automatically infer the language writing direction
otherProps.dir = 'auto';
return createDOMElement('span', otherProps);
}

View File

@@ -0,0 +1,14 @@
import TextStylePropTypes from '../Text/TextStylePropTypes';
import { PropTypes } from 'react';
const { oneOf } = PropTypes;
const TextInputOnlyStylePropTypes = {
/* @platform web */
resize: oneOf([ 'none', 'vertical', 'horizontal', 'both' ])
};
module.exports = {
...TextStylePropTypes,
...TextInputOnlyStylePropTypes
};

View File

@@ -1,13 +1,14 @@
import applyLayout from '../../modules/applyLayout';
import applyNativeMethods from '../../modules/applyNativeMethods';
import NativeMethodsMixin from '../../modules/NativeMethodsMixin';
import createDOMElement from '../../modules/createDOMElement';
import findNodeHandle from '../../modules/findNodeHandle';
import StyleSheet from '../../apis/StyleSheet';
import Text from '../Text';
import StyleSheetPropType from '../../propTypes/StyleSheetPropType';
import TextInputStylePropTypes from './TextInputStylePropTypes';
import TextareaAutosize from 'react-textarea-autosize';
import TextInputState from './TextInputState';
import UIManager from '../../apis/UIManager';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import { Component, PropTypes } from 'react';
const emptyObject = {};
@@ -52,7 +53,7 @@ class TextInput extends Component {
static displayName = 'TextInput';
static propTypes = {
...View.propTypes,
...ViewPropTypes,
autoCapitalize: PropTypes.oneOf([ 'characters', 'none', 'sentences', 'words' ]),
autoComplete: PropTypes.string,
autoCorrect: PropTypes.bool,
@@ -83,7 +84,7 @@ class TextInput extends Component {
start: PropTypes.number.isRequired,
end: PropTypes.number
}),
style: Text.propTypes.style,
style: StyleSheetPropType(TextInputStylePropTypes),
value: PropTypes.string
};
@@ -99,6 +100,8 @@ class TextInput extends Component {
style: emptyObject
};
static State = TextInputState;
blur() {
TextInputState.blurTextInput(this._node);
}
@@ -116,7 +119,7 @@ class TextInput extends Component {
}
setNativeProps(props) {
UIManager.updateView(this._node, props, this);
NativeMethodsMixin.setNativeProps.call(this, props);
}
componentDidMount() {
@@ -274,7 +277,8 @@ const styles = StyleSheet.create({
boxSizing: 'border-box',
color: 'inherit',
font: 'inherit',
padding: 0
padding: 0,
resize: 'none'
}
});

View File

@@ -14,7 +14,6 @@
/* @edit start */
const BoundingDimensions = require('./BoundingDimensions');
const normalizeColor = require('../../modules/normalizeColor');
const Position = require('./Position');
const React = require('react');
const TouchEventUtils = require('fbjs/lib/TouchEventUtils');
@@ -404,6 +403,13 @@ var TouchableMixin = {
*/
touchableHandleResponderRelease: function(e) {
this._receiveSignal(Signals.RESPONDER_RELEASE, e);
// Browsers fire mouse events after touch events. This causes the
// 'onResponderRelease' handler to be called twice for Touchables.
// Auto-fix this issue by calling 'preventDefault' to cancel the mouse
// events.
if (e.cancelable && !e.isDefaultPrevented()) {
e.preventDefault();
}
},
/**

View File

@@ -27,7 +27,6 @@ var ViewStylePropTypes = require('../View/ViewStylePropTypes');
var ensureComponentIsNative = require('./ensureComponentIsNative');
var ensurePositiveDelayProps = require('./ensurePositiveDelayProps');
var keyOf = require('fbjs/lib/keyOf');
type Event = Object;
@@ -226,7 +225,7 @@ var TouchableHighlight = React.createClass({
_onKeyEnter(e, callback) {
var ENTER = 13
if (e.keyCode === ENTER) {
if ((e.type === 'keypress' ? e.charCode : e.keyCode) === ENTER) {
callback && callback(e)
}
},
@@ -268,8 +267,9 @@ var TouchableHighlight = React.createClass({
}
});
var CHILD_REF = keyOf({childRef: null});
var UNDERLAY_REF = keyOf({underlayRef: null});
var CHILD_REF = 'childRef';
var UNDERLAY_REF = 'underlayRef';
var INACTIVE_CHILD_PROPS = {
style: StyleSheet.create({x: {opacity: 1.0}}).x,
};

View File

@@ -87,7 +87,7 @@ var TouchableOpacity = React.createClass({
this.setNativeProps({
style: {
opacity: value,
transitionDuration: duration
transitionDuration: `${duration / 1000}s`
}
});
},
@@ -157,7 +157,7 @@ var TouchableOpacity = React.createClass({
_onKeyEnter(e, callback) {
var ENTER = 13
if (e.keyCode === ENTER) {
if ((e.type === 'keypress' ? e.charCode : e.keyCode) === ENTER) {
callback && callback(e)
}
},

View File

@@ -0,0 +1,37 @@
import BaseComponentPropTypes from '../../propTypes/BaseComponentPropTypes';
import EdgeInsetsPropType from '../../propTypes/EdgeInsetsPropType';
import StyleSheetPropType from '../../propTypes/StyleSheetPropType';
import ViewStylePropTypes from './ViewStylePropTypes';
import { PropTypes } from 'react';
const ViewPropTypes = {
...BaseComponentPropTypes,
children: PropTypes.any,
collapsable: PropTypes.bool,
hitSlop: EdgeInsetsPropType,
onClick: PropTypes.func,
onClickCapture: PropTypes.func,
onLayout: PropTypes.func,
onMoveShouldSetResponder: PropTypes.func,
onMoveShouldSetResponderCapture: PropTypes.func,
onResponderGrant: PropTypes.func,
onResponderMove: PropTypes.func,
onResponderReject: PropTypes.func,
onResponderRelease: PropTypes.func,
onResponderTerminate: PropTypes.func,
onResponderTerminationRequest: PropTypes.func,
onStartShouldSetResponder: PropTypes.func,
onStartShouldSetResponderCapture: PropTypes.func,
onTouchCancel: PropTypes.func,
onTouchCancelCapture: PropTypes.func,
onTouchEnd: PropTypes.func,
onTouchEndCapture: PropTypes.func,
onTouchMove: PropTypes.func,
onTouchMoveCapture: PropTypes.func,
onTouchStart: PropTypes.func,
onTouchStartCapture: PropTypes.func,
pointerEvents: PropTypes.oneOf([ 'auto', 'box-none', 'box-only', 'none' ]),
style: StyleSheetPropType(ViewStylePropTypes)
};
module.exports = ViewPropTypes;

View File

@@ -10,7 +10,7 @@ const { number, oneOf, string } = PropTypes;
const autoOrHiddenOrVisible = oneOf([ 'auto', 'hidden', 'visible' ]);
const hiddenOrVisible = oneOf([ 'hidden', 'visible' ]);
module.exports = process.env.NODE_ENV !== 'production' ? {
module.exports = {
...AnimationPropTypes,
...BorderPropTypes,
...LayoutPropTypes,
@@ -27,8 +27,8 @@ module.exports = process.env.NODE_ENV !== 'production' ? {
backgroundAttachment: string,
backgroundClip: string,
backgroundImage: string,
backgroundPosition: string,
backgroundOrigin: oneOf([ 'border-box', 'content-box', 'padding-box' ]),
backgroundPosition: string,
backgroundRepeat: string,
backgroundSize: string,
boxShadow: string,
@@ -36,11 +36,14 @@ module.exports = process.env.NODE_ENV !== 'production' ? {
outline: string,
overflowX: autoOrHiddenOrVisible,
overflowY: autoOrHiddenOrVisible,
perspective: PropTypes.oneOfType([ number, string ]),
perspectiveOrigin: string,
transitionDelay: string,
transitionDuration: string,
transitionProperty: string,
transitionTimingFunction: string,
userSelect: string,
visibility: hiddenOrVisible,
willChange: string,
WebkitOverflowScrolling: oneOf([ 'auto', 'touch' ])
} : {};
};

View File

@@ -14,9 +14,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -31,8 +31,7 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
style={Object {}}>
rn-textDecoration:none">
<div
className="
rn-alignItems:stretch
@@ -48,9 +47,9 @@ rn-textDecoration:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -66,8 +65,7 @@ rn-textDecoration:none"
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
data-testid="1"
style={Object {}} />
data-testid="1" />
</div>
`;
@@ -87,51 +85,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
rn-marginBottom:0px
rn-marginLeft:0px
rn-minHeight:0px
rn-minWidth:0px
rn-paddingTop:0px
rn-paddingRight:0px
rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
style={
Object {
"pointerEvents": "box-only",
}
} />
`;
exports[`components/View prop "style" 1`] = `
<div
className="
rn-alignItems:stretch
rn-backgroundColor:transparent
rn-borderTopStyle:solid
rn-borderRightStyle:solid
rn-borderBottomStyle:solid
rn-borderLeftStyle:solid
rn-borderTopWidth:0px
rn-borderRightWidth:0px
rn-borderBottomWidth:0px
rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -144,149 +100,13 @@ rn-paddingTop:0px
rn-paddingRight:0px
rn-paddingBottom:0px
rn-paddingLeft:0px
rn-pointerEvents:box-only
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
style={Object {}} />
`;
exports[`components/View prop "style" 2`] = `
<div
className="
rn-alignItems:stretch
rn-backgroundColor:transparent
rn-borderTopStyle:solid
rn-borderRightStyle:solid
rn-borderBottomStyle:solid
rn-borderLeftStyle:solid
rn-borderTopWidth:0px
rn-borderRightWidth:0px
rn-borderBottomWidth:0px
rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexBasis:auto
rn-flexDirection:column
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
rn-marginBottom:0px
rn-marginLeft:0px
rn-minHeight:0px
rn-minWidth:0px
rn-paddingTop:0px
rn-paddingRight:0px
rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
style={
Object {
"WebkitFlexGrow": 1,
"WebkitFlexShrink": 1,
"flexGrow": 1,
"flexShrink": 1,
"msFlexNegative": 1,
"msFlexPositive": 1,
}
} />
`;
exports[`components/View prop "style" 3`] = `
<div
className="
rn-alignItems:stretch
rn-backgroundColor:transparent
rn-borderTopStyle:solid
rn-borderRightStyle:solid
rn-borderBottomStyle:solid
rn-borderLeftStyle:solid
rn-borderTopWidth:0px
rn-borderRightWidth:0px
rn-borderBottomWidth:0px
rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexBasis:auto
rn-flexDirection:column
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
rn-marginBottom:0px
rn-marginLeft:0px
rn-minHeight:0px
rn-minWidth:0px
rn-paddingTop:0px
rn-paddingRight:0px
rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
style={
Object {
"WebkitFlexShrink": 1,
"flexShrink": 1,
"msFlexNegative": 1,
}
} />
`;
exports[`components/View prop "style" 4`] = `
<div
className="
rn-alignItems:stretch
rn-backgroundColor:transparent
rn-borderTopStyle:solid
rn-borderRightStyle:solid
rn-borderBottomStyle:solid
rn-borderLeftStyle:solid
rn-borderTopWidth:0px
rn-borderRightWidth:0px
rn-borderBottomWidth:0px
rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexBasis:auto
rn-flexDirection:column
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
rn-marginRight:0px
rn-marginBottom:0px
rn-marginLeft:0px
rn-minHeight:0px
rn-minWidth:0px
rn-paddingTop:0px
rn-paddingRight:0px
rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
style={
Object {
"WebkitFlexGrow": 1,
"WebkitFlexShrink": 2,
"flexGrow": 1,
"flexShrink": 2,
"msFlexNegative": 2,
"msFlexPositive": 1,
}
} />
`;
exports[`components/View rendered element is a "div" by default 1`] = `
<div
className="
@@ -303,9 +123,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -320,8 +140,7 @@ rn-paddingBottom:0px
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
style={Object {}} />
rn-textDecoration:none" />
`;
exports[`components/View rendered element is a "span" when inside <View accessibilityRole="button" /> 1`] = `
@@ -340,9 +159,9 @@ rn-borderLeftWidth:0px
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -359,7 +178,6 @@ rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
role="button"
style={Object {}}
type="button">
<span
className="
@@ -376,9 +194,9 @@ rn-textDecoration:none"
rn-boxSizing:border-box
rn-color:inherit
rn-display:flex
rn-flexShrink:0
rn-flexBasis:auto
rn-flexDirection:column
rn-flexShrink:0
rn-font:inherit
rn-listStyle:none
rn-marginTop:0px
@@ -393,7 +211,6 @@ rn-textDecoration:none"
rn-paddingLeft:0px
rn-position:relative
rn-textAlign:inherit
rn-textDecoration:none"
style={Object {}} />
rn-textDecoration:none" />
</button>
`;

View File

@@ -29,18 +29,4 @@ describe('components/View', () => {
const component = renderer.create(<View pointerEvents='box-only' />);
expect(component.toJSON()).toMatchSnapshot();
});
test('prop "style"', () => {
let component = renderer.create(<View />);
expect(component.toJSON()).toMatchSnapshot();
component = renderer.create(<View style={{ flex: 1 }} />);
expect(component.toJSON()).toMatchSnapshot();
component = renderer.create(<View style={{ flexShrink: 1 }} />);
expect(component.toJSON()).toMatchSnapshot();
component = renderer.create(<View style={{ flex: 1, flexShrink: 2 }} />);
expect(component.toJSON()).toMatchSnapshot();
});
});

View File

@@ -2,13 +2,10 @@ import '../../modules/injectResponderEventPlugin';
import applyLayout from '../../modules/applyLayout';
import applyNativeMethods from '../../modules/applyNativeMethods';
import BaseComponentPropTypes from '../../propTypes/BaseComponentPropTypes';
import createDOMElement from '../../modules/createDOMElement';
import EdgeInsetsPropType from '../../propTypes/EdgeInsetsPropType';
import normalizeNativeEvent from '../../modules/normalizeNativeEvent';
import StyleSheet from '../../apis/StyleSheet';
import StyleSheetPropType from '../../propTypes/StyleSheetPropType';
import ViewStylePropTypes from './ViewStylePropTypes';
import ViewPropTypes from './ViewPropTypes';
import { Component, PropTypes } from 'react';
const eventHandlerNames = [
@@ -34,38 +31,24 @@ const eventHandlerNames = [
'onTouchStartCapture'
];
const _normalizeEventForHandler = (handler) => (e) => {
e.nativeEvent = normalizeNativeEvent(e.nativeEvent);
return handler(e);
};
const normalizeEventHandlers = (props) => {
eventHandlerNames.forEach((handlerName) => {
const handler = props[handlerName];
if (typeof handler === 'function') {
props[handlerName] = _normalizeEventForHandler(handler);
}
});
};
class View extends Component {
static displayName = 'View';
static propTypes = {
...BaseComponentPropTypes,
children: PropTypes.any,
collapsable: PropTypes.bool,
hitSlop: EdgeInsetsPropType,
onClick: PropTypes.func,
onClickCapture: PropTypes.func,
onLayout: PropTypes.func,
onMoveShouldSetResponder: PropTypes.func,
onMoveShouldSetResponderCapture: PropTypes.func,
onResponderGrant: PropTypes.func,
onResponderMove: PropTypes.func,
onResponderReject: PropTypes.func,
onResponderRelease: PropTypes.func,
onResponderTerminate: PropTypes.func,
onResponderTerminationRequest: PropTypes.func,
onStartShouldSetResponder: PropTypes.func,
onStartShouldSetResponderCapture: PropTypes.func,
onTouchCancel: PropTypes.func,
onTouchCancelCapture: PropTypes.func,
onTouchEnd: PropTypes.func,
onTouchEndCapture: PropTypes.func,
onTouchMove: PropTypes.func,
onTouchMoveCapture: PropTypes.func,
onTouchStart: PropTypes.func,
onTouchStartCapture: PropTypes.func,
pointerEvents: PropTypes.oneOf([ 'auto', 'box-none', 'box-only', 'none' ]),
style: StyleSheetPropType(ViewStylePropTypes)
};
static propTypes = ViewPropTypes;
static defaultProps = {
accessible: true
@@ -102,47 +85,19 @@ class View extends Component {
...otherProps
} = this.props;
const flattenedStyle = StyleSheet.flatten(style);
const pointerEventsStyle = pointerEvents && { pointerEvents };
// 'View' needs to set 'flexShrink:0' only when there is no 'flex' or 'flexShrink' style provided
const needsFlexReset = !flattenedStyle || (flattenedStyle.flex == null && flattenedStyle.flexShrink == null);
const component = this.context.isInAButtonView ? 'span' : 'div';
eventHandlerNames.reduce((props, handlerName) => {
const handler = this.props[handlerName];
if (typeof handler === 'function') {
props[handlerName] = this._normalizeEventForHandler(handler, handlerName);
}
return props;
}, otherProps);
// DOM events need to be normalized to expect RN format
normalizeEventHandlers(otherProps);
otherProps.style = [
styles.initial,
style,
needsFlexReset && styles.flexReset,
pointerEventsStyle
pointerEvents && pointerEventStyles[pointerEvents]
];
return createDOMElement(component, otherProps);
}
_normalizeEventForHandler(handler, handlerName) {
// Browsers fire mouse events after touch events. This causes the
// 'onResponderRelease' handler to be called twice for Touchables.
// Auto-fix this issue by calling 'preventDefault' to cancel the mouse
// events.
const shouldCancelEvent = handlerName === 'onResponderRelease';
return (e) => {
e.nativeEvent = normalizeNativeEvent(e.nativeEvent);
const returnValue = handler(e);
if (shouldCancelEvent && e.cancelable) {
e.preventDefault();
}
return returnValue;
};
}
}
const styles = StyleSheet.create({
@@ -169,9 +124,21 @@ const styles = StyleSheet.create({
// fix flexbox bugs
minHeight: 0,
minWidth: 0
}
});
const pointerEventStyles = StyleSheet.create({
'auto': {
pointerEvents: 'auto'
},
flexReset: {
flexShrink: 0
'box-none': {
pointerEvents: 'box-none'
},
'box-only': {
pointerEvents: 'box-only'
},
'none': {
pointerEvents: 'none'
}
});

View File

@@ -1,8 +1,5 @@
import findNodeHandle from './modules/findNodeHandle';
import ReactDefaultInjection from 'react-dom/lib/ReactDefaultInjection';
import { render, unmountComponentAtNode } from 'react-dom/lib/ReactMount';
ReactDefaultInjection.inject();
import { render, unmountComponentAtNode } from 'react-dom';
// APIs
import I18nManager from './apis/I18nManager';
@@ -21,6 +18,9 @@ import View from './components/View';
// modules
import createDOMElement from './modules/createDOMElement';
import modality from './modules/modality';
modality();
const ReactNativeCore = {
createDOMElement,

Some files were not shown because too many files have changed in this diff Show More