Compare commits

...

34 Commits

Author SHA1 Message Date
Nicolas Gallagher
3d79861970 0.0.129 2017-09-21 14:20:37 -07:00
Nicolas Gallagher
0a84ccb299 [fix] IE10 flexbox support
Add prefixes for flexbox (and other) support in IE10.

Ref #650
2017-09-21 14:18:11 -07:00
Nicolas Gallagher
3aa37450a0 Improve error message for text nodes in View 2017-09-21 14:04:41 -07:00
Nicolas Gallagher
450722153d 0.0.128 2017-09-20 09:45:25 -07:00
Nicolas Gallagher
fbba32defb [fix] cross-browser flex styles
Fix #616
Close #648
2017-09-19 15:44:10 -07:00
Nicolas Gallagher
d762d64b49 Revert SSR Image change
Reverts 3c660e2ad7

See #543
2017-09-19 15:23:09 -07:00
Nicolas Gallagher
a5b1dda62d 0.0.127 2017-09-19 15:12:13 -07:00
Nicolas Gallagher
aad904b550 [fix] remove 'use strict' from warnValidStyle 2017-09-19 15:07:54 -07:00
Unknown
a01e895e30 [change] RefreshControl placeholder
Fix #638
Close #644
2017-09-19 13:44:31 -07:00
Nicolas Gallagher
52e5d41518 [fix] keyboard interaction with Touchable as link
Fix #643
Close #645
2017-09-19 13:40:57 -07:00
Nicolas Gallagher
77a40b6237 [fix] Easing import when using babel plugin
Fix #649
2017-09-19 13:37:12 -07:00
Nicolas Gallagher
4bbe1a40aa 0.0.126 2017-09-18 21:08:39 -07:00
Nicolas Gallagher
6942e4e417 Shallow render ActivityIndicator tests
These snapshots should be improved by flattening the React Native style
object.
2017-09-18 19:47:03 -07:00
Nicolas Gallagher
63daff7f80 Simplify Switch tests 2017-09-18 19:32:02 -07:00
Nicolas Gallagher
662b7c3d6e Simplify Image snapshot testing 2017-09-18 19:26:48 -07:00
Nicolas Gallagher
12fb588596 Simplify View snapshot testing 2017-09-18 19:26:11 -07:00
Nicolas Gallagher
5cb09b1a9e [fix] disallow text node children of View
Catch text nodes that are not the only child of View. Fixes a case
missing from 0ad6ab948b.
2017-09-18 13:28:51 -07:00
Nicolas Gallagher
c03cfdf8bd Add compile task to build task 2017-09-17 11:25:50 -07:00
Nicolas Gallagher
997b598de8 [fix] event normalization
Work better with simulated events, and avoid crashing if
'nativeEvent.target' isn't an element node.

Close #597
2017-09-15 15:16:40 -07:00
Nicolas Gallagher
6fe796f9da [add] accessibilityRole 'label' to Text 2017-09-15 11:29:44 -07:00
Nicolas Gallagher
0ad6ab948b [fix] disallow text node children of View
Fix #627
2017-09-15 11:29:41 -07:00
Nicolas Gallagher
32a23136af 0.0.125 2017-09-14 15:16:52 -07:00
Nicolas Gallagher
96f48226cb [fix] ColorPropType validation
Check color is of type string before using `indexOf`.

Fix #630
2017-09-14 13:19:13 -07:00
Peter Schussheim
f1ef0f21af Fix typo in NetInfo docs 2017-09-14 11:31:18 -07:00
Unknown
d42e8907ca [fix] return value of Keyboard.addListener
Close #631
Fix #632
2017-09-14 11:26:46 -07:00
Nicolas Gallagher
90724b2cef [fix] filter unsupported ScrollView props
Fix #633
2017-09-14 11:20:18 -07:00
Nicolas Gallagher
dd0f1de3d1 [fix] avoid prop types check on UnimplementedView
Fix #635
2017-09-14 11:08:36 -07:00
Nicolas Gallagher
fc751ed715 [fix] remove TouchalbeWithoutFeedback children prop type
Fix #634
2017-09-14 10:49:49 -07:00
Nicolas Gallagher
917b06a690 Update README 2017-09-13 11:27:36 -07:00
Nicolas Gallagher
80cb7baf82 0.0.124 2017-09-12 15:58:28 -07:00
Nicolas Gallagher
f08515b1f1 Avoid compiling tests 2017-09-12 15:58:14 -07:00
Nicolas Gallagher
8591bf7ce5 [fix] add AppState to Babel plugin list 2017-09-12 15:46:27 -07:00
Nicolas Gallagher
b7c8f00fcc 0.0.123 2017-09-12 11:31:49 -07:00
Nicolas Gallagher
ed81b985a9 Include the babel dir in published package 2017-09-12 11:31:38 -07:00
38 changed files with 871 additions and 523 deletions

View File

