Compare commits

...

16 Commits

Author SHA1 Message Date
Nicolas Gallagher
b7c72308ea 0.0.80 2017-03-22 23:43:37 -07:00
Nicolas Gallagher
5fee075774 Add 'processColor' tests 2017-03-22 23:40:40 -07:00
Nicolas Gallagher
25204eeff0 [fix] convert color values to CSS color
Convert all hex and numeric colors to rgba. Assume non-hex strings are
valid CSS colors.
2017-03-22 23:15:42 -07:00
Nicolas Gallagher
9c61fe58d3 [add] View 'hitSlop' shim
Shim the 'hitSlop' prop using a positioned element to extend the size of
a View's touch target without changing layout. Unlike the native
implementation, the touch target may extend past the parent view bounds.
2017-03-22 23:01:53 -07:00
Nicolas Gallagher
782125d169 Remove pointerEvents code from View 2017-03-20 22:53:57 -07:00
Nicolas Gallagher
af805d67e6 0.0.79 2017-03-20 22:42:00 -07:00
Nicolas Gallagher
68068f8cb6 [fix] support React Native props in 'setNativeProps'
React Native allows props like 'pointerEvents' to be set using
'setNativeProps'.

Fix #392
2017-03-20 22:33:59 -07:00
Nicolas Gallagher
e05e2122d7 [fix] avoid setting empty style objects 2017-03-20 22:33:59 -07:00
Nicolas Gallagher
47dac44120 [fix] filter 'lineBreakMode' from Text props 2017-03-20 22:33:53 -07:00
Nicolas Gallagher
22af6894c2 Update jest 2017-03-20 22:18:50 -07:00
Nicolas Gallagher
458c534200 [change] improve button accessibility and styling
1. If no 'accessibilityRole' is set, fallback to looking for 'button'
role in the equivalent native props. This helps improve accessibility of
button-like components authored without the web platform in mind.

2. Ensure button context is properly inherited.

3. Add 'appearance:none' to DOM button elements to enable better styling
support in Safari

Fix #378
2017-03-20 14:50:01 -07:00
Nicolas Gallagher
ec2db3e2a3 0.0.78 2017-03-19 18:45:21 -07:00
Bruno Lemos
e6f00f7592 [add] default option for Platform.select
See: f30ab35e92
2017-03-19 15:27:07 -07:00
Nicolas Gallagher
976320916e [change] move bridge code into createDOMElement
Moves event normalization and the ResponderEventPlugin injection from
'View' to 'createDOMElement'.

The 'react-native-web/lite' variant is removed from the performance
directory as the implementation is not substantially different.
Micro-optimizations to marginally narrow the performance gap to
css-modules.
2017-03-19 15:19:26 -07:00
Nicolas Gallagher
808790505e [change] onLayout improvements
1. Fires when window resizes
2. Guards against nodes being unmounted

Fix #397
Ref #60
2017-03-19 13:29:47 -07:00
Nicolas Gallagher
89ad493ce5 Update benchmark results 2017-03-14 17:23:16 -07:00
53 changed files with 1191 additions and 895 deletions

View File

@@ -45,9 +45,7 @@ If true, disable all interactions for this component.
**hitSlop**: `{top: number, left: number, bottom: number, right: number}`
This defines how far your touch can start away from the button. This is added
to `pressRetentionOffset` when moving off of the button. **NOTE**: The touch
area never extends past the parent view bounds and the z-index of sibling views
always takes precedence if a touch hits two overlapping views.
to `pressRetentionOffset` when moving off of the button.
**onLayout**: function

View File

@@ -18,8 +18,10 @@ NOTE: `View` will transfer all other props to the rendered HTML element.
**accessibilityLabel**: string
Defines the text available to assistive technologies upon interaction with the
element. (This is implemented using `aria-label`.)
Overrides the text that's read by the screen reader when the user interacts
with the element. By default, the label is constructed by traversing all the
children and accumulating all the `Text` nodes separated by space. (This is
implemented using `aria-label`.)
**accessibilityLiveRegion**: oneOf('assertive', 'off', 'polite') = 'off'
@@ -46,6 +48,15 @@ assistive technologies of a `role` value change.
When `false`, the view is hidden from assistive technologies. (This is
implemented using `aria-hidden`.)
**hitSlop**: {top: number, left: number, bottom: number, right: number}
This defines how far a touch event can start away from the view. Typical
interface guidelines recommend touch targets that are at least 30 - 40
points/density-independent pixels.
For example, if a touchable view has a height of 20 the touchable height can be
extended to 40 with `hitSlop={{top: 10, bottom: 10, left: 0, right: 0}}`.
**onLayout**: function
Invoked on mount and layout changes with `{ nativeEvent: { layout: { x, y, width,

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-web",
"version": "0.0.77",
"version": "0.0.80",
"description": "React Native for Web",
"main": "dist/index.js",
"files": [
@@ -25,7 +25,6 @@
"dependencies": {
"animated": "^0.2.0",
"array-find-index": "^1.0.2",
"asap": "^2.0.5",
"babel-runtime": "^6.23.0",
"debounce": "^1.0.0",
"deep-assign": "^2.0.0",
@@ -53,7 +52,7 @@
"eslint-plugin-promise": "^2.0.1",
"eslint-plugin-react": "^6.1.2",
"file-loader": "^0.9.0",
"jest": "^16.0.2",
"jest": "^19.0.2",
"node-libs-browser": "^0.5.3",
"prettier": "^0.19.0",
"react": "~15.4.1",

View File

@@ -10,27 +10,18 @@ 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.
implemented by multiple UI or style libraries. The implementations are not
equivalent in functionality.
## Benchmark results
Typical render timings*: mean / two standard deviations
Typical render timings*: mean ± two standard deviations
Version: 0.0.73
| Implementation | Deep tree (ms) | Wide tree (ms) |
| 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` |
| `css-modules` | `76.66` `±18.46` | `157.03` `±19.79` |
| `react-native-web@0.0.78` | `90.13` 20.91` | `198.72` `±24.44` |
| `styled-components@2.0.0-7` | `263.06` 31.87` | `564.53` 27.62` |
| `glamor@3.0.0-1` | `267.49` 35.12` | `451.99` `±37.32` |
*MacBook Pro (13-inch, Early 2011); 2.7 GHz Intel Core i7; 16 GB 1600 MHz DDR3. Google Chrome 56.

View File

@@ -1,49 +0,0 @@
/* 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

@@ -1,32 +0,0 @@
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

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

View File

@@ -1,7 +1,6 @@
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';
import renderDeepTree from './tests/renderDeepTree';
@@ -10,13 +9,11 @@ import renderWideTree from './tests/renderWideTree';
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)

View File

@@ -3,9 +3,9 @@
"private": true,
"dependencies": {
"classnames": "^2.2.5",
"glamor": "^2.20.24",
"glamor": "3.0.0-1",
"marky": "^1.1.3",
"styled-components": "2.0.0-5"
"styled-components": "2.0.0-7"
},
"devDependencies": {
"css-loader": "^0.26.2",

View File

@@ -19,7 +19,9 @@ module.exports = {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: { cacheDirectory: true }
query: {
cacheDirectory: true
}
}
]
},

View File

@@ -155,10 +155,6 @@ colormin@^1.0.5:
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"
@@ -171,15 +167,9 @@ 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-keywords@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
css-color-names@0.0.4:
version "0.0.4"
@@ -218,13 +208,13 @@ css-selector-tokenizer@^0.7.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"
css-to-react-native@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-2.0.1.tgz#179b25cba8cab7798118b1679b81f4d6b3fa0de3"
dependencies:
css-color-list "0.0.1"
css-color-keywords "^1.0.0"
fbjs "^0.8.5"
nearley "^2.7.7"
postcss-value-parser "^3.3.0"
cssesc@^0.1.0:
version "0.1.0"
@@ -282,10 +272,6 @@ 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"
@@ -336,7 +322,15 @@ 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.22, glamor@^2.20.24:
glamor@3.0.0-1:
version "3.0.0-1"
resolved "https://registry.yarnpkg.com/glamor/-/glamor-3.0.0-1.tgz#60f489e96d96c12620803d3677ac26413cb76a95"
dependencies:
babel-runtime "^6.18.0"
fbjs "^0.8.8"
object-assign "^4.1.0"
glamor@^2.20.22:
version "2.20.24"
resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.24.tgz#a299af2eec687322634ba38e4a0854d8743d2041"
dependencies:
@@ -501,14 +495,6 @@ mkdirp@~0.5.1:
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"
@@ -516,13 +502,6 @@ node-fetch@^1.0.1:
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"
@@ -803,17 +782,6 @@ query-string@^4.1.0:
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"
@@ -854,10 +822,6 @@ regjsparser@^0.1.4:
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"
@@ -900,23 +864,23 @@ style-loader@^0.13.2:
dependencies:
loader-utils "^1.0.2"
styled-components@2.0.0-5:
version "2.0.0-5"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.0.0-5.tgz#df802d110cfb1a08a37e7746ecff11c765075e34"
styled-components@2.0.0-7:
version "2.0.0-7"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.0.0-7.tgz#a420b99622eacec26ae3d62c1c75985791d9691b"
dependencies:
buffer "^5.0.3"
css-to-react-native "^1.0.6"
css-to-react-native "2.0.1"
fbjs "^0.8.9"
glamor "^2.20.22"
inline-style-prefixer "^2.0.5"
is-function "^1.0.1"
is-plain-object "^2.0.1"
stylis "^1.1.13"
stylis "^1.2.0"
supports-color "^3.2.3"
stylis@^1.1.13:
version "1.1.13"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-1.1.13.tgz#e15095d0027f49683f7556e31df184c1eafe1d6d"
stylis@^1.2.0:
version "1.2.6"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-1.2.6.tgz#d7e72d3c8de52684a4f6cc82b3086e3634dc3c13"
supports-color@^2.0.0:
version "2.0.0"
@@ -944,10 +908,6 @@ 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"

View File

@@ -1,5 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`apis/AppRegistry/renderApplication getApplication 1`] = `
"<style id=\"react-native-stylesheet-static\">
"<style id=\\"react-native-stylesheet-static\\">
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);}
body{margin:0;}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
@@ -13,7 +15,7 @@ input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit
.rn-pointerEvents-ah5dr5 *{pointer-events:none;}
.rn-pointerEvents-633pao{pointer-events:none;}
</style>
<style id=\"react-native-stylesheet\">
<style id=\\"react-native-stylesheet\\">
.rn-bottom-1p0dtai{bottom:0px}
.rn-left-1d2f490{left:0px}
.rn-position-u8s1d{position:absolute}
@@ -50,5 +52,8 @@ input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit
.rn-paddingLeft-gy4na3{padding-left:0px}
.rn-textAlign-1ttztb7{text-align:inherit}
.rn-textDecoration-bauka4{text-decoration:none}
.rn-appearance-30o5oe{-moz-appearance:none;-webkit-appearance:none;appearance:none}
.rn-zIndex-1lgpqti{z-index:0}
.rn-zIndex-1wyyakw{z-index:-1}
</style>"
`;

View File

@@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`apis/AsyncStorage mergeLocalStorageItem should have same behavior as react-native 1`] = `
Object {
"age": 31,

View File

@@ -6,11 +6,11 @@
* @flow
*/
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import debounce from 'debounce';
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import invariant from 'fbjs/lib/invariant';
const win = ExecutionEnvironment.canUseDOM ? window : { screen: {} };
const win = canUseDOM ? window : { screen: {} };
const dimensions = {};
@@ -38,6 +38,9 @@ class Dimensions {
}
Dimensions.set();
ExecutionEnvironment.canUseDOM && window.addEventListener('resize', debounce(Dimensions.set, 50));
if (canUseDOM) {
window.addEventListener('resize', debounce(Dimensions.set, 16), false);
}
module.exports = Dimensions;

View File

@@ -1,6 +1,6 @@
const Platform = {
OS: 'web',
select: (obj: Object) => obj.web
select: (obj: Object) => 'web' in obj ? obj.web : obj.default
};
module.exports = Platform;

View File

@@ -1,7 +1,7 @@
import asap from 'asap';
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import generateCss from './generateCss';
import hash from './hash';
import requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
import staticCss from './staticCss';
const emptyObject = {};
@@ -111,7 +111,7 @@ class StyleManager {
className = createClassName(prop, value);
this._addToCache(className, prop, value);
if (canUseDOM) {
asap(() => {
requestAnimationFrame(() => {
const sheet = this.mainSheet.sheet;
// avoid injecting if the rule already exists (e.g., server rendered, hot reload)
if (this.mainSheet.textContent.indexOf(className) === -1) {

View File

@@ -127,16 +127,20 @@ class StyleRegistry {
if (className) {
props.classList.push(className);
} else {
if (!props.style) {
props.style = {};
}
// 4x slower render
props.style[styleProp] = value;
}
}
return props;
}, { classList: [], style: {} });
}, { classList: [] });
const style = prefixInlineStyles(props.style);
props.className = classListToString(props.classList);
props.style = style;
if (props.style) {
props.style = prefixInlineStyles(props.style);
}
return props;
}

View File

@@ -1,7 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`apis/StyleSheet/StyleManager getClassName 1`] = `"rn-pointerEvents-ah5dr5"`;
exports[`apis/StyleSheet/StyleManager getStyleSheetHtml 1`] = `
"<style id=\"react-native-stylesheet-static\">
"<style id=\\"react-native-stylesheet-static\\">
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);}
body{margin:0;}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
@@ -15,13 +17,13 @@ input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit
.rn-pointerEvents-ah5dr5 *{pointer-events:none;}
.rn-pointerEvents-633pao{pointer-events:none;}
</style>
<style id=\"react-native-stylesheet\">
<style id=\\"react-native-stylesheet\\">
</style>"
`;
exports[`apis/StyleSheet/StyleManager getStyleSheetHtml 2`] = `
"<style id=\"react-native-stylesheet-static\">
"<style id=\\"react-native-stylesheet-static\\">
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);}
body{margin:0;}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
@@ -35,7 +37,7 @@ input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit
.rn-pointerEvents-ah5dr5 *{pointer-events:none;}
.rn-pointerEvents-633pao{pointer-events:none;}
</style>
<style id=\"react-native-stylesheet\">
<style id=\\"react-native-stylesheet\\">
.rn-width-b8lwoo{width:100px}
</style>"
`;

View File

@@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`apis/StyleSheet/StyleRegistry resolve with register, resolves to className 1`] = `
Object {
"classList": Array [
@@ -15,7 +17,6 @@ Object {
"rn-width-b8lwoo",
],
"className": "rn-borderTopColor-1gxhl28 rn-borderRightColor-knoah9 rn-borderBottomColor-1ani3fp rn-borderLeftColor-ribj9x rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-left-1tsx3h3 rn-pointerEvents-ah5dr5 rn-position-u8s1d rn-width-b8lwoo",
"style": Object {},
}
`;
@@ -36,7 +37,6 @@ Object {
"rn-width-l0gwng",
],
"className": "rn-borderTopColor-1gxhl28 rn-borderRightColor-knoah9 rn-borderBottomColor-1ani3fp rn-borderLeftColor-ribj9x rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-left-1tsx3h3 rn-pointerEvents-ah5dr5 rn-position-u8s1d rn-width-l0gwng",
"style": Object {},
}
`;
@@ -57,7 +57,6 @@ Object {
"rn-width-b8lwoo",
],
"className": "rn-borderTopColor-1gxhl28 rn-borderRightColor-knoah9 rn-borderBottomColor-1ani3fp rn-borderLeftColor-ribj9x rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-left-1tsx3h3 rn-pointerEvents-ah5dr5 rn-position-u8s1d rn-width-b8lwoo",
"style": Object {},
}
`;