@@ -3,19 +3,23 @@
[![Build Status][travis-image]][travis-url]
[![npm version][npm-image]][npm-url]
"React Native for Web" brings [React Native][react-native-url]'s
building blocks and touch handling to the Web.
"React Native for Web" brings the platform-agnostic Components and APIs of
[React Native][react-native-url] to the Web.
* [UI Explorer and documentation](https://necolas.github.io/react-native-web/storybook/).
* [React Native for Web: Playground](https://glitch.com/edit/#!/react-native-web-playground) using create-react-app.
Browse the [interactive
documentation](https://necolas.github.io/react-native-web/storybook/) or [try
it out](https://glitch.com/edit/#!/react-native-web-playground) on Glitch.
Browser support: Chrome, Firefox, Safari >= 7, IE 10, Edge.
## Features
[npm-image]: https://badge.fury.io/js/react-native-web.svg
[npm-url]: https://npmjs.org/package/react-native-web
[react-native-url]: https://facebook.github.io/react-native/
[travis-image]: https://travis-ci.org/necolas/react-native-web.svg?branch=master
[travis-url]: https://travis-ci.org/necolas/react-native-web
* Interoperability with ReactDOM components.
* Native-like touch handling.
* Built-in integration with web accessibility APIs.
* Built-in support for LTR and RTL layouts.
* Built-in expressive and reliable subset of CSS.
* Optimized, vendor-prefixed CSS with [good runtime performance](benchmarks/README.md).
* Server-side rendering of HTML and critical CSS.
* Browser support: Chrome, Firefox, Safari >= 7, IE 10, Edge.
## Quick start
@@ -27,12 +31,28 @@ Install in your existing app using `yarn` or `npm`:
yarn add react@15.6 react-dom@15.6 react-native-web
```
Then read the [Getting Started](docs/guides/getting-started.md) guide.
Add the `react-native-web/babel` plugin to your Babel configuration. This will
alias `react-native` to `react-native-web` and exclude any modules not required
by the app.
```json
{
"plugins": [
"react-native-web/babel"
],
"presets": [
"react-native"
]
}
```
See the [Getting Started](docs/guides/getting-started.md) guide for more details.
## Documentation
The [UI Explorer](https://necolas.github.io/react-native-web/storybook/)
interactively documents all the supported APIs and Components.
The [interactive
documentation](https://necolas.github.io/react-native-web/storybook/) shows all
the supported APIs and Components.
Guides:
@@ -46,7 +66,8 @@ Guides:
## Starter kits
* [create-react-app](https://github.com/facebookincubator/create-react-app) ([on Glitch](https://glitch.com/edit/#!/react-native-web-playground))
* [Glitch](https://glitch.com/edit/#!/react-native-web-playground)
* [create-react-app](https://github.com/facebookincubator/create-react-app)
* [react-native-web-starter](https://github.com/grabcode/react-native-web-starter)
* [react-native-web-webpack](https://github.com/ndbroadbent/react-native-web-webpack)
@@ -99,3 +120,9 @@ AppRegistry.runApplication('MyApp', { rootTag: document.getElementById('react-ro
## License
React Native for Web is [BSD licensed](LICENSE).
[npm-image]: https://badge.fury.io/js/react-native-web.svg
[npm-url]: https://npmjs.org/package/react-native-web
[react-native-url]: https://facebook.github.io/react-native/
[travis-image]: https://travis-ci.org/necolas/react-native-web.svg?branch=master
[travis-url]: https://travis-ci.org/necolas/react-native-web

View File

@@ -5,6 +5,7 @@ const getDistLocation = importName => {
// apis
case 'Animated':
case 'AppRegistry':
case 'AppState':
case 'AsyncStorage':
case 'BackAndroid':
case 'Clipboard':

View File

@@ -20,7 +20,7 @@ const NetInfoScreen = () => (
NetInfo asynchronously determines the online/offline status of the application.
</AppText>
<AppText>
Note that support for retrieving the connection type depends upon browswer support (and is
Note that support for retrieving the connection type depends upon browser support (and is
limited to mobile browsers). It will default to <Code>unknown</Code> when support is
missing.
</AppText>

View File

@@ -14,7 +14,6 @@
* @providesModule Game2048
* @flow
*/
'use strict';
import { any, func, object } from 'prop-types';
import GameBoard from './GameBoard';

View File

@@ -14,7 +14,6 @@
* @providesModule GameBoard
* @flow
*/
'use strict';
// NB: Taken straight from: https://github.com/IvanVergiliev/2048-react/blob/master/src/board.js
// with no modification except to format it for CommonJS and fix lint/flow errors

View File

@@ -1,17 +1,19 @@
{
"name": "react-native-web",
"version": "0.0.122",
"version": "0.0.129",
"description": "React Native for Web",
"main": "dist/index.js",
"files": [
"babel",
"dist",
"src",
"!**/__tests__"
],
"scripts": {
"benchmark": "cd benchmarks && yarn && webpack && open index.html",
"build": "webpack --config webpack.config.js --sort-assets-by --progress",
"compile": "del ./dist && mkdir dist && babel src -d dist --ignore **/__tests__",
"build": "yarn compile && webpack --config webpack.config.js --sort-assets-by --progress",
"clean-dist": "del ./dist && mkdir dist",
"compile": "babel src -d dist --ignore *-test.js",
"docs:build": "cd docs && yarn build",
"docs:start": "cd docs && yarn && yarn start",
"docs:release": "cd docs && yarn release",
@@ -23,7 +25,7 @@
"lint": "yarn lint:cmd -- babel benchmarks docs src",
"lint:cmd": "eslint --ignore-path .gitignore --fix",
"precommit": "lint-staged",
"release": "yarn lint && yarn test && yarn compile && yarn build && npm publish",
"release": "yarn clean-dist && yarn lint && yarn test && yarn build && npm publish",
"test": "flow && jest"
},
"babel": {

View File

@@ -7,7 +7,7 @@ const browserList = {
firefox: 40,
ios_saf: 7,
safari: 7,
ie: 11,
ie: 10,
ie_mob: 11,
edge: 12,
opera: 16,

View File

@@ -38,7 +38,7 @@ exports[`apis/AppRegistry/renderApplication getApplication 3`] = `
.rn-textAlign-1ttztb7{text-align:inherit}
.rn-textDecoration-bauka4{text-decoration:none}
.rn-listStyle-1ebb2ja{list-style:none}
.rn-alignItems-1oszu61{-webkit-align-items:stretch;-webkit-box-align:stretch;align-items:stretch}
.rn-alignItems-1oszu61{-ms-flex-align:stretch;-webkit-align-items:stretch;-webkit-box-align:stretch;align-items:stretch}
.rn-borderTopStyle-1efd50x{border-top-style:solid}
.rn-borderRightStyle-14skgim{border-right-style:solid}
.rn-borderBottomStyle-rull8r{border-bottom-style:solid}
@@ -50,11 +50,10 @@ exports[`apis/AppRegistry/renderApplication getApplication 3`] = `
.rn-boxSizing-deolkf{box-sizing:border-box}
.rn-display-6koalj{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}
.rn-display-xoduu5{display:-webkit-inline-box;display:-moz-inline-box;display:-ms-inline-flexbox;display:-webkit-inline-flex;display:inline-flex}
.rn-flexShrink-1qe8dj5{-webkit-flex-shrink:0;flex-shrink:0}
.rn-flexShrink-1wbh5a2{-webkit-flex-shrink:1;flex-shrink:1}
.rn-flexBasis-1mlwlqe{-webkit-flex-basis:auto;flex-basis:auto}
.rn-flexBasis-1ro0kt6{-webkit-flex-basis:0%;flex-basis:0%}
.rn-flexDirection-eqz5dr{-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column}
.rn-flexShrink-1pxmb3b{-ms-flex-negative:0 !important;-webkit-flex-shrink:0 !important;flex-shrink:0 !important}
.rn-flexShrink-1awmn5t{-ms-flex-negative:1 !important;-webkit-flex-shrink:1 !important;flex-shrink:1 !important}
.rn-flexBasis-7vfszb{-ms-flex-preferred-size:auto !important;-webkit-flex-basis:auto !important;flex-basis:auto !important}
.rn-flexDirection-eqz5dr{-ms-flex-direction:column;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column}
.rn-marginTop-1mnahxq{margin-top:0px}
.rn-marginRight-61z16t{margin-right:0px}
.rn-marginBottom-p1pxzi{margin-bottom:0px}
@@ -67,5 +66,6 @@ exports[`apis/AppRegistry/renderApplication getApplication 3`] = `
.rn-paddingLeft-gy4na3{padding-left:0px}
.rn-zIndex-1lgpqti{z-index:0}
.rn-zIndex-1wyyakw{z-index:-1}
.rn-flexGrow-16y2uox{-webkit-flex-grow:1;flex-grow:1}</style>"
.rn-flex-13awgt0{-ms-flex:1;-webkit-flex:1;flex:1}
.rn-flexGrow-1m1wadx{-ms-flex-positive:1 !important;-webkit-flex-grow:1 !important;flex-grow:1 !important}</style>"
`;

13
src/apis/Easing/index.js Normal file
View File

@@ -0,0 +1,13 @@
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule Easing
* @noflow
*/
import Easing from 'animated/lib/Easing';
export default Easing;

View File

@@ -13,7 +13,9 @@
import dismissKeyboard from '../../modules/dismissKeyboard';
const Keyboard = {
addListener() {},
addListener() {
return { remove: () => {} };
},
dismiss() {
dismissKeyboard();
},

View File

@@ -26,44 +26,44 @@ describe('apis/StyleSheet/createReactDOMStyle', () => {
test('flex defaults', () => {
expect(createReactDOMStyle({ display: 'flex' })).toEqual({
display: 'flex',
flexShrink: 0,
flexBasis: 'auto'
flexShrink: '0 !important',
flexBasis: 'auto !important'
});
});
test('flex: -1', () => {
expect(createReactDOMStyle({ display: 'flex', flex: -1 })).toEqual({
display: 'flex',
flexGrow: 0,
flexShrink: 1,
flexBasis: 'auto'
flexGrow: '0 !important',
flexShrink: '1 !important',
flexBasis: 'auto !important'
});
});
test('flex: 0', () => {
expect(createReactDOMStyle({ display: 'flex', flex: 0 })).toEqual({
display: 'flex',
flexGrow: 0,
flexShrink: 0,
flexBasis: 'auto'
flexGrow: '0 !important',
flexShrink: '0 !important',
flexBasis: 'auto !important'
});
});
test('flex: 1', () => {
expect(createReactDOMStyle({ display: 'flex', flex: 1 })).toEqual({
display: 'flex',
flexGrow: 1,
flexShrink: 1,
flexBasis: '0%'
flex: 1,
flexGrow: '1 !important',
flexShrink: '1 !important'
});
});
test('flex: 10', () => {
expect(createReactDOMStyle({ display: 'flex', flex: 10 })).toEqual({
display: 'flex',
flexGrow: 10,
flexShrink: 1,
flexBasis: '0%'
flex: 10,
flexGrow: '10 !important',
flexShrink: '1 !important'
});
});
@@ -71,16 +71,17 @@ describe('apis/StyleSheet/createReactDOMStyle', () => {
// is flex-basis applied?
expect(createReactDOMStyle({ display: 'flex', flexBasis: '25%' })).toEqual({
display: 'flex',
flexShrink: 0,
flexBasis: '25%'
flexShrink: '0 !important',
flexBasis: '25% !important'
});
// can flex-basis override the 'flex' expansion?
expect(createReactDOMStyle({ display: 'flex', flex: 1, flexBasis: '25%' })).toEqual({
display: 'flex',
flexGrow: 1,
flexShrink: 1,
flexBasis: '25%'
flex: 1,
flexGrow: '1 !important',
flexShrink: '1 !important',
flexBasis: '25% !important'
});
});
@@ -88,16 +89,16 @@ describe('apis/StyleSheet/createReactDOMStyle', () => {
// is flex-shrink applied?
expect(createReactDOMStyle({ display: 'flex', flexShrink: 1 })).toEqual({
display: 'flex',
flexShrink: 1,
flexBasis: 'auto'
flexShrink: '1 !important',
flexBasis: 'auto !important'
});
// can flex-shrink override the 'flex' expansion?
expect(createReactDOMStyle({ display: 'flex', flex: 1, flexShrink: 2 })).toEqual({
display: 'flex',
flexGrow: 1,
flexShrink: 2,
flexBasis: '0%'
flex: 1,
flexGrow: '1 !important',
flexShrink: '2 !important'
});
});
});

View File

@@ -158,29 +158,56 @@ const createReducer = (style, styleProps) => {
case 'display': {
resolvedStyle.display = value;
// defaults of 'flexBasis:auto' and 'flexShrink:0' have lowest precedence
if (style.display === 'flex') {
// A flex container in React Native has these defaults which should be
// set only if there is no otherwise supplied flex style.
if (style.display === 'flex' && style.flex == null) {
if (style.flexShrink == null) {
resolvedStyle.flexShrink = 0;
resolvedStyle.flexShrink = '0 !important';
}
if (style.flexBasis == null) {
resolvedStyle.flexBasis = 'auto';
resolvedStyle.flexBasis = 'auto !important';
}
}
break;
}
// The 'flex' property value in React Native must be a positive integer,
// 0, or -1.
//
// On the web, a positive integer value for 'flex' is complicated by
// browser differences. Although browsers render styles like 'flex:2'
// consistently, they don't all set the same value for the resulting
// 'flexBasis' (See #616). Expanding 'flex' in 'StyleSheet' would mean
// setting different values for different browsers.
//
// This fix instead relies on the browser expanding 'flex' itself. And
// because the 'flex' style is not being expanded the generated CSS is
// likely to contain source order "conflicts". To avoid the browser
// relying on source order to resolve the styles, all the longhand flex
// property values must use '!important'.
case 'flex': {
if (value > 0) {
resolvedStyle.flexGrow = value;
resolvedStyle.flexShrink = 1;
resolvedStyle.flexBasis = '0%';
resolvedStyle.flex = value;
resolvedStyle.flexGrow = `${value} !important`;
resolvedStyle.flexShrink = '1 !important';
} else if (value === 0) {
resolvedStyle.flexGrow = 0;
resolvedStyle.flexShrink = 0;
resolvedStyle.flexGrow = '0 !important';
resolvedStyle.flexShrink = '0 !important';
resolvedStyle.flexBasis = 'auto !important';
} else if (value === -1) {
resolvedStyle.flexGrow = 0;
resolvedStyle.flexShrink = 1;
resolvedStyle.flexGrow = '0 !important';
resolvedStyle.flexShrink = '1 !important';
resolvedStyle.flexBasis = 'auto !important';
}
break;
}
case 'flexGrow':
case 'flexShrink':
case 'flexBasis': {
if (value != null) {
const hasImportant = `${value}`.indexOf('!important') > -1;
resolvedStyle[prop] = hasImportant ? value : `${value} !important`;
}
break;
}

View File

@@ -1,18 +1,30 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/ActivityIndicator prop "animating" is "false" 1`] = `
<div
<View
accessibilityRole="progressbar"
aria-valuemax="1"
aria-valuemin="0"
class="rn-alignItems-1awozwy rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-justifyContent-1777fci rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim"
role="progressbar"
style={
Array [
15,
undefined,
]
}
>
<div
class="rn-alignItems-1oszu61 rn-animationDuration-17bb2tj rn-animationIterationCount-1muvv40 rn-animationName-dozj4v rn-animationPlayState-1abnn5w rn-animationTimingFunction-1ldzwu0 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-height-z80fyv rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-visibility-11j9u27 rn-width-19wmn03"
<View
style={
Array [
19,
17,
18,
16,
]
}
>
<svg
height="100%"
viewbox="0 0 32 32"
viewBox="0 0 32 32"
width="100%"
>
<circle
@@ -20,35 +32,58 @@ exports[`components/ActivityIndicator prop "animating" is "false" 1`] = `
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;opacity:0.2;"
strokeWidth="4"
style={
Object {
"opacity": 0.2,
"stroke": "#1976D2",
}
}
/>
<circle
cx="16"
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;stroke-dasharray:80;stroke-dashoffset:60;"
strokeWidth="4"
style={
Object {
"stroke": "#1976D2",
"strokeDasharray": 80,
"strokeDashoffset": 60,
}
}
/>
</svg>
</div>
</div>
</View>
</View>
`;
exports[`components/ActivityIndicator prop "animating" is "true" 1`] = `
<div
<View
accessibilityRole="progressbar"
aria-valuemax="1"
aria-valuemin="0"
class="rn-alignItems-1awozwy rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-justifyContent-1777fci rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim"
role="progressbar"
style={
Array [
15,
undefined,
]
}
>
<div
class="rn-alignItems-1oszu61 rn-animationDuration-17bb2tj rn-animationIterationCount-1muvv40 rn-animationName-dozj4v rn-animationTimingFunction-1ldzwu0 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-height-z80fyv rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-width-19wmn03"
<View
style={
Array [
19,
17,
false,
false,
]
}
>
<svg
height="100%"
viewbox="0 0 32 32"
viewBox="0 0 32 32"
width="100%"
>
<circle
@@ -56,71 +91,94 @@ exports[`components/ActivityIndicator prop "animating" is "true" 1`] = `
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;opacity:0.2;"
strokeWidth="4"
style={
Object {
"opacity": 0.2,
"stroke": "#1976D2",
}
}
/>
<circle
cx="16"
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;stroke-dasharray:80;stroke-dashoffset:60;"
strokeWidth="4"
style={
Object {
"stroke": "#1976D2",
"strokeDasharray": 80,
"strokeDashoffset": 60,
}
}
/>
</svg>
</div>
</div>
</View>
</View>
`;
exports[`components/ActivityIndicator prop "color" 1`] = `
<div
aria-valuemax="1"
aria-valuemin="0"
class="rn-alignItems-1awozwy rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-justifyContent-1777fci rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim"
role="progressbar"
<svg
height="100%"
viewBox="0 0 32 32"
width="100%"
>
<div
class="rn-alignItems-1oszu61 rn-animationDuration-17bb2tj rn-animationIterationCount-1muvv40 rn-animationName-dozj4v rn-animationTimingFunction-1ldzwu0 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-height-z80fyv rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-width-19wmn03"
>
<svg
height="100%"
viewbox="0 0 32 32"
width="100%"
>
<circle
cx="16"
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:red;opacity:0.2;"
/>
<circle
cx="16"
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:red;stroke-dasharray:80;stroke-dashoffset:60;"
/>
</svg>
</div>
</div>
<circle
cx="16"
cy="16"
fill="none"
r="14"
strokeWidth="4"
style={
Object {
"opacity": 0.2,
"stroke": "red",
}
}
/>
<circle
cx="16"
cy="16"
fill="none"
r="14"
strokeWidth="4"
style={
Object {
"stroke": "red",
"strokeDasharray": 80,
"strokeDashoffset": 60,
}
}
/>
</svg>
`;
exports[`components/ActivityIndicator prop "hidesWhenStopped" is "false" 1`] = `
<div
<View
accessibilityRole="progressbar"
aria-valuemax="1"
aria-valuemin="0"
class="rn-alignItems-1awozwy rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-justifyContent-1777fci rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim"
role="progressbar"
style={
Array [
15,
undefined,
]
}
>
<div
class="rn-alignItems-1oszu61 rn-animationDuration-17bb2tj rn-animationIterationCount-1muvv40 rn-animationName-dozj4v rn-animationPlayState-1abnn5w rn-animationTimingFunction-1ldzwu0 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-height-z80fyv rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-width-19wmn03"
<View
style={
Array [
19,
17,
18,
false,
]
}
>
<svg
height="100%"
viewbox="0 0 32 32"
viewBox="0 0 32 32"
width="100%"
>
<circle
@@ -128,35 +186,58 @@ exports[`components/ActivityIndicator prop "hidesWhenStopped" is "false" 1`] = `
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;opacity:0.2;"
strokeWidth="4"
style={
Object {
"opacity": 0.2,
"stroke": "#1976D2",
}
}
/>
<circle
cx="16"
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;stroke-dasharray:80;stroke-dashoffset:60;"
strokeWidth="4"
style={
Object {
"stroke": "#1976D2",
"strokeDasharray": 80,
"strokeDashoffset": 60,
}
}
/>
</svg>
</div>
</div>
</View>
</View>
`;
exports[`components/ActivityIndicator prop "hidesWhenStopped" is "true" 1`] = `
<div
<View
accessibilityRole="progressbar"
aria-valuemax="1"
aria-valuemin="0"
class="rn-alignItems-1awozwy rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-justifyContent-1777fci rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim"
role="progressbar"
style={
Array [
15,
undefined,
]
}
>
<div
class="rn-alignItems-1oszu61 rn-animationDuration-17bb2tj rn-animationIterationCount-1muvv40 rn-animationName-dozj4v rn-animationPlayState-1abnn5w rn-animationTimingFunction-1ldzwu0 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-height-z80fyv rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-visibility-11j9u27 rn-width-19wmn03"
<View
style={
Array [
19,
17,
18,
16,
]
}
>
<svg
height="100%"
viewbox="0 0 32 32"
viewBox="0 0 32 32"
width="100%"
>
<circle
@@ -164,35 +245,58 @@ exports[`components/ActivityIndicator prop "hidesWhenStopped" is "true" 1`] = `
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;opacity:0.2;"
strokeWidth="4"
style={
Object {
"opacity": 0.2,
"stroke": "#1976D2",
}
}
/>
<circle
cx="16"
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;stroke-dasharray:80;stroke-dashoffset:60;"
strokeWidth="4"
style={
Object {
"stroke": "#1976D2",
"strokeDasharray": 80,
"strokeDashoffset": 60,
}
}
/>
</svg>
</div>
</div>
</View>
</View>
`;
exports[`components/ActivityIndicator prop "size" is "large" 1`] = `
<div
<View
accessibilityRole="progressbar"
aria-valuemax="1"
aria-valuemin="0"
class="rn-alignItems-1awozwy rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-justifyContent-1777fci rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim"
role="progressbar"
style={
Array [
15,
undefined,
]
}
>
<div
class="rn-alignItems-1oszu61 rn-animationDuration-17bb2tj rn-animationIterationCount-1muvv40 rn-animationName-dozj4v rn-animationTimingFunction-1ldzwu0 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-height-1r8g8re rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-width-1acpoxo"
<View
style={
Array [
20,
17,
false,
false,
]
}
>
<svg
height="100%"
viewbox="0 0 32 32"
viewBox="0 0 32 32"
width="100%"
>
<circle
@@ -200,36 +304,61 @@ exports[`components/ActivityIndicator prop "size" is "large" 1`] = `
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;opacity:0.2;"
strokeWidth="4"
style={
Object {
"opacity": 0.2,
"stroke": "#1976D2",
}
}
/>
<circle
cx="16"
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;stroke-dasharray:80;stroke-dashoffset:60;"
strokeWidth="4"
style={
Object {
"stroke": "#1976D2",
"strokeDasharray": 80,
"strokeDashoffset": 60,
}
}
/>
</svg>
</div>
</div>
</View>
</View>
`;
exports[`components/ActivityIndicator prop "size" is a number 1`] = `
<div
<View
accessibilityRole="progressbar"
aria-valuemax="1"
aria-valuemin="0"
class="rn-alignItems-1awozwy rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-justifyContent-1777fci rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim"
role="progressbar"
style={
Array [
15,
undefined,
]
}
>
<div
class="rn-alignItems-1oszu61 rn-animationDuration-17bb2tj rn-animationIterationCount-1muvv40 rn-animationName-dozj4v rn-animationTimingFunction-1ldzwu0 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim"
style="height:30px;width:30px;"
<View
style={
Array [
Object {
"height": 30,
"width": 30,
},
17,
false,
false,
]
}
>
<svg
height="100%"
viewbox="0 0 32 32"
viewBox="0 0 32 32"
width="100%"
>
<circle
@@ -237,18 +366,29 @@ exports[`components/ActivityIndicator prop "size" is a number 1`] = `
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;opacity:0.2;"
strokeWidth="4"
style={
Object {
"opacity": 0.2,
"stroke": "#1976D2",
}
}
/>
<circle
cx="16"
cy="16"
fill="none"
r="14"
stroke-width="4"
style="stroke:#1976D2;stroke-dasharray:80;stroke-dashoffset:60;"
strokeWidth="4"
style={
Object {
"stroke": "#1976D2",
"strokeDasharray": 80,
"strokeDashoffset": 60,
}
}
/>
</svg>
</div>
</div>
</View>
</View>
`;

View File

@@ -2,46 +2,46 @@
import ActivityIndicator from '..';
import React from 'react';
import { render } from 'enzyme';
import { shallow } from 'enzyme';
describe('components/ActivityIndicator', () => {
describe('prop "animating"', () => {
test('is "true"', () => {
const component = render(<ActivityIndicator animating={true} />);
const component = shallow(<ActivityIndicator animating={true} />);
expect(component).toMatchSnapshot();
});
test('is "false"', () => {
const component = render(<ActivityIndicator animating={false} />);
const component = shallow(<ActivityIndicator animating={false} />);
expect(component).toMatchSnapshot();
});
});
test('prop "color"', () => {
const component = render(<ActivityIndicator color="red" />);
const component = shallow(<ActivityIndicator color="red" />).find('svg');
expect(component).toMatchSnapshot();
});
describe('prop "hidesWhenStopped"', () => {
test('is "true"', () => {
const component = render(<ActivityIndicator animating={false} hidesWhenStopped={true} />);
const component = shallow(<ActivityIndicator animating={false} hidesWhenStopped={true} />);
expect(component).toMatchSnapshot();
});
test('is "false"', () => {
const component = render(<ActivityIndicator animating={false} hidesWhenStopped={false} />);
const component = shallow(<ActivityIndicator animating={false} hidesWhenStopped={false} />);
expect(component).toMatchSnapshot();
});
});
describe('prop "size"', () => {
test('is "large"', () => {
const component = render(<ActivityIndicator size="large" />);
const component = shallow(<ActivityIndicator size="large" />);
expect(component).toMatchSnapshot();
});
test('is a number', () => {
const component = render(<ActivityIndicator size={30} />);
const component = shallow(<ActivityIndicator size={30} />);
expect(component).toMatchSnapshot();
});
});

View File

@@ -1,138 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/Image passes other props through to underlying View 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`components/Image prop "defaultSource" sets background image when value is a string 1`] = `"url(\\"https://google.com/favicon.ico\\")"`;
exports[`components/Image prop "accessibilityLabel" 1`] = `
<div
aria-label="accessibilityLabel"
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
style="background-image:url(\\"https://google.com/favicon.ico\\");"
>
<img
alt="accessibilityLabel"
class="rn-bottom-1p0dtai rn-height-1pi2tsx rn-left-1d2f490 rn-opacity-1272l3b rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-width-13qz1uu rn-zIndex-1wyyakw"
src="https://google.com/favicon.ico"
/>
</div>
`;
exports[`components/Image prop "defaultSource" sets background image when value is an object 1`] = `"url(\\"https://google.com/favicon.ico\\")"`;
exports[`components/Image prop "accessible" 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`components/Image prop "resizeMode" value "contain" 1`] = `"contain"`;
exports[`components/Image prop "children" 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
>
<div
class="unique"
/>
</div>
`;
exports[`components/Image prop "resizeMode" value "cover" 1`] = `"cover"`;
exports[`components/Image prop "defaultSource" does not override "height" and "width" styles 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
style="background-image:url(\\"https://google.com/favicon.ico\\");height:20px;width:40px;"
>
<img
alt=""
class="rn-bottom-1p0dtai rn-height-1pi2tsx rn-left-1d2f490 rn-opacity-1272l3b rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-width-13qz1uu rn-zIndex-1wyyakw"
src="https://google.com/favicon.ico"
/>
</div>
`;
exports[`components/Image prop "resizeMode" value "none" 1`] = `"auto"`;
exports[`components/Image prop "defaultSource" sets "height" and "width" styles if missing 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
style="background-image:url(\\"https://google.com/favicon.ico\\");height:10px;width:20px;"
>
<img
alt=""
class="rn-bottom-1p0dtai rn-height-1pi2tsx rn-left-1d2f490 rn-opacity-1272l3b rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-width-13qz1uu rn-zIndex-1wyyakw"
src="https://google.com/favicon.ico"
/>
</div>
`;
exports[`components/Image prop "resizeMode" value "stretch" 1`] = `"100% 100%"`;
exports[`components/Image prop "defaultSource" sets background image when value is a string 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
style="background-image:url(\\"https://google.com/favicon.ico\\");"
>
<img
alt=""
class="rn-bottom-1p0dtai rn-height-1pi2tsx rn-left-1d2f490 rn-opacity-1272l3b rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-width-13qz1uu rn-zIndex-1wyyakw"
src="https://google.com/favicon.ico"
/>
</div>
`;
exports[`components/Image prop "resizeMode" value "undefined" 1`] = `"cover"`;
exports[`components/Image prop "defaultSource" sets background image when value is an object 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
style="background-image:url(\\"https://google.com/favicon.ico\\");"
>
<img
alt=""
class="rn-bottom-1p0dtai rn-height-1pi2tsx rn-left-1d2f490 rn-opacity-1272l3b rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-width-13qz1uu rn-zIndex-1wyyakw"
src="https://google.com/favicon.ico"
/>
</div>
`;
exports[`components/Image prop "resizeMode" value "contain" 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-ehq7j7 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`components/Image prop "resizeMode" value "cover" 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`components/Image prop "resizeMode" value "none" 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-1sxrcry rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`components/Image prop "resizeMode" value "stretch" 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-x3cy2q rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`components/Image prop "resizeMode" value "undefined" 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`components/Image prop "style" correctly supports "resizeMode" property 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-ehq7j7 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`components/Image prop "testID" 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
data-testid="testID"
/>
`;
exports[`components/Image sets correct accessibility role" 1`] = `
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-wib322 rn-backgroundPosition-vvn4in rn-backgroundRepeat-u6sd8q rn-backgroundSize-4gszlv rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
/>
`;
exports[`components/Image prop "style" correctly supports "resizeMode" property 1`] = `"contain"`;

View File

@@ -1,12 +1,10 @@
/* eslint-env jasmine, jest */
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import Image from '../';
import ImageUriCache from '../ImageUriCache';
import React from 'react';
import { mount, render, shallow } from 'enzyme';
import { mount, shallow } from 'enzyme';
const originalCanUseDOM = ExecutionEnvironment.canUseDOM;
const originalImage = window.Image;
describe('components/Image', () => {
@@ -18,42 +16,39 @@ describe('components/Image', () => {
window.Image = originalImage;
});
test('sets correct accessibility role"', () => {
const component = render(<Image />);
expect(component).toMatchSnapshot();
});
test('prop "accessibilityLabel"', () => {
const defaultSource = { uri: 'https://google.com/favicon.ico' };
const component = render(
const component = shallow(
<Image accessibilityLabel="accessibilityLabel" defaultSource={defaultSource} />
);
expect(component).toMatchSnapshot();
const img = component.find('img');
expect(component.prop('accessibilityLabel')).toBe('accessibilityLabel');
expect(img.prop('alt')).toBe('accessibilityLabel');
});
test('prop "accessible"', () => {
const component = render(<Image accessible={false} />);
expect(component).toMatchSnapshot();
const component = shallow(<Image accessible={false} />);
expect(component.prop('accessible')).toBe(false);
});
test('prop "children"', () => {
const children = <div className="unique" />;
const component = render(<Image children={children} />);
expect(component).toMatchSnapshot();
const component = shallow(<Image children={children} />);
expect(component.find('.unique').length).toBe(1);
});
describe('prop "defaultSource"', () => {
test('sets background image when value is an object', () => {
const defaultSource = { uri: 'https://google.com/favicon.ico' };
const component = render(<Image defaultSource={defaultSource} />);
expect(component).toMatchSnapshot();
const component = shallow(<Image defaultSource={defaultSource} />);
expect(component.prop('style').backgroundImage).toMatchSnapshot();
});
test('sets background image when value is a string', () => {
// emulate require-ed asset
const defaultSource = 'https://google.com/favicon.ico';
const component = render(<Image defaultSource={defaultSource} />);
expect(component).toMatchSnapshot();
const component = shallow(<Image defaultSource={defaultSource} />);
expect(component.prop('style').backgroundImage).toMatchSnapshot();
});
test('sets "height" and "width" styles if missing', () => {
@@ -62,8 +57,10 @@ describe('components/Image', () => {
height: 10,
width: 20
};
const component = render(<Image defaultSource={defaultSource} />);
expect(component).toMatchSnapshot();
const component = shallow(<Image defaultSource={defaultSource} />);
const { height, width } = component.prop('style');
expect(height).toBe(10);
expect(width).toBe(20);
});
test('does not override "height" and "width" styles', () => {
@@ -72,10 +69,12 @@ describe('components/Image', () => {
height: 10,
width: 20
};
const component = render(
const component = shallow(
<Image defaultSource={defaultSource} style={{ height: 20, width: 40 }} />
);
expect(component).toMatchSnapshot();
const { height, width } = component.prop('style');
expect(height).toBe(20);
expect(width).toBe(40);
});
});
@@ -96,8 +95,8 @@ describe('components/Image', () => {
undefined
].forEach(resizeMode => {
test(`value "${resizeMode}"`, () => {
const component = render(<Image resizeMode={resizeMode} />);
expect(component).toMatchSnapshot();
const component = shallow(<Image resizeMode={resizeMode} />);
expect(component.prop('style').backgroundSize).toMatchSnapshot();
});
});
});
@@ -106,7 +105,7 @@ describe('components/Image', () => {
test('is not set immediately if the image has not already been loaded', () => {
const uri = 'https://google.com/favicon.ico';
const source = { uri };
const component = render(<Image source={source} />);
const component = shallow(<Image source={source} />);
expect(component.find('img')).toBeUndefined;
});
@@ -136,21 +135,12 @@ describe('components/Image', () => {
.attr('src')
).toBe(uriTwo);
});
test('is set immediately when rendered on the server', () => {
ExecutionEnvironment.canUseDOM = false;
const uri = 'https://google.com/favicon.ico';
const component = render(<Image source={{ uri }} />);
expect(component.find('img').attr('src')).toBe(uri);
expect(ImageUriCache.has(uri)).toBe(true);
ExecutionEnvironment.canUseDOM = originalCanUseDOM;
});
});
describe('prop "style"', () => {
test('correctly supports "resizeMode" property', () => {
const component = render(<Image style={{ resizeMode: Image.resizeMode.contain }} />);
expect(component).toMatchSnapshot();
const component = shallow(<Image style={{ resizeMode: Image.resizeMode.contain }} />);
expect(component.prop('style').backgroundSize).toMatchSnapshot();
});
test('removes other unsupported View styles', () => {
@@ -161,13 +151,13 @@ describe('components/Image', () => {
});
test('prop "testID"', () => {
const component = render(<Image testID="testID" />);
expect(component).toMatchSnapshot();
const component = shallow(<Image testID="testID" />);
expect(component.prop('testID')).toBe('testID');
});
test('passes other props through to underlying View', () => {
const fn = () => {};
const component = render(<Image onResponderGrant={fn} />);
expect(component).toMatchSnapshot();
const component = shallow(<Image onResponderGrant={fn} />);
expect(component.prop('onResponderGrant')).toBe(fn);
});
});

View File

@@ -11,7 +11,6 @@
*/
import applyNativeMethods from '../../modules/applyNativeMethods';
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import createElement from '../../modules/createElement';
import { getAssetByID } from '../../modules/AssetRegistry';
import ImageLoader from '../../modules/ImageLoader';
@@ -131,7 +130,7 @@ class Image extends Component {
super(props, context);
// If an image has been loaded before, render it immediately
const uri = resolveAssetSource(props.source);
const shouldDisplaySource = ImageUriCache.has(uri) || !canUseDOM;
const shouldDisplaySource = ImageUriCache.has(uri);
this.state = { shouldDisplaySource };
this._imageState = getImageState(uri, shouldDisplaySource);
shouldDisplaySource && ImageUriCache.add(uri);

View File

@@ -1,2 +1,55 @@
import UnimplementedView from '../UnimplementedView';
export default UnimplementedView;
/**
* Copyright (c) 2017-present, Nicolas Gallagher.
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule RefreshControl
* @flow
*/
import ColorPropType from '../../propTypes/ColorPropType';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import { arrayOf, bool, func, number, oneOf, string } from 'prop-types';
import React, { Component } from 'react';
class RefreshControl extends Component {
static propTypes = {
...ViewPropTypes,
colors: arrayOf(ColorPropType),
enabled: bool,
onRefresh: func,
progressBackgroundColor: ColorPropType,
progressViewOffset: number,
refreshing: bool.isRequired,
size: oneOf([0, 1]),
tintColor: ColorPropType,
title: string,
titleColor: ColorPropType
};
render() {
const {
/* eslint-disable */
colors,
enabled,
onRefresh,
progressBackgroundColor,
progressViewOffset,
refreshing,
size,
tintColor,
title,
titleColor,
/* eslint-enable */
...rest
} = this.props;
return <View {...rest} />;
}
}
export default RefreshControl;

View File

@@ -134,14 +134,39 @@ export default class ScrollViewBase extends Component {
scrollEnabled,
style,
/* eslint-disable */
alwaysBounceHorizontal,
alwaysBounceVertical,
automaticallyAdjustContentInsets,
bounces,
bouncesZoom,
canCancelContentTouches,
centerContent,
contentInset,
contentInsetAdjustmentBehavior,
contentOffset,
decelerationRate,
directionalLockEnabled,
endFillColor,
indicatorStyle,
keyboardShouldPersistTaps,
maximumZoomScale,
minimumZoomScale,
onMomentumScrollBegin,
onMomentumScrollEnd,
onScrollBeginDrag,
onScrollEndDrag,
overScrollMode,
pinchGestureEnabled,
removeClippedSubviews,
scrollEventThrottle,
scrollIndicatorInsets,
scrollPerfTag,
scrollsToTop,
showsHorizontalScrollIndicator,
showsVerticalScrollIndicator,
snapToInterval,
snapToAlignment,
zoomScale,
/* eslint-enable */
...other
} = this.props;

View File

@@ -137,6 +137,7 @@ const ScrollView = createReactClass({
keyboardDismissMode,
onScroll,
pagingEnabled,
stickyHeaderIndices,
/* eslint-enable */
...other
} = this.props;

View File

@@ -1,84 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/Switch disabled when "false" a default checkbox is rendered 1`] = `
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-cursor-1loqt21 rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-userSelect-lrvibr"
style="height:20px;width:40px;"
>
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-bottom-1p0dtai rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-height-1dernwh rn-left-1d2f490 rn-marginTop-1t01tom rn-marginRight-lchren rn-marginBottom-1qahzrx rn-marginLeft-1jj8364 rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-transitionDuration-13tjlyg rn-width-13qz1uu"
style="background-color:rgba(147,147,147,1);border-top-left-radius:10px;border-top-right-radius:10px;border-bottom-right-radius:10px;border-bottom-left-radius:10px;"
/>
<div
class="rn-alignItems-1oszu61 rn-alignSelf-k200y rn-borderTopLeftRadius-jt3ufn rn-borderTopRightRadius-1e868j9 rn-borderBottomRightRadius-ujv9e3 rn-borderBottomLeftRadius-1hakmuk rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxShadow-1ewcgjf rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-left-1fe0xdi rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-transform-emqnss rn-transitionDuration-13tjlyg"
style="background-color:rgba(250,250,250,1);height:20px;width:20px;"
/>
<input
class="rn-bottom-1p0dtai rn-cursor-1ei5mc7 rn-height-1pi2tsx rn-left-1d2f490 rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-opacity-1272l3b rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-width-13qz1uu"
type="checkbox"
/>
</div>
`;
exports[`components/Switch disabled when "true" a disabled checkbox is rendered 1`] = `
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-cursor-7q8q6z rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-userSelect-lrvibr"
style="height:20px;width:40px;"
>
<div
class="rn-alignItems-1oszu61 rn-backgroundColor-1hj8efq rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-bottom-1p0dtai rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-height-1dernwh rn-left-1d2f490 rn-marginTop-1t01tom rn-marginRight-lchren rn-marginBottom-1qahzrx rn-marginLeft-1jj8364 rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-transitionDuration-13tjlyg rn-width-13qz1uu"
style="border-top-left-radius:10px;border-top-right-radius:10px;border-bottom-right-radius:10px;border-bottom-left-radius:10px;"
/>
<div
class="rn-alignItems-1oszu61 rn-alignSelf-k200y rn-backgroundColor-1bgzomc rn-borderTopLeftRadius-jt3ufn rn-borderTopRightRadius-1e868j9 rn-borderBottomRightRadius-ujv9e3 rn-borderBottomLeftRadius-1hakmuk rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxShadow-1ewcgjf rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-left-1fe0xdi rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-transform-emqnss rn-transitionDuration-13tjlyg"
style="height:20px;width:20px;"
/>
<input
aria-disabled="true"
class="rn-bottom-1p0dtai rn-cursor-1ei5mc7 rn-height-1pi2tsx rn-left-1d2f490 rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-opacity-1272l3b rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-width-13qz1uu"
disabled=""
type="checkbox"
/>
</div>
`;
exports[`components/Switch value when "false" an unchecked checkbox is rendered 1`] = `
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-cursor-1loqt21 rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-userSelect-lrvibr"
style="height:20px;width:40px;"
>
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-bottom-1p0dtai rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-height-1dernwh rn-left-1d2f490 rn-marginTop-1t01tom rn-marginRight-lchren rn-marginBottom-1qahzrx rn-marginLeft-1jj8364 rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-transitionDuration-13tjlyg rn-width-13qz1uu"
style="background-color:rgba(147,147,147,1);border-top-left-radius:10px;border-top-right-radius:10px;border-bottom-right-radius:10px;border-bottom-left-radius:10px;"
/>
<div
class="rn-alignItems-1oszu61 rn-alignSelf-k200y rn-borderTopLeftRadius-jt3ufn rn-borderTopRightRadius-1e868j9 rn-borderBottomRightRadius-ujv9e3 rn-borderBottomLeftRadius-1hakmuk rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxShadow-1ewcgjf rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-left-1fe0xdi rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-transform-emqnss rn-transitionDuration-13tjlyg"
style="background-color:rgba(250,250,250,1);height:20px;width:20px;"
/>
<input
class="rn-bottom-1p0dtai rn-cursor-1ei5mc7 rn-height-1pi2tsx rn-left-1d2f490 rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-opacity-1272l3b rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-width-13qz1uu"
type="checkbox"
/>
</div>
`;
exports[`components/Switch value when "true" a checked checkbox is rendered 1`] = `
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-cursor-1loqt21 rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-userSelect-lrvibr"
style="height:20px;width:40px;"
>
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-bottom-1p0dtai rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-height-1dernwh rn-left-1d2f490 rn-marginTop-1t01tom rn-marginRight-lchren rn-marginBottom-1qahzrx rn-marginLeft-1jj8364 rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-transitionDuration-13tjlyg rn-width-13qz1uu"
style="background-color:rgba(163,211,207,1);border-top-left-radius:10px;border-top-right-radius:10px;border-bottom-right-radius:10px;border-bottom-left-radius:10px;"
/>
<div
class="rn-alignItems-1oszu61 rn-alignSelf-k200y rn-borderTopLeftRadius-jt3ufn rn-borderTopRightRadius-1e868j9 rn-borderBottomRightRadius-ujv9e3 rn-borderBottomLeftRadius-1hakmuk rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxShadow-1ewcgjf rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-left-7b7h2f rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-transform-emqnss rn-transitionDuration-13tjlyg"
style="background-color:rgba(0,150,136,1);height:20px;margin-left:-20px;width:20px;"
/>
<input
checked=""
class="rn-bottom-1p0dtai rn-cursor-1ei5mc7 rn-height-1pi2tsx rn-left-1d2f490 rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-opacity-1272l3b rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-u8s1d rn-right-zchlnj rn-top-ipm5af rn-width-13qz1uu"
type="checkbox"
/>
</div>
`;

View File

@@ -1,19 +1,21 @@
/* eslint-env jasmine, jest */
import React from 'react';
import { render } from 'enzyme';
import { shallow } from 'enzyme';
import Switch from '..';
const checkboxSelector = 'input[type="checkbox"]';
describe('components/Switch', () => {
describe('disabled', () => {
test('when "false" a default checkbox is rendered', () => {
const component = render(<Switch />);
expect(component).toMatchSnapshot();
const component = shallow(<Switch />);
expect(component.find(checkboxSelector).prop('disabled')).toBe(false);
});
test('when "true" a disabled checkbox is rendered', () => {
const component = render(<Switch disabled />);
expect(component).toMatchSnapshot();
const component = shallow(<Switch disabled />);
expect(component.find(checkboxSelector).prop('disabled')).toBe(true);
});
});
@@ -35,13 +37,13 @@ describe('components/Switch', () => {
describe('value', () => {
test('when "false" an unchecked checkbox is rendered', () => {
const component = render(<Switch value={false} />);
expect(component).toMatchSnapshot();
const component = shallow(<Switch value={false} />);
expect(component.find(checkboxSelector).prop('checked')).toBe(false);
});
test('when "true" a checked checkbox is rendered', () => {
const component = render(<Switch value />);
expect(component).toMatchSnapshot();
const component = shallow(<Switch value />);
expect(component.find(checkboxSelector).prop('checked')).toBe(true);
});
});
});

View File

@@ -17,7 +17,7 @@ import { any, bool, func, number, oneOf } from 'prop-types';
const TextPropTypes = {
...BaseComponentPropTypes,
accessibilityRole: oneOf(['button', 'heading', 'link', 'listitem']),
accessibilityRole: oneOf(['button', 'heading', 'label', 'link', 'listitem']),
children: any,
numberOfLines: number,
onLayout: func,

View File

@@ -12,6 +12,7 @@
* @flow
*/
import AccessibilityUtil from '../../modules/AccessibilityUtil';
import BoundingDimensions from './BoundingDimensions';
import findNodeHandle from '../../modules/findNodeHandle';
import normalizeColor from 'normalize-css-color';
@@ -819,7 +820,11 @@ const TouchableMixin = {
}
}
e.stopPropagation();
e.preventDefault();
// prevent the default behaviour unless the Touchable functions as a link
// and Enter is pressed
if (!(which === ENTER && AccessibilityUtil.propsToAriaRole(this.props) === 'link')) {
e.preventDefault();
}
}
}
};

View File

@@ -19,7 +19,7 @@ import StyleSheet from '../../apis/StyleSheet';
import TimerMixin from 'react-timer-mixin';
import Touchable from './Touchable';
import warning from 'fbjs/lib/warning';
import { bool, element, func, number, string } from 'prop-types';
import { bool, func, number, string } from 'prop-types';
type Event = Object;
@@ -33,7 +33,7 @@ const PRESS_RETENTION_OFFSET = { top: 20, left: 20, right: 20, bottom: 30 };
* If you wish to have several child components, wrap them in a View.
*/
/* eslint-disable react/prefer-es6-class */
/* eslint-disable react/prefer-es6-class, react/prop-types */
const TouchableWithoutFeedback = createReactClass({
displayName: 'TouchableWithoutFeedback',
mixins: [TimerMixin, Touchable.Mixin],
@@ -44,7 +44,6 @@ const TouchableWithoutFeedback = createReactClass({
accessibilityRole: BaseComponentPropTypes.accessibilityRole,
accessibilityTraits: BaseComponentPropTypes.accessibilityTraits,
accessible: bool,
children: element,
/**
* Delay in ms, from onPressIn, before onLongPress is called.
*/
@@ -161,6 +160,7 @@ const TouchableWithoutFeedback = createReactClass({
} = this.props;
// Note(avik): remove dynamic typecast once Flow has been upgraded
// $FlowFixMe
const child = React.Children.only(this.props.children);
let children = child.props.children;
warning(

View File

@@ -11,18 +11,13 @@
*/
import View from '../View';
import { any, object } from 'prop-types';
import React, { Component } from 'react';
/**
* Common implementation for a simple stubbed view.
*/
/* eslint-disable react/prop-types */
class UnimplementedView extends Component {
static propTypes = {
children: any,
style: object
};
setNativeProps() {
// Do nothing.
// This method is required in order to use this view as a Touchable* child.

View File

@@ -1,29 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/View prop "hitSlop" handles partial offsets 1`] = `
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
>
<span
class="rn-bottom-1p0dtai rn-left-1d2f490 rn-position-u8s1d rn-right-zchlnj rn-zIndex-1wyyakw"
style="top:-10px;"
/>
</div>
Object {
"top": "-10px",
}
`;
exports[`components/View prop "hitSlop" renders a span with negative position offsets 1`] = `
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-position-bnwqim rn-zIndex-1lgpqti"
>
<span
class="rn-position-u8s1d rn-zIndex-1wyyakw"
style="bottom:-10px;left:-5px;right:-5px;top:-10px;"
/>
</div>
`;
exports[`components/View prop "pointerEvents" 1`] = `
<div
class="rn-alignItems-1oszu61 rn-borderTopStyle-1efd50x rn-borderRightStyle-14skgim rn-borderBottomStyle-rull8r rn-borderLeftStyle-mm0ijv rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-boxSizing-deolkf rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-minHeight-ifefl9 rn-minWidth-bcqeeo rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-pointerEvents-ah5dr5 rn-position-bnwqim"
/>
Object {
"bottom": "-10px",
"left": "-5px",
"right": "-5px",
"top": "-10px",
}
`;

View File

@@ -1,7 +1,7 @@
/* eslint-env jasmine, jest */
import React from 'react';
import { render, shallow } from 'enzyme';
import { shallow } from 'enzyme';
import View from '../';
describe('components/View', () => {
@@ -12,26 +12,48 @@ describe('components/View', () => {
});
});
test('prop "children"', () => {
const children = <View testID="1" />;
const component = shallow(<View>{children}</View>);
expect(component.contains(children)).toEqual(true);
describe('prop "children"', () => {
test('text node throws error (single)', () => {
const render = () => shallow(<View>'hello'</View>);
expect(render).toThrow();
});
test('text node throws error (array)', () => {
const render = () =>
shallow(
<View>
<View />
'hello'
<View />
</View>
);
expect(render).toThrow();
});
test('non-text is rendered', () => {
const children = <View testID="1" />;
const component = shallow(<View>{children}</View>);
expect(component.contains(children)).toEqual(true);
});
});
describe('prop "hitSlop"', () => {
it('renders a span with negative position offsets', () => {
const component = render(<View hitSlop={{ top: 10, bottom: 10, right: 5, left: 5 }} />);
expect(component).toMatchSnapshot();
const component = shallow(<View hitSlop={{ top: 10, bottom: 10, right: 5, left: 5 }} />);
const span = component.find('span');
expect(span.length).toBe(1);
expect(span.prop('style')).toMatchSnapshot();
});
it('handles partial offsets', () => {
const component = render(<View hitSlop={{ top: 10 }} />);
expect(component).toMatchSnapshot();
const component = shallow(<View hitSlop={{ top: 10 }} />);
const span = component.find('span');
expect(span.prop('style')).toMatchSnapshot();
});
});
test('prop "pointerEvents"', () => {
const component = render(<View pointerEvents="box-only" />);
expect(component).toMatchSnapshot();
const component = shallow(<View pointerEvents="box-only" />);
expect(component.prop('className').indexOf('pointerEvents') > -1).toBe(true);
});
});

View File

@@ -11,6 +11,7 @@ import applyLayout from '../../modules/applyLayout';
import applyNativeMethods from '../../modules/applyNativeMethods';
import { bool } from 'prop-types';
import createElement from '../../modules/createElement';
import invariant from 'fbjs/lib/invariant';
import StyleSheet from '../../apis/StyleSheet';
import ViewPropTypes from './ViewPropTypes';
import React, { Component } from 'react';
@@ -49,6 +50,15 @@ class View extends Component {
...otherProps
} = this.props;
if (process.env.NODE_ENV !== 'production') {
React.Children.toArray(this.props.children).forEach(item => {
invariant(
typeof item !== 'string',
`Unexpected text node: ${item}. A text node cannot be a child of a <View>.`
);
});
}
const { isInAParentText } = this.context;
otherProps.style = [styles.initial, isInAParentText && styles.inline, style];

View File

@@ -12,7 +12,7 @@ export { default as AsyncStorage } from './apis/AsyncStorage';
export { default as BackAndroid } from './apis/BackAndroid';
export { default as Clipboard } from './apis/Clipboard';
export { default as Dimensions } from './apis/Dimensions';
export { default as Easing } from 'animated/lib/Easing';
export { default as Easing } from './apis/Easing';
export { default as I18nManager } from './apis/I18nManager';
export { default as Keyboard } from './apis/Keyboard';
export { default as InteractionManager } from './apis/InteractionManager';

View File

@@ -4,6 +4,9 @@ exports[`modules/createElement it normalizes event.nativeEvent 1`] = `
Object {
"_normalized": true,
"changedTouches": Array [],
"identifier": undefined,
"locationX": undefined,
"locationY": undefined,
"pageX": undefined,
"pageY": undefined,
"preventDefault": [Function],

View File

@@ -19,11 +19,7 @@ describe('modules/createElement', () => {
};
const component = shallow(createElement('span', { onClick }));
component.find('span').simulate('click', {
nativeEvent: {
preventDefault() {},
stopImmediatePropagation() {},
stopPropagation() {}
}
nativeEvent: {}
});
});
@@ -38,11 +34,7 @@ describe('modules/createElement', () => {
);
component.find('span').simulate('keyPress', {
isDefaultPrevented() {},
nativeEvent: {
preventDefault() {},
stopImmediatePropagation() {},
stopPropagation() {}
},
nativeEvent: {},
preventDefault() {},
which
});

View File

@@ -0,0 +1,124 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`modules/normalizeNativeEvent mouse events simulated event 1`] = `
Object {
"_normalized": true,
"changedTouches": Array [
Object {
"_normalized": true,
"clientX": undefined,
"clientY": undefined,
"force": undefined,
"identifier": 0,
"locationX": undefined,
"locationY": undefined,
"pageX": undefined,
"pageY": undefined,
"screenX": undefined,
"screenY": undefined,
"target": undefined,
"timestamp": 1496876171255,
},
],
"identifier": 0,
"locationX": undefined,
"locationY": undefined,
"pageX": undefined,
"pageY": undefined,
"preventDefault": [Function],
"stopImmediatePropagation": [Function],
"stopPropagation": [Function],
"target": undefined,
"timestamp": 1496876171255,
"touches": Array [],
}
`;
exports[`modules/normalizeNativeEvent mouse events synthetic event 1`] = `
Object {
"_normalized": true,
"changedTouches": Array [
Object {
"_normalized": true,
"clientX": 100,
"clientY": 100,
"force": false,
"identifier": 0,
"locationX": 100,
"locationY": 100,
"pageX": 300,
"pageY": 300,
"screenX": 400,
"screenY": 400,
"target": undefined,
"timestamp": 1496876171255,
},
],
"identifier": 0,
"locationX": 200,
"locationY": 200,
"pageX": 300,
"pageY": 300,
"preventDefault": [Function],
"stopImmediatePropagation": [Function],
"stopPropagation": [Function],
"target": undefined,
"timestamp": 1496876171255,
"touches": Array [],
}
`;
exports[`modules/normalizeNativeEvent touch events simulated event 1`] = `
Object {
"_normalized": true,
"changedTouches": Array [],
"identifier": undefined,
"locationX": undefined,
"locationY": undefined,
"pageX": undefined,
"pageY": undefined,
"preventDefault": [Function],
"stopImmediatePropagation": [Function],
"stopPropagation": [Function],
"target": undefined,
"timestamp": 1496876171255,
"touches": Array [],
}
`;
exports[`modules/normalizeNativeEvent touch events synthetic event 1`] = `
Object {
"_normalized": true,
"changedTouches": Array [
Object {
"_normalized": true,
"clientX": 100,
"clientY": 100,
"force": false,
"identifier": undefined,
"locationX": undefined,
"locationY": undefined,
"pageX": 300,
"pageY": 300,
"radiusX": 10,
"radiusY": 10,
"rotationAngle": 45,
"screenX": 400,
"screenY": 400,
"target": undefined,
"timestamp": 1496876171255,
},
],
"identifier": undefined,
"locationX": undefined,
"locationY": undefined,
"pageX": 300,
"pageY": 300,
"preventDefault": [Function],
"stopImmediatePropagation": [Function],
"stopPropagation": [Function],
"target": undefined,
"timestamp": 1496876171255,
"touches": Array [],
}
`;

View File

@@ -0,0 +1,82 @@
/* eslint-env jasmine, jest */
import normalizeNativeEvent from '..';
const normalizeEvent = nativeEvent => {
const result = normalizeNativeEvent(nativeEvent);
result.timestamp = 1496876171255;
if (result.changedTouches && result.changedTouches[0]) {
result.changedTouches[0].timestamp = 1496876171255;
}
if (result.touches && result.touches[0]) {
result.touches[0].timestamp = 1496876171255;
}
return result;
};
describe('modules/normalizeNativeEvent', () => {
describe('mouse events', () => {
test('simulated event', () => {
const nativeEvent = {
type: 'mouseup'
};
const result = normalizeEvent(nativeEvent);
expect(result).toMatchSnapshot();
});
test('synthetic event', () => {
const nativeEvent = {
type: 'mouseup',
clientX: 100,
clientY: 100,
force: false,
offsetX: 200,
offsetY: 200,
pageX: 300,
pageY: 300,
screenX: 400,
screenY: 400
};
const result = normalizeEvent(nativeEvent);
expect(result).toMatchSnapshot();
});
});
describe('touch events', () => {
test('simulated event', () => {
const nativeEvent = {
type: 'touchstart'
};
const result = normalizeEvent(nativeEvent);
expect(result).toMatchSnapshot();
});
test('synthetic event', () => {
const nativeEvent = {
type: 'touchstart',
changedTouches: [
{
clientX: 100,
clientY: 100,
force: false,
pageX: 300,
pageY: 300,
radiusX: 10,
radiusY: 10,
rotationAngle: 45,
screenX: 400,
screenY: 400
}
],
pageX: 300,
pageY: 300
};
const result = normalizeEvent(nativeEvent);
expect(result).toMatchSnapshot();
});
});
});

View File

@@ -5,19 +5,31 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
* @flow
*/
const emptyArray = [];
const emptyFunction = () => {};
// Mobile Safari re-uses touch objects, so we copy the properties we want and normalize the identifier
const normalizeTouches = (touches = emptyArray) =>
Array.prototype.slice.call(touches).map(touch => {
const identifier = touch.identifier > 20 ? touch.identifier % 20 : touch.identifier;
const normalizeTouches = touches => {
if (!touches) {
return emptyArray;
}
const rect = touch.target && touch.target.getBoundingClientRect();
const locationX = touch.pageX - rect.left;
const locationY = touch.pageY - rect.top;
return Array.prototype.slice.call(touches).map(touch => {
const identifier = touch.identifier > 20 ? touch.identifier % 20 : touch.identifier;
let locationX, locationY;
const node = touch.target;
if (node) {
const isElement = node.nodeType === 1 /* Node.ELEMENT_NODE */;
if (isElement && typeof node.getBoundingClientRect === 'function') {
const rect = node.getBoundingClientRect();
locationX = touch.pageX - rect.left;
locationY = touch.pageY - rect.top;
}
}
return {
_normalized: true,
@@ -40,19 +52,36 @@ const normalizeTouches = (touches = emptyArray) =>
timestamp: Date.now()
};
});
};
function normalizeTouchEvent(nativeEvent) {
const changedTouches = normalizeTouches(nativeEvent.changedTouches);
const touches = normalizeTouches(nativeEvent.touches);
const preventDefault =
typeof nativeEvent.preventDefault === 'function'
? nativeEvent.preventDefault.bind(nativeEvent)
: emptyFunction;
const stopImmediatePropagation =
typeof nativeEvent.stopImmediatePropagation === 'function'
? nativeEvent.stopImmediatePropagation.bind(nativeEvent)
: emptyFunction;
const stopPropagation =
typeof nativeEvent.stopPropagation === 'function'
? nativeEvent.stopPropagation.bind(nativeEvent)
: emptyFunction;
const event = {
_normalized: true,
changedTouches,
identifier: undefined,
locationX: undefined,
locationY: undefined,
pageX: nativeEvent.pageX,
pageY: nativeEvent.pageY,
preventDefault: nativeEvent.preventDefault.bind(nativeEvent),
stopImmediatePropagation: nativeEvent.stopImmediatePropagation.bind(nativeEvent),
stopPropagation: nativeEvent.stopPropagation.bind(nativeEvent),
preventDefault,
stopImmediatePropagation,
stopPropagation,
target: nativeEvent.target,
// normalize the timestamp
// https://stackoverflow.com/questions/26177087/ios-8-mobile-safari-wrong-timestamp-on-touch-events
@@ -89,6 +118,20 @@ function normalizeMouseEvent(nativeEvent) {
timestamp: Date.now()
}
];
const preventDefault =
typeof nativeEvent.preventDefault === 'function'
? nativeEvent.preventDefault.bind(nativeEvent)
: emptyFunction;
const stopImmediatePropagation =
typeof nativeEvent.stopImmediatePropagation === 'function'
? nativeEvent.stopImmediatePropagation.bind(nativeEvent)
: emptyFunction;
const stopPropagation =
typeof nativeEvent.stopPropagation === 'function'
? nativeEvent.stopPropagation.bind(nativeEvent)
: emptyFunction;
return {
_normalized: true,
changedTouches: touches,
@@ -97,22 +140,27 @@ function normalizeMouseEvent(nativeEvent) {
locationY: nativeEvent.offsetY,
pageX: nativeEvent.pageX,
pageY: nativeEvent.pageY,
preventDefault: nativeEvent.preventDefault.bind(nativeEvent),
stopImmediatePropagation: nativeEvent.stopImmediatePropagation.bind(nativeEvent),
stopPropagation: nativeEvent.stopPropagation.bind(nativeEvent),
preventDefault,
stopImmediatePropagation,
stopPropagation,
target: nativeEvent.target,
timestamp: touches[0].timestamp,
touches: nativeEvent.type === 'mouseup' ? emptyArray : touches
};
}
function normalizeNativeEvent(nativeEvent) {
if (nativeEvent._normalized) {
// TODO: how to best handle keyboard events?
function normalizeNativeEvent(nativeEvent: Object) {
if (!nativeEvent || nativeEvent._normalized) {
return nativeEvent;
}
const eventType = nativeEvent.type || '';
const mouse = eventType.indexOf('mouse') >= 0;
return mouse ? normalizeMouseEvent(nativeEvent) : normalizeTouchEvent(nativeEvent);
if (mouse) {
return normalizeMouseEvent(nativeEvent);
} else {
return normalizeTouchEvent(nativeEvent);
}
}
export default normalizeNativeEvent;

View File

@@ -2,6 +2,7 @@ import crossFade from 'inline-style-prefixer/static/plugins/crossFade';
import cursor from 'inline-style-prefixer/static/plugins/cursor';
import filter from 'inline-style-prefixer/static/plugins/filter';
import flex from 'inline-style-prefixer/static/plugins/flex';
import flexboxIE from 'inline-style-prefixer/static/plugins/flexboxIE';
import flexboxOld from 'inline-style-prefixer/static/plugins/flexboxOld';
import gradient from 'inline-style-prefixer/static/plugins/gradient';
import imageSet from 'inline-style-prefixer/static/plugins/imageSet';
@@ -21,6 +22,7 @@ export default {
cursor,
filter,
flex,
flexboxIE,
flexboxOld,
gradient,
imageSet,
@@ -82,13 +84,13 @@ export default {
columns: wm,
columnSpan: wm,
columnWidth: wm,
flex: w,
flex: wms,
flexBasis: w,
flexDirection: w,
flexDirection: wms,
flexGrow: w,
flexFlow: w,
flexFlow: wms,
flexShrink: w,
flexWrap: w,
flexWrap: wms,
alignContent: w,
alignItems: w,
alignSelf: w,
@@ -122,6 +124,7 @@ export default {
wrapFlow: ms,
wrapThrough: ms,
wrapMargin: ms,
touchAction: ms,
gridTemplateColumns: ms,
gridTemplateRows: ms,
gridTemplateAreas: ms,

View File

@@ -10,6 +10,9 @@
* @flow
*/
const isWebColor = (color: string) =>
color === 'currentcolor' || color === 'inherit' || color.indexOf('var(') === 0;
const colorPropType = function(isRequired, props, propName, componentName, location, propFullName) {
const normalizeColor = require('normalize-css-color');
const color = props[propName];
@@ -35,8 +38,8 @@ const colorPropType = function(isRequired, props, propName, componentName, locat
return;
}
// Web supports additional color keywords and custom property values
if (color === 'currentcolor' || color === 'inherit' || color.indexOf('var(') === 0) {
if (typeof color === 'string' && isWebColor(color)) {
// Web supports additional color keywords and custom property values. Ignore them.
return;
}

View File

@@ -11,8 +11,6 @@
* @providesModule warnValidStyle
*/
'use strict';
var emptyFunction = require('fbjs/lib/emptyFunction');
var warnValidStyle = emptyFunction;