View File

@@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`apis/StyleSheet/createReactDOMStyle converts ReactNative style to ReactDOM style 1`] = `
Object {
"borderBottomWidth": "1px",
@@ -6,7 +8,7 @@ Object {
"borderTopWidth": "1px",
"borderWidthLeft": "2px",
"borderWidthRight": "3px",
"boxShadow": "1px 1px 1px 1px #000, 1px 2px 0px rgba(255,0,0,1)",
"boxShadow": "1px 1px 1px 1px #000, 1px 2px 0px red",
"display": "flex",
"flexShrink": 0,
"marginBottom": "0px",

View File

@@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`apis/StyleSheet/expandStyle shortform -> longform 1`] = `
Object {
"borderBottomColor": "white",

View File

@@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`apis/StyleSheet/flattenStyle should merge style objects 1`] = `
Object {
"opacity": 1,

View File

@@ -1 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
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

@@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`apis/StyleSheet/i18nStyle LTR mode does not auto-flip 1`] = `
Object {
"borderBottomLeftRadius": 20,

View File

@@ -1,5 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`apis/StyleSheet renderToString 1`] = `
"<style id=\"react-native-stylesheet-static\">
"<style id=\\"react-native-stylesheet-static\\">
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);}
body{margin:0;}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
@@ -13,7 +15,7 @@ input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit
.rn-pointerEvents-ah5dr5 *{pointer-events:none;}
.rn-pointerEvents-633pao{pointer-events:none;}
</style>
<style id=\"react-native-stylesheet\">
<style id=\\"react-native-stylesheet\\">
.rn-bottom-1p0dtai{bottom:0px}
.rn-left-1d2f490{left:0px}
.rn-position-u8s1d{position:absolute}

View File

@@ -0,0 +1,89 @@
/* eslint-env jasmine, jest */
import processColor from '../processColor';
describe('apis/StyleSheet/processColor', () => {
describe('predefined color names', () => {
it('should not convert "red"', () => {
const color = processColor('red');
expect(color).toEqual('red');
});
it('should not convert "white"', () => {
const color = processColor('white');
expect(color).toEqual('white');
});
it('should not convert "black"', () => {
const color = processColor('black');
expect(color).toEqual('black');
});
it('should not convert "currentcolor"', () => {
const color = processColor('currentcolor');
expect(color).toEqual('currentcolor');
});
it('should not convert "inherit"', () => {
const color = processColor('inherit');
expect(color).toEqual('inherit');
});
it('should not convert "transparent"', () => {
const color = processColor('transparent');
expect(color).toEqual('transparent');
});
});
describe('RGB strings', () => {
it('should not convert "rgb(x,y,z)"', () => {
const color = processColor('rgb(10,20,30)');
expect(color).toEqual('rgb(10,20,30)');
});
});
describe('RGBA strings', () => {
it('should not convert "rgba(x,y,z,a)"', () => {
const color = processColor('rgba(10,20,30,0.4)');
expect(color).toEqual('rgba(10,20,30,0.4)');
});
});
describe('HSL strings', () => {
it('should not convert "hsl(x,y%,z%)"', () => {
const color = processColor('hsl(318,69%,55%)');
expect(color).toEqual('hsl(318,69%,55%)');
});
});
describe('HSLA strings', () => {
it('should not convert "hsla(x,y%,z%,a)"', () => {
const color = processColor('hsla(318,69%,55%,0.25)');
expect(color).toEqual('hsla(318,69%,55%,0.25)');
});
});
describe('hex strings', () => {
it('should convert "#rrggbb"', () => {
const color = processColor('#1e83c9');
expect(color).toEqual('rgba(30,131,201,1)');
});
it('should convert "#rgba"', () => {
const color = processColor('#123A');
expect(color).toEqual('rgba(17,34,51,0.7)');
});
it('should convert "#rrggbbaa"', () => {
const color = processColor('#1e83c9AA');
expect(color).toEqual('rgba(30,131,201,0.7)');
});
});
describe('color int', () => {
it('should convert 0xff0000ff', () => {
const color = processColor(0xff0000ff);
expect(color).toEqual('rgba(255,0,0,1)');
});
});
});

View File

@@ -9,7 +9,7 @@ describe('apis/StyleSheet/resolveBoxShadow', () => {
resolveBoxShadow(resolvedStyle, style);
expect(resolvedStyle).toEqual({
boxShadow: '0px 0px 0px rgba(255,0,0,1)'
boxShadow: '0px 0px 0px red'
});
});
@@ -28,9 +28,7 @@ describe('apis/StyleSheet/resolveBoxShadow', () => {
const style = { shadowOffset: { width: 1, height: 2 } };
resolveBoxShadow(resolvedStyle, style);
expect(resolvedStyle).toEqual({
boxShadow: '1px 2px 0px rgba(0,0,0,0)'
});
expect(resolvedStyle).toEqual({});
});
test('shadowRadius only', () => {
@@ -38,9 +36,7 @@ describe('apis/StyleSheet/resolveBoxShadow', () => {
const style = { shadowRadius: 5 };
resolveBoxShadow(resolvedStyle, style);
expect(resolvedStyle).toEqual({
boxShadow: '0px 0px 5px rgba(0,0,0,0)'
});
expect(resolvedStyle).toEqual({});
});
test('shadowOffset, shadowRadius, shadowColor', () => {

View File

@@ -10,6 +10,7 @@
*/
import normalizeValue from './normalizeValue';
import processColor from './processColor';
import resolveBoxShadow from './resolveBoxShadow';
import resolveTextShadow from './resolveTextShadow';
import resolveTransform from './resolveTransform';
@@ -36,6 +37,16 @@ const styleShortFormProperties = {
writingDirection: ['direction']
};
const colorProps = {
backgroundColor: true,
borderColor: true,
borderTopColor: true,
borderRightColor: true,
borderBottomColor: true,
borderLeftColor: true,
color: true
};
const alphaSortProps = propsArray => propsArray.sort((a, b) => {
if (a < b) {
return -1;
@@ -106,17 +117,23 @@ const createReducer = (style, styleProps) => {
break;
}
default: {
// normalize color values
let finalValue = value;
if (colorProps[prop]) {
finalValue = processColor(value);
}
const longFormProperties = styleShortFormProperties[prop];
if (longFormProperties) {
longFormProperties.forEach((longForm, i) => {
// the value of any longform property in the original styles takes
// precedence over the shortform's value
if (styleProps.indexOf(longForm) === -1) {
resolvedStyle[longForm] = value;
resolvedStyle[longForm] = finalValue;
}
});
} else {
resolvedStyle[prop] = value;
resolvedStyle[prop] = finalValue;
}
}
}

View File

@@ -0,0 +1,25 @@
import normalizeColor from 'normalize-css-color';
const processColor = (color, opacity = 1) => {
if (
color === undefined ||
color === null ||
(opacity === 1 && typeof color === 'string' && color.charAt(0) !== '#')
) {
return color;
}
// convert number and hex
const int32Color = normalizeColor(color);
if (int32Color === null) {
return undefined;
}
// convert 0xrrggbbaa into rgba
const rgba = normalizeColor.rgba(int32Color);
rgba.a = rgba.a.toFixed(1);
const { r, g, b, a } = rgba;
return `rgba(${r},${g},${b},${a * opacity})`;
};
module.exports = processColor;

View File

@@ -1,26 +1,22 @@
import normalizeColor from 'normalize-css-color';
import normalizeValue from './normalizeValue';
import processColor from './processColor';
const defaultOffset = { height: 0, width: 0 };
const applyOpacity = (color, opacity = 1) => {
const nullableColor = normalizeColor(color);
const colorInt = nullableColor === null ? 0x00000000 : nullableColor;
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
const resolveBoxShadow = (resolvedStyle, style) => {
const { height, width } = style.shadowOffset || defaultOffset;
const offsetX = normalizeValue(null, width);
const offsetY = normalizeValue(null, height);
const blurRadius = normalizeValue(null, style.shadowRadius || 0);
const color = applyOpacity(style.shadowColor, style.shadowOpacity);
const color = processColor(style.shadowColor, style.shadowOpacity);
const boxShadow = `${offsetX} ${offsetY} ${blurRadius} ${color}`;
resolvedStyle.boxShadow = style.boxShadow ? `${style.boxShadow}, ${boxShadow}` : boxShadow;
if (color) {
const boxShadow = `${offsetX} ${offsetY} ${blurRadius} ${color}`;
resolvedStyle.boxShadow = style.boxShadow ? `${style.boxShadow}, ${boxShadow}` : boxShadow;
} else if (style.boxShadow) {
resolvedStyle.boxShadow = style.boxShadow;
}
};
module.exports = resolveBoxShadow;

View File

@@ -1,4 +1,5 @@
import normalizeValue from './normalizeValue';
import processColor from './processColor';
const defaultOffset = { height: 0, width: 0 };
@@ -7,9 +8,11 @@ const resolveTextShadow = (resolvedStyle, style) => {
const offsetX = normalizeValue(null, width);
const offsetY = normalizeValue(null, height);
const blurRadius = normalizeValue(null, style.textShadowRadius || 0);
const color = style.textShadowColor || 'currentcolor';
const color = processColor(style.textShadowColor);
resolvedStyle.textShadow = `${offsetX} ${offsetY} ${blurRadius} ${color}`;
if (color) {
resolvedStyle.textShadow = `${offsetX} ${offsetY} ${blurRadius} ${color}`;
}
};
module.exports = resolveTextShadow;

View File

@@ -1,5 +1,5 @@
import asap from 'asap';
import CSSPropertyOperations from 'react-dom/lib/CSSPropertyOperations';
import requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
const getRect = node => {
const height = node.offsetHeight;
@@ -15,13 +15,15 @@ const getRect = node => {
};
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);
requestAnimationFrame(() => {
const relativeNode = relativeToNativeNode || (node && node.parentNode);
if (node && relativeNode) {
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);
}
});
};
@@ -43,13 +45,16 @@ const UIManager = {
},
measureInWindow(node, callback) {
const { height, left, top, width } = getRect(node);
callback(left, top, width, height);
requestAnimationFrame(() => {
if (node) {
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, relativeToNativeNode, onSuccess);
},
updateView(node, props, component /* only needed to surpress React errors in development */) {

View File

@@ -1,17 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/ActivityIndicator default render 1`] = `
<div
aria-valuemax="1"
aria-valuemin="0"
className="rn-alignItems-1awozwy rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-justifyContent-1777fci rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4"
role="progressbar"
style={Object {}}>
>
<div
className="rn-alignItems-1oszu61 rn-animationDuration-17bb2tj rn-animationIterationCount-1muvv40 rn-animationName-dozj4v rn-animationTimingFunction-1ldzwu0 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-height-z80fyv rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-width-19wmn03"
style={Object {}}>
>
<svg
height="100%"
viewBox="0 0 32 32"
width="100%">
width="100%"
>
<circle
cx="16"
cy="16"
@@ -23,7 +26,8 @@ exports[`components/ActivityIndicator default render 1`] = `
"opacity": 0.2,
"stroke": "#1976D2",
}
} />
}
/>
<circle
cx="16"
cy="16"
@@ -36,7 +40,8 @@ exports[`components/ActivityIndicator default render 1`] = `
"strokeDasharray": 80,
"strokeDashoffset": 60,
}
} />
}
/>
</svg>
</div>
</div>
@@ -48,14 +53,15 @@ exports[`components/ActivityIndicator other render 1`] = `
aria-valuemin="0"
className="rn-alignItems-1awozwy rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-justifyContent-1777fci rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4"
role="progressbar"
style={Object {}}>
>
<div
className="rn-alignItems-1oszu61 rn-animationDuration-17bb2tj rn-animationIterationCount-1muvv40 rn-animationName-dozj4v rn-animationPlayState-1abnn5w rn-animationTimingFunction-1ldzwu0 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-height-1r8g8re rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-width-1acpoxo"
style={Object {}}>
>
<svg
height="100%"
viewBox="0 0 32 32"
width="100%">
width="100%"
>
<circle
cx="16"
cy="16"
@@ -67,7 +73,8 @@ exports[`components/ActivityIndicator other render 1`] = `
"opacity": 0.2,
"stroke": "#1976D2",
}
} />
}
/>
<circle
cx="16"
cy="16"
@@ -80,7 +87,8 @@ exports[`components/ActivityIndicator other render 1`] = `
"strokeDasharray": 80,
"strokeDashoffset": 60,
}
} />
}
/>
</svg>
</div>
</div>

View File

@@ -1,30 +1,33 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/Image passes other props through to underlying View 1`] = `
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
onResponderGrant={[Function]}
style={Object {}} />
/>
`;
exports[`components/Image prop "accessibilityLabel" 1`] = `
<div
aria-label="accessibilityLabel"
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={Object {}} />
/>
`;
exports[`components/Image prop "accessible" 1`] = `
<div
aria-hidden={true}
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={Object {}} />
/>
`;
exports[`components/Image prop "children" 1`] = `
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={Object {}}>
>
<div
className="unique" />
className="unique"
/>
</div>
`;
@@ -33,15 +36,16 @@ exports[`components/Image prop "defaultSource" does not override "height" and "w
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={
Object {
"backgroundImage": "url(\"https://google.com/favicon.ico\")",
"backgroundImage": "url(\\"https://google.com/favicon.ico\\")",
"height": "20px",
"width": "40px",
}
}>
}
>
<img
className="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"
style={Object {}} />
/>
</div>
`;
@@ -50,15 +54,16 @@ exports[`components/Image prop "defaultSource" sets "height" and "width" styles
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={
Object {
"backgroundImage": "url(\"https://google.com/favicon.ico\")",
"backgroundImage": "url(\\"https://google.com/favicon.ico\\")",
"height": "10px",
"width": "20px",
}
}>
}
>
<img
className="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"
style={Object {}} />
/>
</div>
`;
@@ -67,13 +72,14 @@ exports[`components/Image prop "defaultSource" sets background image when value
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={
Object {
"backgroundImage": "url(\"https://google.com/favicon.ico\")",
"backgroundImage": "url(\\"https://google.com/favicon.ico\\")",
}
}>
}
>
<img
className="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"
style={Object {}} />
/>
</div>
`;
@@ -82,61 +88,62 @@ exports[`components/Image prop "defaultSource" sets background image when value
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={
Object {
"backgroundImage": "url(\"https://google.com/favicon.ico\")",
"backgroundImage": "url(\\"https://google.com/favicon.ico\\")",
}
}>
}
>
<img
className="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"
style={Object {}} />
/>
</div>
`;
exports[`components/Image prop "resizeMode" value "contain" 1`] = `
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={Object {}} />
/>
`;
exports[`components/Image prop "resizeMode" value "cover" 1`] = `
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={Object {}} />
/>
`;
exports[`components/Image prop "resizeMode" value "none" 1`] = `
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={Object {}} />
/>
`;
exports[`components/Image prop "resizeMode" value "stretch" 1`] = `
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={Object {}} />
/>
`;
exports[`components/Image prop "resizeMode" value "undefined" 1`] = `
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={Object {}} />
/>
`;
exports[`components/Image prop "style" correctly supports "resizeMode" property 1`] = `
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={Object {}} />
/>
`;
exports[`components/Image prop "testID" 1`] = `
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
data-testid="testID"
style={Object {}} />
/>
`;
exports[`components/Image sets correct accessibility role" 1`] = `
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
style={Object {}} />
/>
`;

View File

@@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/Switch disabled when "false" a default checkbox is rendered 1`] = `
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-cursor-1loqt21 rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-userSelect-lrvibr"
@@ -6,27 +8,30 @@ exports[`components/Switch disabled when "false" a default checkbox is rendered
"height": "20px",
"width": "40px",
}
}>
}
>
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-height-1dernwh rn-left-1d2f490 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-top-ipm5af rn-transitionDuration-13tjlyg rn-width-e7q0ms"
style={
Object {
"backgroundColor": "#939393",
"backgroundColor": "rgba(147,147,147,1)",
"borderBottomLeftRadius": "10px",
"borderBottomRightRadius": "10px",
"borderTopLeftRadius": "10px",
"borderTopRightRadius": "10px",
}
} />
}
/>
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-left-1fe0xdi rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-transform-emqnss rn-transitionDuration-13tjlyg"
style={
Object {
"backgroundColor": "#FAFAFA",
"backgroundColor": "rgba(250,250,250,1)",
"height": "20px",
"width": "20px",
}
} />
}
/>
<input
checked={false}
className="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"
@@ -34,8 +39,8 @@ exports[`components/Switch disabled when "false" a default checkbox is rendered
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
style={Object {}}
type="checkbox" />
type="checkbox"
/>
</div>
`;
@@ -47,9 +52,10 @@ exports[`components/Switch disabled when "true" a disabled checkbox is rendered
"height": "20px",
"width": "40px",
}
}>
}
>
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-1i8mn1y 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-height-1dernwh rn-left-1d2f490 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-top-ipm5af rn-transitionDuration-13tjlyg rn-width-e7q0ms"
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-height-1dernwh rn-left-1d2f490 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-top-ipm5af rn-transitionDuration-13tjlyg rn-width-e7q0ms"
style={
Object {
"borderBottomLeftRadius": "10px",
@@ -57,15 +63,17 @@ exports[`components/Switch disabled when "true" a disabled checkbox is rendered
"borderTopLeftRadius": "10px",
"borderTopRightRadius": "10px",
}
} />
}
/>
<div
className="rn-alignItems-1oszu61 rn-alignSelf-k200y rn-backgroundColor-1jvdyr1 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-left-1fe0xdi rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-transform-emqnss rn-transitionDuration-13tjlyg"
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-left-1fe0xdi rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-transform-emqnss rn-transitionDuration-13tjlyg"
style={
Object {
"height": "20px",
"width": "20px",
}
} />
}
/>
<input
checked={false}
className="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"
@@ -73,8 +81,8 @@ exports[`components/Switch disabled when "true" a disabled checkbox is rendered
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
style={Object {}}
type="checkbox" />
type="checkbox"
/>
</div>
`;
@@ -86,27 +94,30 @@ exports[`components/Switch value when "false" an unchecked checkbox is rendered
"height": "20px",
"width": "40px",
}
}>
}
>
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-height-1dernwh rn-left-1d2f490 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-top-ipm5af rn-transitionDuration-13tjlyg rn-width-e7q0ms"
style={
Object {
"backgroundColor": "#939393",
"backgroundColor": "rgba(147,147,147,1)",
"borderBottomLeftRadius": "10px",
"borderBottomRightRadius": "10px",
"borderTopLeftRadius": "10px",
"borderTopRightRadius": "10px",
}
} />
}
/>
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-left-1fe0xdi rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-transform-emqnss rn-transitionDuration-13tjlyg"
style={
Object {
"backgroundColor": "#FAFAFA",
"backgroundColor": "rgba(250,250,250,1)",
"height": "20px",
"width": "20px",
}
} />
}
/>
<input
checked={false}
className="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"
@@ -114,8 +125,8 @@ exports[`components/Switch value when "false" an unchecked checkbox is rendered
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
style={Object {}}
type="checkbox" />
type="checkbox"
/>
</div>
`;
@@ -127,28 +138,31 @@ exports[`components/Switch value when "true" a checked checkbox is rendered 1`]
"height": "20px",
"width": "40px",
}
}>
}
>
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-height-1dernwh rn-left-1d2f490 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-top-ipm5af rn-transitionDuration-13tjlyg rn-width-e7q0ms"
style={
Object {
"backgroundColor": "#A3D3CF",
"backgroundColor": "rgba(163,211,207,1)",
"borderBottomLeftRadius": "10px",
"borderBottomRightRadius": "10px",
"borderTopLeftRadius": "10px",
"borderTopRightRadius": "10px",
}
} />
}
/>
<div
className="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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-left-7b7h2f rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-transform-emqnss rn-transitionDuration-13tjlyg"
style={
Object {
"backgroundColor": "#009688",
"backgroundColor": "rgba(0,150,136,1)",
"height": "20px",
"marginLeft": "-20px",
"width": "20px",
}
} />
}
/>
<input
checked={true}
className="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"
@@ -156,7 +170,7 @@ exports[`components/Switch value when "true" a checked checkbox is rendered 1`]
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
style={Object {}}
type="checkbox" />
type="checkbox"
/>
</div>
`;

View File

@@ -1,7 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/Text prop "children" 1`] = `
<span
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-color-homxoj rn-display-1471scf rn-font-1lw9tu2 rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto">
dir="auto"
>
children
</span>
`;
@@ -12,19 +15,20 @@ exports[`components/Text prop "onPress" 1`] = `
dir="auto"
onClick={[Function]}
onKeyDown={[Function]}
style={Object {}}
tabIndex={0} />
tabIndex={0}
/>
`;
exports[`components/Text prop "selectable" 1`] = `
<span
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-color-homxoj rn-display-1471scf rn-font-1lw9tu2 rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto" />
dir="auto"
/>
`;
exports[`components/Text prop "selectable" 2`] = `
<span
className="rn-borderTopWidth-13yce4e rn-borderRightWidth-fnigne rn-borderBottomWidth-ndvcnb rn-borderLeftWidth-gxnn5r rn-color-homxoj rn-display-1471scf rn-font-1lw9tu2 rn-marginTop-1mnahxq rn-marginRight-61z16t rn-marginBottom-p1pxzi rn-marginLeft-11wrixw rn-paddingTop-wk8lta rn-paddingRight-9aemit rn-paddingBottom-1mdbw0j rn-paddingLeft-gy4na3 rn-textDecoration-bauka4 rn-userSelect-lrvibr rn-whiteSpace-q42fyq rn-wordWrap-qvutc0"
dir="auto"
style={Object {}} />
/>
`;

View File

@@ -36,6 +36,7 @@ class Text extends Component {
adjustsFontSizeToFit,
allowFontScaling,
ellipsizeMode,
lineBreakMode,
minimumFontScale,
onLayout,
suppressHighlighting,

View File

@@ -14,6 +14,7 @@
/* @edit start */
const BoundingDimensions = require('./BoundingDimensions');
const normalizeColor = require('normalize-css-color');
const Position = require('./Position');
const React = require('react');
const TouchEventUtils = require('fbjs/lib/TouchEventUtils');
@@ -755,7 +756,40 @@ var TouchableMixin = {
};
var Touchable = {
Mixin: TouchableMixin
Mixin: TouchableMixin,
TOUCH_TARGET_DEBUG: false, // Highlights all touchable targets. Toggle with Inspector.
/**
* Renders a debugging overlay to visualize touch target with hitSlop (might not work on Android).
*/
renderDebugView: ({ color, hitSlop }) => {
if (process.env.NODE_ENV !== 'production') {
if (!Touchable.TOUCH_TARGET_DEBUG) {
return null;
}
const debugHitSlopStyle = {};
hitSlop = hitSlop || { top: 0, bottom: 0, left: 0, right: 0 };
for (const key in hitSlop) {
debugHitSlopStyle[key] = -hitSlop[key];
}
const hexColor = '#' + ('00000000' + normalizeColor(color).toString(16)).substr(-8);
return (
<View
pointerEvents="none"
style={{
position: 'absolute',
borderColor: hexColor.slice(0, -2) + '55', // More opaque
borderWidth: 1,
borderStyle: 'dashed',
backgroundColor: hexColor.slice(0, -2) + '0F', // Less opaque
...debugHitSlopStyle
}}
/>
);
}
}
};
module.exports = Touchable;

View File

@@ -231,6 +231,7 @@ var TouchableHighlight = React.createClass({
render: function() {
const {
children,
/* eslint-disable */
activeOpacity,
onHideUnderlay,
@@ -270,9 +271,10 @@ var TouchableHighlight = React.createClass({
style={[styles.root, this.props.disabled && styles.disabled, this.state.underlayStyle]}
tabIndex={this.props.disabled ? null : '0'}
>
{React.cloneElement(React.Children.only(this.props.children), {
{React.cloneElement(React.Children.only(children), {
ref: CHILD_REF
})}
{Touchable.renderDebugView({ color: 'green', hitSlop: this.props.hitSlop })}
</View>
);
}

View File

@@ -160,6 +160,7 @@ var TouchableOpacity = React.createClass({
render: function() {
const {
children,
/* eslint-disable */
activeOpacity,
focusedOpacity,
@@ -195,7 +196,10 @@ var TouchableOpacity = React.createClass({
onResponderRelease={this.touchableHandleResponderRelease}
onResponderTerminate={this.touchableHandleResponderTerminate}
tabIndex={this.props.disabled ? null : '0'}
/>
>
{children}
{Touchable.renderDebugView({ color: 'blue', hitSlop: this.props.hitSlop })}
</View>
);
}
});

View File

@@ -166,6 +166,15 @@ const TouchableWithoutFeedback = React.createClass({
'TouchableWithoutFeedback does not work well with Text children. Wrap children in a View instead. See ' +
((child._owner && child._owner.getName && child._owner.getName()) || '<unknown>')
);
if (
process.env.NODE_ENV !== 'production' &&
Touchable.TOUCH_TARGET_DEBUG &&
child.type &&
child.type.displayName === 'View'
) {
children = React.Children.toArray(children);
children.push(Touchable.renderDebugView({ color: 'red', hitSlop: this.props.hitSlop }));
}
const style = Touchable.TOUCH_TARGET_DEBUG && child.type && child.type.displayName === 'Text'
? [styles.root, this.props.disabled && styles.disabled, child.props.style, { color: 'red' }]
: [styles.root, this.props.disabled && styles.disabled, child.props.style];

View File

@@ -1,29 +1,69 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/View prop "children" 1`] = `
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4">
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4"
>
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4"
data-testid="1" />
data-testid="1"
/>
</div>
`;
exports[`components/View prop "hitSlop" handles partial offsets 1`] = `
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
>
<span
className="rn-bottom-1p0dtai rn-left-1d2f490 rn-position-u8s1d rn-right-zchlnj rn-zIndex-1wyyakw"
style={
Object {
"top": "-10px",
}
}
/>
</div>
`;
exports[`components/View prop "hitSlop" renders a span with negative position offsets 1`] = `
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4 rn-zIndex-1lgpqti"
>
<span
className="rn-position-u8s1d rn-zIndex-1wyyakw"
style={
Object {
"bottom": "-10px",
"left": "-5px",
"right": "-5px",
"top": "-10px",
}
}
/>
</div>
`;
exports[`components/View prop "pointerEvents" 1`] = `
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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 rn-textAlign-1ttztb7 rn-textDecoration-bauka4"
style={Object {}} />
/>
`;
exports[`components/View rendered element is a "div" by default 1`] = `
<div
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4" />
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4"
/>
`;
exports[`components/View rendered element is a "span" when inside <View accessibilityRole="button" /> 1`] = `
<button
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4"
className="rn-alignItems-1oszu61 rn-appearance-30o5oe rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4"
role="button"
type="button">
type="button"
>
<span
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4" />
className="rn-alignItems-1oszu61 rn-backgroundColor-wib322 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-color-homxoj rn-display-6koalj rn-flexShrink-1qe8dj5 rn-flexBasis-1mlwlqe rn-flexDirection-eqz5dr rn-font-1lw9tu2 rn-listStyle-1ebb2ja 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-textAlign-1ttztb7 rn-textDecoration-bauka4"
/>
</button>
`;

View File

@@ -25,6 +25,20 @@ describe('components/View', () => {
expect(component.toJSON()).toMatchSnapshot();
});
describe('prop "hitSlop"', () => {
it('renders a span with negative position offsets', () => {
const component = renderer.create(
<View hitSlop={{ top: 10, bottom: 10, right: 5, left: 5 }} />
);
expect(component.toJSON()).toMatchSnapshot();
});
it('handles partial offsets', () => {
const component = renderer.create(<View hitSlop={{ top: 10 }} />);
expect(component.toJSON()).toMatchSnapshot();
});
});
test('prop "pointerEvents"', () => {
const component = renderer.create(<View pointerEvents="box-only" />);
expect(component.toJSON()).toMatchSnapshot();

View File

@@ -1,48 +1,22 @@
import '../../modules/injectResponderEventPlugin';
import applyLayout from '../../modules/applyLayout';
import applyNativeMethods from '../../modules/applyNativeMethods';
import createDOMElement from '../../modules/createDOMElement';
import normalizeNativeEvent from '../../modules/normalizeNativeEvent';
import getAccessibilityRole from '../../modules/getAccessibilityRole';
import StyleSheet from '../../apis/StyleSheet';
import ViewPropTypes from './ViewPropTypes';
import { Component, PropTypes } from 'react';
import React, { Component, PropTypes } from 'react';
const eventHandlerNames = [
'onClick',
'onClickCapture',
'onMoveShouldSetResponder',
'onMoveShouldSetResponderCapture',
'onResponderGrant',
'onResponderMove',
'onResponderReject',
'onResponderRelease',
'onResponderTerminate',
'onResponderTerminationRequest',
'onStartShouldSetResponder',
'onStartShouldSetResponderCapture',
'onTouchCancel',
'onTouchCancelCapture',
'onTouchEnd',
'onTouchEndCapture',
'onTouchMove',
'onTouchMoveCapture',
'onTouchStart',
'onTouchStartCapture'
];
const emptyObject = {};
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);
const calculateHitSlopStyle = hitSlop => {
const hitStyle = {};
for (const prop in hitSlop) {
if (hitSlop.hasOwnProperty(prop)) {
const value = hitSlop[prop];
hitStyle[prop] = value > 0 ? (-1) * value : 0;
}
});
}
return hitStyle;
};
class View extends Component {
@@ -63,20 +37,17 @@ class View extends Component {
};
getChildContext() {
return {
isInAButtonView: this.props.accessibilityRole === 'button'
};
const isInAButtonView = getAccessibilityRole(this.props) === 'button' ||
this.context.isInAButtonView;
return isInAButtonView ? { isInAButtonView } : emptyObject;
}
render() {
const {
pointerEvents,
hitSlop,
style,
/* eslint-disable */
accessibilityComponentType,
accessibilityTraits,
collapsable,
hitSlop,
onAccessibilityTap,
onLayout,
onMagicTap,
@@ -85,13 +56,20 @@ class View extends Component {
...otherProps
} = this.props;
const component = this.context.isInAButtonView ? 'span' : 'div';
const { isInAButtonView } = this.context;
const isButton = getAccessibilityRole(this.props) === 'button';
// DOM events need to be normalized to expect RN format
normalizeEventHandlers(otherProps);
otherProps.style = [styles.initial, isButton && styles.buttonOnly, style];
otherProps.style = [styles.initial, style, pointerEvents && pointerEventStyles[pointerEvents]];
if (hitSlop) {
const hitSlopStyle = calculateHitSlopStyle(hitSlop);
const hitSlopChild = createDOMElement('span', { style: [styles.hitSlop, hitSlopStyle] });
otherProps.children = React.Children.toArray(otherProps.children);
otherProps.children.unshift(hitSlopChild);
otherProps.style.unshift(styles.hasHitSlop);
}
const component = isInAButtonView ? 'span' : 'div';
return createDOMElement(component, otherProps);
}
}
@@ -109,7 +87,7 @@ const styles = StyleSheet.create({
margin: 0,
padding: 0,
position: 'relative',
// button and anchor reset
// button and anchor resets
backgroundColor: 'transparent',
color: 'inherit',
font: 'inherit',
@@ -120,21 +98,18 @@ const styles = StyleSheet.create({
// fix flexbox bugs
minHeight: 0,
minWidth: 0
}
});
const pointerEventStyles = StyleSheet.create({
auto: {
pointerEvents: 'auto'
},
'box-none': {
pointerEvents: 'box-none'
buttonOnly: {
appearance: 'none'
},
'box-only': {
pointerEvents: 'box-only'
// this zIndex ordering positions the hitSlop above the View but behind
// its children
hasHitSlop: {
zIndex: 0
},
none: {
pointerEvents: 'none'
hitSlop: {
...StyleSheet.absoluteFillObject,
zIndex: -1
}
});

View File

@@ -6,6 +6,7 @@
* @flow
*/
import createDOMProps from '../createDOMProps';
import findNodeHandle from '../findNodeHandle';
import StyleRegistry from '../../apis/StyleSheet/registry';
import UIManager from '../../apis/UIManager';
@@ -70,10 +71,9 @@ const NativeMethodsMixin = {
const node = findNodeHandle(this);
const classList = [...node.classList];
const { className, style } = StyleRegistry.resolveStateful(nativeProps.style, classList);
const props = { ...nativeProps, className, style };
UIManager.updateView(node, props, this);
const domProps = createDOMProps(nativeProps, style =>
StyleRegistry.resolveStateful(style, classList));
UIManager.updateView(node, domProps, this);
}
};

View File

@@ -5,24 +5,66 @@
* @flow
*/
import emptyFunction from 'fbjs/lib/emptyFunction';
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import debounce from 'debounce';
const emptyObject = {};
const registry = {};
let id = 1;
const guid = () => `r-${id++}`;
if (canUseDOM) {
const triggerAll = () => {
Object.keys(registry).forEach(key => {
const instance = registry[key];
instance._handleLayout();
});
};
window.addEventListener('resize', debounce(triggerAll, 16), false);
}
const safeOverride = (original, next) => {
if (original) {
return function prototypeOverride() {
original.call(this);
next.call(this);
};
}
return next;
};
const applyLayout = Component => {
const componentDidMount = Component.prototype.componentDidMount || emptyFunction;
const componentDidUpdate = Component.prototype.componentDidUpdate || emptyFunction;
const componentDidMount = Component.prototype.componentDidMount;
const componentDidUpdate = Component.prototype.componentDidUpdate;
const componentWillUnmount = Component.prototype.componentWillUnmount;
Component.prototype.componentDidMount = function() {
componentDidMount.call(this);
this._layoutState = emptyObject;
this._handleLayout();
};
Component.prototype.componentDidMount = safeOverride(
componentDidMount,
function componentDidMount() {
this._layoutState = emptyObject;
this._isMounted = true;
this._onLayoutId = guid();
registry[this._onLayoutId] = this;
this._handleLayout();
}
);
Component.prototype.componentDidUpdate = function() {
componentDidUpdate.call(this);
this._handleLayout();
};
Component.prototype.componentDidUpdate = safeOverride(
componentDidUpdate,
function componentDidUpdate() {
this._handleLayout();
}
);
Component.prototype.componentWillUnmount = safeOverride(
componentWillUnmount,
function componentWillUnmount() {
this._isMounted = false;
delete registry[this._onLayoutId];
}
);
Component.prototype._handleLayout = function() {
const layout = this._layoutState;
@@ -30,13 +72,14 @@ const applyLayout = Component => {
if (onLayout) {
this.measure((x, y, width, height) => {
if (!this._isMounted) return;
if (
layout.x !== x || layout.y !== y || layout.width !== width || layout.height !== height
) {
const nextLayout = { x, y, width, height };
const nativeEvent = { layout: nextLayout };
this._layoutState = { x, y, width, height };
const nativeEvent = { layout: this._layoutState };
onLayout({ nativeEvent, timeStamp: Date.now() });
this._layoutState = nextLayout;
}
});
}

View File

@@ -1,29 +1,62 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`modules/createDOMElement prop "accessibilityLabel" 1`] = `
<span
aria-label="accessibilityLabel" />
aria-label="accessibilityLabel"
/>
`;
exports[`modules/createDOMElement prop "accessibilityLiveRegion" 1`] = `
<span
aria-live="polite" />
aria-live="polite"
/>
`;
exports[`modules/createDOMElement prop "accessibilityRole" button 1`] = `
<button
role="button"
type="button" />
type="button"
/>
`;
exports[`modules/createDOMElement prop "accessibilityRole" compatibility with accessibilityComponentType 1`] = `
<button
role="button"
type="button"
/>
`;
exports[`modules/createDOMElement prop "accessibilityRole" compatibility with accessibilityComponentType 2`] = `
<a
role="link"
/>
`;
exports[`modules/createDOMElement prop "accessibilityRole" compatibility with accessibilityTraits 1`] = `
<button
role="button"
type="button"
/>
`;
exports[`modules/createDOMElement prop "accessibilityRole" compatibility with accessibilityTraits 2`] = `
<a
role="link"
/>
`;
exports[`modules/createDOMElement prop "accessibilityRole" link and target="_blank" 1`] = `
<a
rel=" noopener noreferrer"
role="link"
target="_blank" />
target="_blank"
/>
`;
exports[`modules/createDOMElement prop "accessibilityRole" roles 1`] = `
<header
role="banner" />
role="banner"
/>
`;
exports[`modules/createDOMElement prop "accessible" 1`] = `<span />`;
@@ -32,12 +65,14 @@ exports[`modules/createDOMElement prop "accessible" 2`] = `<span />`;
exports[`modules/createDOMElement prop "accessible" 3`] = `
<span
aria-hidden={true} />
aria-hidden={true}
/>
`;
exports[`modules/createDOMElement prop "testID" 1`] = `
<span
data-testid="Example.testID" />
data-testid="Example.testID"
/>
`;
exports[`modules/createDOMElement renders correct DOM element 1`] = `<span />`;

View File

@@ -43,6 +43,35 @@ describe('modules/createDOMElement', () => {
);
expect(component.toJSON()).toMatchSnapshot();
});
describe('compatibility with', () => {
test('accessibilityComponentType', () => {
let component = renderer.create(
createDOMElement('span', { accessibilityComponentType: 'button' })
);
expect(component.toJSON()).toMatchSnapshot();
component = renderer.create(
createDOMElement('span', {
accessibilityComponentType: 'button',
accessibilityRole: 'link'
})
);
expect(component.toJSON()).toMatchSnapshot();
});
test('accessibilityTraits', () => {
let component = renderer.create(
createDOMElement('span', { accessibilityTraits: 'button' })
);
expect(component.toJSON()).toMatchSnapshot();
component = renderer.create(
createDOMElement('span', { accessibilityTraits: 'button', accessibilityRole: 'link' })
);
expect(component.toJSON()).toMatchSnapshot();
});
});
});
test('prop "accessible"', () => {

View File

@@ -1,3 +1,8 @@
import '../injectResponderEventPlugin';
import createDOMProps from '../createDOMProps';
import getAccessibilityRole from '../getAccessibilityRole';
import normalizeNativeEvent from '../normalizeNativeEvent';
import React from 'react';
import StyleRegistry from '../../apis/StyleSheet/registry';
@@ -19,52 +24,52 @@ const roleComponents = {
region: 'section'
};
const createDOMElement = (component, rnProps) => {
const {
accessibilityLabel,
accessibilityLiveRegion,
accessibilityRole,
accessible = true,
style: rnStyle, // we need to remove the RN styles from 'domProps'
testID,
type,
...domProps
} = rnProps || emptyObject;
const eventHandlerNames = {
onClick: true,
onClickCapture: true,
onMoveShouldSetResponder: true,
onMoveShouldSetResponderCapture: true,
onResponderGrant: true,
onResponderMove: true,
onResponderReject: true,
onResponderRelease: true,
onResponderTerminate: true,
onResponderTerminationRequest: true,
onStartShouldSetResponder: true,
onStartShouldSetResponderCapture: true,
onTouchCancel: true,
onTouchCancelCapture: true,
onTouchEnd: true,
onTouchEndCapture: true,
onTouchMove: true,
onTouchMoveCapture: true,
onTouchStart: true,
onTouchStartCapture: true
};
const accessibilityComponent = accessibilityRole && roleComponents[accessibilityRole];
const wrapEventHandler = handler => e => {
e.nativeEvent = normalizeNativeEvent(e.nativeEvent);
return handler(e);
};
const createDOMElement = (component, rnProps) => {
// use equivalent platform elements where possible
const role = getAccessibilityRole(rnProps || emptyObject);
const accessibilityComponent = role && roleComponents[role];
const Component = accessibilityComponent || component;
const { className, style } = StyleRegistry.resolve(rnStyle) || emptyObject;
const domProps = createDOMProps(rnProps, style => StyleRegistry.resolve(style));
if (!accessible) {
domProps['aria-hidden'] = true;
}
if (accessibilityLabel) {
domProps['aria-label'] = accessibilityLabel;
}
if (accessibilityLiveRegion) {
domProps['aria-live'] = accessibilityLiveRegion;
}
if (testID) {
domProps['data-testid'] = testID;
}
if (accessibilityRole) {
domProps.role = accessibilityRole;
if (accessibilityRole === 'button') {
domProps.type = 'button';
} else if (accessibilityRole === 'link' && domProps.target === '_blank') {
domProps.rel = `${domProps.rel || ''} noopener noreferrer`;
// normalize DOM events to match React Native events
// TODO: move this out of the render path
for (const prop in domProps) {
if (Object.prototype.hasOwnProperty.call(domProps, prop)) {
const isEventHandler = typeof prop === 'function' && eventHandlerNames[prop];
if (isEventHandler) {
domProps[prop] = wrapEventHandler(prop);
}
}
}
if (className && className !== '') {
domProps.className = domProps.className ? `${domProps.className} ${className}` : className;
}
if (style) {
domProps.style = style;
}
if (type) {
domProps.type = type;
}
return <Component {...domProps} />;
};

View File

@@ -0,0 +1,75 @@
import getAccessibilityRole from '../getAccessibilityRole';
import StyleSheet from '../../apis/StyleSheet';
const emptyObject = {};
const pointerEventStyles = StyleSheet.create({
auto: {
pointerEvents: 'auto'
},
'box-none': {
pointerEvents: 'box-none'
},
'box-only': {
pointerEvents: 'box-only'
},
none: {
pointerEvents: 'none'
}
});
const createDOMProps = (rnProps, resolveStyle) => {
const {
accessibilityLabel,
accessibilityLiveRegion,
accessible = true,
pointerEvents,
style: rnStyle,
testID,
type,
/* eslint-disable */
accessibilityComponentType,
accessibilityRole,
accessibilityTraits,
/* eslint-enable */
...domProps
} = rnProps || emptyObject;
const pointerEventStyle = pointerEvents && pointerEventStyles[pointerEvents];
const { className, style } = resolveStyle([rnStyle, pointerEventStyle]) || emptyObject;
const role = getAccessibilityRole(rnProps || emptyObject);
if (!accessible) {
domProps['aria-hidden'] = true;
}
if (accessibilityLabel) {
domProps['aria-label'] = accessibilityLabel;
}
if (accessibilityLiveRegion) {
domProps['aria-live'] = accessibilityLiveRegion;
}
if (className && className !== '') {
domProps.className = domProps.className ? `${domProps.className} ${className}` : className;
}
if (role) {
domProps.role = role;
if (role === 'button') {
domProps.type = 'button';
} else if (role === 'link' && domProps.target === '_blank') {
domProps.rel = `${domProps.rel || ''} noopener noreferrer`;
}
}
if (style) {
domProps.style = style;
}
if (testID) {
domProps['data-testid'] = testID;
}
if (type) {
domProps.type = type;
}
return domProps;
};
module.exports = createDOMProps;

View File

@@ -0,0 +1,28 @@
/* eslint-env jasmine, jest */
import getAccessibilityRole from '..';
describe('modules/getAccessibilityRole', () => {
test('returns undefined when missing accessibility props', () => {
expect(getAccessibilityRole({})).toBeUndefined();
});
test('returns value of "accessibilityRole" when defined', () => {
expect(getAccessibilityRole({ accessibilityRole: 'banner' })).toEqual('banner');
});
test('returns "button" when iOS/Android accessibility prop equals "button"', () => {
expect(getAccessibilityRole({ accessibilityComponentType: 'button' })).toEqual('button');
expect(getAccessibilityRole({ accessibilityTraits: 'button' })).toEqual('button');
});
test('prioritizes "accessibilityRole" when defined', () => {
expect(
getAccessibilityRole({
accessibilityComponentType: 'button',
accessibilityRole: 'link',
accessibilityTraits: 'button'
})
).toEqual('link');
});
});

View File

@@ -0,0 +1,15 @@
const getAccessibilityRole = (
{
accessibilityComponentType,
accessibilityRole,
accessibilityTraits
}
) => {
if (accessibilityRole) {
return accessibilityRole;
} else if (accessibilityComponentType === 'button' || accessibilityTraits === 'button') {
return 'button';
}
};
module.exports = getAccessibilityRole;

826
yarn.lock

File diff suppressed because it is too large Load Diff