Compare commits

..

46 Commits

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

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

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

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

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

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

Fix #315
2017-01-04 10:43:19 -08:00
Nicolas Gallagher
8d2a650670 [fix] StyleSheet selector escaping
Values that contain '*' (e.g. 'calc(2 * 2)') were not properly escaped,
resulting in broken selectors.
2017-01-03 14:25:39 -08:00
56 changed files with 474 additions and 727 deletions

View File

@@ -99,6 +99,14 @@ from `style`.
+ `alignContent`
+ `alignItems`
+ `alignSelf`
+ `animationDelay`
+ `animationDirection`
+ `animationDuration`
+ `animationFillMode`
+ `animationIterationCount`
+ `animationName`
+ `animationPlayState`
+ `animationTimingFunction`
+ `backfaceVisibility`
+ `backgroundAttachment`
+ `backgroundClip`
@@ -164,10 +172,17 @@ from `style`.
+ `paddingRight`
+ `paddingTop`
+ `paddingVertical`
+ `perspective`
+ `perspectiveOrigin`
+ `position`
+ `right`
+ `top`
+ `transform`
+ `transformOrigin`
+ `transitionDelay`
+ `transitionDuration`
+ `transitionProperty`
+ `transitionTimingFunction`
+ `userSelect`
+ `visibility`
+ `width`

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-web",
"version": "0.0.63",
"version": "0.0.71",
"description": "React Native for Web",
"main": "dist/index.js",
"files": [
@@ -30,6 +30,7 @@
"deep-assign": "^2.0.0",
"fbjs": "^0.8.8",
"inline-style-prefixer": "^2.0.5",
"normalize-css-color": "^1.0.2",
"react-dom": "~15.4.1",
"react-textarea-autosize": "^4.0.4",
"react-timer-mixin": "^0.13.3"
@@ -40,7 +41,7 @@
"babel-core": "^6.21.0",
"babel-eslint": "^7.1.1",
"babel-loader": "^6.2.10",
"babel-plugin-transform-react-remove-prop-types": "^0.2.11",
"babel-plugin-transform-react-remove-prop-types": "^0.3.0",
"babel-preset-react-native": "^1.9.1",
"del-cli": "^0.2.1",
"enzyme": "^2.4.1",
@@ -57,7 +58,7 @@
"react-test-renderer": "~15.4.1",
"url-loader": "^0.5.7",
"webpack": "^1.13.2",
"webpack-bundle-analyzer": "^1.5.3"
"webpack-bundle-analyzer": "^2.2.1"
},
"peerDependencies": {
"react": "~15.4.1"

View File

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

View File

@@ -7,7 +7,7 @@ button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit-search-cancel-button,input::-webkit-search-decoration,input::-webkit-search-results-button,input::-webkit-search-results-decoration{display:none}
@keyframes rn-ActivityIndicator-animation{0%{-webkit-transform: rotate(0deg); transform: rotate(0deg);}100%{-webkit-transform: rotate(360deg); transform: rotate(360deg);}}
@keyframes rn-ProgressBar-animation{0%{-webkit-transform: translateX(-100%); transform: translateX(-100%);}100%{-webkit-transform: translateX(400%); transform: translateX(400%);}}
.rn-pointerEvents\\:auto,.rn_pointerEvents\\:box-only,.rn-pointerEvents\\:box-none *{pointer-events:auto}.rn-pointerEvents\\:none,.rn_pointerEvents\\:box-only *,.rn-pointerEvents\\:box-none{pointer-events:none}
.rn-pointerEvents\\:auto,.rn-pointerEvents\\:box-only,.rn-pointerEvents\\:box-none *{pointer-events:auto}.rn-pointerEvents\\:none,.rn-pointerEvents\\:box-only *,.rn-pointerEvents\\:box-none{pointer-events:none}
.rn-bottom\\:0px{bottom:0px}
.rn-left\\:0px{left:0px}
.rn-position\\:absolute{position:absolute}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -12,9 +12,9 @@ import mapKeyValue from '../../modules/mapKeyValue';
import prefixInlineStyles from './prefixInlineStyles';
import ReactNativePropRegistry from '../../modules/ReactNativePropRegistry';
const prefix = 'r';
const prefix = 'r-';
const SPACE_REGEXP = /\s/g;
const ESCAPE_SELECTOR_CHARS_REGEXP = /[(),":?.%\\$#]/g;
const ESCAPE_SELECTOR_CHARS_REGEXP = /[(),":?.%\\$#*]/g;
/**
* Creates an HTML class name for use on elements
@@ -24,6 +24,14 @@ const createClassName = (prop, value) => {
return `rn-${prop}:${val}`;
};
/**
* Formatting improves debugging in devtools and snapshot
*/
const mapDeclarationsToClassName = (style, fn) => {
const result = mapKeyValue(style, fn).join('\n').trim();
return `\n${result}`;
};
/**
* Inject a CSS rule for a given declaration and record the availability of the
* resulting class name.
@@ -50,13 +58,13 @@ const injectClassNameIfNeeded = (prop, value) => {
let resolvedPropsCache = {};
const registerStyle = (id, flatStyle) => {
const style = createReactDOMStyle(flatStyle);
const className = mapKeyValue(style, (prop, value) => {
const className = mapDeclarationsToClassName(style, (prop, value) => {
if (value != null) {
return injectClassNameIfNeeded(prop, value);
}
}).join(' ').trim();
});
const key = `${prefix}-${id}`;
const key = `${prefix}${id}`;
resolvedPropsCache[key] = { className };
return id;
@@ -70,7 +78,7 @@ const resolveProps = (reactNativeStyle) => {
const domStyle = createReactDOMStyle(flatStyle);
const style = {};
const _className = mapKeyValue(domStyle, (prop, value) => {
const className = mapDeclarationsToClassName(domStyle, (prop, value) => {
if (value != null) {
const singleClassName = createClassName(prop, value);
if (injectedClassNames[singleClassName]) {
@@ -80,18 +88,14 @@ const resolveProps = (reactNativeStyle) => {
style[prop] = value;
}
}
})
// improves debugging in devtools and snapshots
.join('\n')
.trim();
const className = `\n${_className}`;
});
const props = {
className,
style: prefixInlineStyles(style)
};
/*
if (process.env.__REACT_NATIVE_DEBUG_ENABLED__) {
console.groupCollapsed('[StyleSheet] resolving uncached styles');
console.log(
@@ -103,6 +107,7 @@ const resolveProps = (reactNativeStyle) => {
console.log('resolve => \n', props);
console.groupEnd();
}
*/
return props;
};
@@ -128,6 +133,7 @@ const StyleRegistry = {
initialize(classNames) {
injectedClassNames = classNames;
/*
if (process.env.__REACT_NATIVE_DEBUG_ENABLED__) {
if (global.__REACT_NATIVE_DEBUG_ENABLED__styleRegistryTimer) {
clearInterval(global.__REACT_NATIVE_DEBUG_ENABLED__styleRegistryTimer);
@@ -139,6 +145,7 @@ const StyleRegistry = {
console.groupEnd();
}, 30000);
}
*/
},
reset() {
@@ -203,7 +210,7 @@ const StyleRegistry = {
// if (!hasValidKey) { key = null; }
// cache resolved props when all styles are registered
const key = isArrayOfNumbers ? `${prefix}-${flatArray.join('-')}` : null;
const key = isArrayOfNumbers ? `${prefix}${flatArray.join('-')}` : null;
return resolvePropsIfNeeded(key, flatArray);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,6 +7,7 @@ import requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
import StyleSheet from '../../apis/StyleSheet';
import StyleSheetPropType from '../../propTypes/StyleSheetPropType';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import React, { Component, PropTypes } from 'react';
const emptyObject = {};
@@ -41,7 +42,7 @@ class Image extends Component {
static displayName = 'Image';
static propTypes = {
...View.propTypes,
...ViewPropTypes,
children: PropTypes.any,
defaultSource: ImageSourcePropType,
onError: PropTypes.func,

View File

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

View File

@@ -1,9 +1,9 @@
import ListViewDataSource from './ListViewDataSource';
import { PropTypes } from 'react';
import ScrollView from '../ScrollView';
import { propTypes as ScrollViewPropTypes } from '../ScrollView';
export default {
...ScrollView.propTypes,
...ScrollViewPropTypes,
dataSource: PropTypes.instanceOf(ListViewDataSource).isRequired,
renderSeparator: PropTypes.func,
renderRow: PropTypes.func.isRequired,

View File

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

View File

@@ -2,13 +2,14 @@ import applyNativeMethods from '../../modules/applyNativeMethods';
import ColorPropType from '../../propTypes/ColorPropType';
import StyleSheet from '../../apis/StyleSheet';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import React, { Component, PropTypes } from 'react';
class ProgressBar extends Component {
static displayName = 'ProgressBar';
static propTypes = {
...View.propTypes,
...ViewPropTypes,
color: ColorPropType,
indeterminate: PropTypes.bool,
progress: PropTypes.number,

View File

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

View File

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

View File

@@ -5,6 +5,7 @@ import multiplyStyleLengthValue from '../../modules/multiplyStyleLengthValue';
import StyleSheet from '../../apis/StyleSheet';
import UIManager from '../../apis/UIManager';
import View from '../View';
import ViewPropTypes from '../View/ViewPropTypes';
import React, { Component, PropTypes } from 'react';
const emptyObject = {};
@@ -15,7 +16,7 @@ class Switch extends Component {
static displayName = 'Switch';
static propTypes = {
...View.propTypes,
...ViewPropTypes,
activeThumbColor: ColorPropType,
activeTrackColor: ColorPropType,
disabled: PropTypes.bool,

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,7 +14,6 @@
/* @edit start */
const BoundingDimensions = require('./BoundingDimensions');
const normalizeColor = require('../../modules/normalizeColor');
const Position = require('./Position');
const React = require('react');
const TouchEventUtils = require('fbjs/lib/TouchEventUtils');

View File

@@ -27,7 +27,7 @@ var ViewStylePropTypes = require('../View/ViewStylePropTypes');
var ensureComponentIsNative = require('./ensureComponentIsNative');
var ensurePositiveDelayProps = require('./ensurePositiveDelayProps');
var keyOf = require('fbjs/lib/keyOf');
var TouchableWithoutFeedbackPropTypes = TouchableWithoutFeedback.propTypes
type Event = Object;
@@ -68,7 +68,7 @@ var PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
var TouchableHighlight = React.createClass({
propTypes: {
...TouchableWithoutFeedback.propTypes,
...TouchableWithoutFeedbackPropTypes,
/**
* Determines what the opacity of the wrapped view should be when touch is
* active.
@@ -268,8 +268,9 @@ var TouchableHighlight = React.createClass({
}
});
var CHILD_REF = keyOf({childRef: null});
var UNDERLAY_REF = keyOf({underlayRef: null});
var CHILD_REF = 'childRef';
var UNDERLAY_REF = 'underlayRef';
var INACTIVE_CHILD_PROPS = {
style: StyleSheet.create({x: {opacity: 1.0}}).x,
};

View File

@@ -24,6 +24,7 @@ var View = require('../View');
var ensurePositiveDelayProps = require('./ensurePositiveDelayProps');
var flattenStyle = StyleSheet.flatten
var TouchableWithoutFeedbackPropTypes = TouchableWithoutFeedback.propTypes;
type Event = Object;
@@ -54,7 +55,7 @@ var TouchableOpacity = React.createClass({
mixins: [TimerMixin, Touchable.Mixin, NativeMethodsMixin],
propTypes: {
...TouchableWithoutFeedback.propTypes,
...TouchableWithoutFeedbackPropTypes,
/**
* Determines what the opacity of the wrapped view should be when touch is
* active.
@@ -87,7 +88,7 @@ var TouchableOpacity = React.createClass({
this.setNativeProps({
style: {
opacity: value,
transitionDuration: duration
transitionDuration: `${duration / 1000}s`
}
});
},

View File

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

View File

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

View File

@@ -2,13 +2,10 @@ import '../../modules/injectResponderEventPlugin';
import applyLayout from '../../modules/applyLayout';
import applyNativeMethods from '../../modules/applyNativeMethods';
import BaseComponentPropTypes from '../../propTypes/BaseComponentPropTypes';
import createDOMElement from '../../modules/createDOMElement';
import EdgeInsetsPropType from '../../propTypes/EdgeInsetsPropType';
import normalizeNativeEvent from '../../modules/normalizeNativeEvent';
import StyleSheet from '../../apis/StyleSheet';
import StyleSheetPropType from '../../propTypes/StyleSheetPropType';
import ViewStylePropTypes from './ViewStylePropTypes';
import ViewPropTypes from './ViewPropTypes';
import { Component, PropTypes } from 'react';
const eventHandlerNames = [
@@ -37,35 +34,7 @@ const eventHandlerNames = [
class View extends Component {
static displayName = 'View';
static propTypes = {
...BaseComponentPropTypes,
children: PropTypes.any,
collapsable: PropTypes.bool,
hitSlop: EdgeInsetsPropType,
onClick: PropTypes.func,
onClickCapture: PropTypes.func,
onLayout: PropTypes.func,
onMoveShouldSetResponder: PropTypes.func,
onMoveShouldSetResponderCapture: PropTypes.func,
onResponderGrant: PropTypes.func,
onResponderMove: PropTypes.func,
onResponderReject: PropTypes.func,
onResponderRelease: PropTypes.func,
onResponderTerminate: PropTypes.func,
onResponderTerminationRequest: PropTypes.func,
onStartShouldSetResponder: PropTypes.func,
onStartShouldSetResponderCapture: PropTypes.func,
onTouchCancel: PropTypes.func,
onTouchCancelCapture: PropTypes.func,
onTouchEnd: PropTypes.func,
onTouchEndCapture: PropTypes.func,
onTouchMove: PropTypes.func,
onTouchMoveCapture: PropTypes.func,
onTouchStart: PropTypes.func,
onTouchStartCapture: PropTypes.func,
pointerEvents: PropTypes.oneOf([ 'auto', 'box-none', 'box-only', 'none' ]),
style: StyleSheetPropType(ViewStylePropTypes)
};
static propTypes = ViewPropTypes;
static defaultProps = {
accessible: true

View File

@@ -1,8 +1,5 @@
import findNodeHandle from './modules/findNodeHandle';
import ReactDefaultInjection from 'react-dom/lib/ReactDefaultInjection';
import { render, unmountComponentAtNode } from 'react-dom/lib/ReactMount';
ReactDefaultInjection.inject();
import { render, unmountComponentAtNode } from 'react-dom';
// APIs
import I18nManager from './apis/I18nManager';

View File

@@ -1,8 +1,5 @@
import findNodeHandle from './modules/findNodeHandle';
import ReactDefaultInjection from 'react-dom/lib/ReactDefaultInjection';
import { render, unmountComponentAtNode } from 'react-dom/lib/ReactMount';
ReactDefaultInjection.inject();
import { render, unmountComponentAtNode } from 'react-dom';
// APIs
import Animated from './apis/Animated';

View File

@@ -7,8 +7,22 @@
*/
import findNodeHandle from '../findNodeHandle';
import StyleRegistry from '../../apis/StyleSheet/registry';
import UIManager from '../../apis/UIManager';
const emptyObject = {};
const REGEX_CLASSNAME_SPLIT = /\s+/;
const REGEX_STYLE_PROP = /rn-(.*):.*/;
const classNameFilter = (className) => { return className !== ''; };
const classNameToList = (className = '') => className.split(REGEX_CLASSNAME_SPLIT).filter(classNameFilter);
const getStyleProp = (className) => {
const match = className.match(REGEX_STYLE_PROP);
if (match) {
return match[1];
}
};
const NativeMethodsMixin = {
/**
* Removes focus from an input or view. This is the opposite of `focus()`.
@@ -45,7 +59,7 @@ const NativeMethodsMixin = {
* - height
*
* Note that these measurements are not available until after the rendering
* has been completed in native.
* has been completed.
*/
measureInWindow(callback) {
UIManager.measureInWindow(findNodeHandle(this), callback);
@@ -60,9 +74,50 @@ const NativeMethodsMixin = {
/**
* This function sends props straight to the underlying DOM node.
* This works as if all styles were set as inline styles. Since a DOM node
* may aleady be styled with class names and inline styles, we need to get
* the initial styles from the DOM node and merge them with incoming props.
*/
setNativeProps(nativeProps: Object) {
UIManager.updateView(findNodeHandle(this), nativeProps, this);
// DOM state
const node = findNodeHandle(this);
const domClassList = [ ...node.classList ];
// Resolved state
const resolvedProps = StyleRegistry.resolve(nativeProps.style) || emptyObject;
const resolvedClassList = classNameToList(resolvedProps.className);
// Merged state
const classList = [];
const style = { ...resolvedProps.style };
// The node has class names that we need to override.
// Only pass on a class name when the style is unchanged.
domClassList.forEach((c) => {
const prop = getStyleProp(c);
const className = resolvedProps.className;
if (!className || className.indexOf(prop) === -1) {
classList.push(c);
}
});
// The node has styles that we need to override.
// Remove any inline style that may collide with a new class name.
resolvedClassList.forEach((c) => {
const prop = getStyleProp(c);
classList.push(c);
style[prop] = null;
});
const className = `\n${classList.sort().join('\n')}`;
const props = {
...nativeProps,
className,
style
};
UIManager.updateView(node, props, this);
}
};

View File

@@ -33,7 +33,7 @@ const applyLayout = (Component) => {
if (layout.x !== x || layout.y !== y || layout.width !== width || layout.height !== height) {
const nextLayout = { x, y, width, height };
const nativeEvent = { layout: nextLayout };
onLayout({ nativeEvent });
onLayout({ nativeEvent, timeStamp: Date.now() });
this._layoutState = nextLayout;
}
});

View File

@@ -25,6 +25,7 @@ const createDOMElement = (component, rnProps = emptyObject) => {
accessibilityLiveRegion,
accessibilityRole,
accessible = true,
style: rnStyle, // we need to remove the RN styles from 'domProps'
testID,
type,
...domProps
@@ -33,7 +34,7 @@ const createDOMElement = (component, rnProps = emptyObject) => {
const accessibilityComponent = accessibilityRole && roleComponents[accessibilityRole];
const Component = accessibilityComponent || component;
const { className, style } = StyleRegistry.resolve(domProps.style) || emptyObject;
const { className, style } = StyleRegistry.resolve(rnStyle) || emptyObject;
if (!accessible) { domProps['aria-hidden'] = true; }
if (accessibilityLabel) { domProps['aria-label'] = accessibilityLabel; }
@@ -53,7 +54,9 @@ const createDOMElement = (component, rnProps = emptyObject) => {
if (style) {
domProps.style = style;
}
if (type) { domProps.type = type; }
if (type) {
domProps.type = type;
}
return (
<Component {...domProps} />

View File

@@ -1,2 +1,2 @@
import findNodeHandle from 'react-dom/lib/findDOMNode';
export default findNodeHandle;
import { findDOMNode } from 'react-dom';
export default findDOMNode;

View File

@@ -1,353 +0,0 @@
/* eslint-disable */
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule normalizeColor
* @flow
*/
/* eslint no-bitwise: 0 */
'use strict';
function normalizeColor(color: string | number): ?number {
var match;
if (typeof color === 'number') {
if (color >>> 0 === color && color >= 0 && color <= 0xffffffff) {
return color;
}
return null;
}
// Ordered based on occurrences on Facebook codebase
if ((match = matchers.hex6.exec(color))) {
return parseInt(match[1] + 'ff', 16) >>> 0;
}
if (names.hasOwnProperty(color)) {
return names[color];
}
if ((match = matchers.rgb.exec(color))) {
return (
parse255(match[1]) << 24 | // r
parse255(match[2]) << 16 | // g
parse255(match[3]) << 8 | // b
0x000000ff // a
) >>> 0;
}
if ((match = matchers.rgba.exec(color))) {
return (
parse255(match[1]) << 24 | // r
parse255(match[2]) << 16 | // g
parse255(match[3]) << 8 | // b
parse1(match[4]) // a
) >>> 0;
}
if ((match = matchers.hex3.exec(color))) {
return parseInt(
match[1] + match[1] + // r
match[2] + match[2] + // g
match[3] + match[3] + // b
'ff', // a
16
) >>> 0;
}
// https://drafts.csswg.org/css-color-4/#hex-notation
if ((match = matchers.hex8.exec(color))) {
return parseInt(match[1], 16) >>> 0;
}
if ((match = matchers.hex4.exec(color))) {
return parseInt(
match[1] + match[1] + // r
match[2] + match[2] + // g
match[3] + match[3] + // b
match[4] + match[4], // a
16
) >>> 0;
}
if ((match = matchers.hsl.exec(color))) {
return (
hslToRgb(
parse360(match[1]), // h
parsePercentage(match[2]), // s
parsePercentage(match[3]) // l
) |
0x000000ff // a
) >>> 0;
}
if ((match = matchers.hsla.exec(color))) {
return (
hslToRgb(
parse360(match[1]), // h
parsePercentage(match[2]), // s
parsePercentage(match[3]) // l
) |
parse1(match[4]) // a
) >>> 0;
}
return null;
}
function hue2rgb(p: number, q: number, t: number): number {
if (t < 0) {
t += 1;
}
if (t > 1) {
t -= 1;
}
if (t < 1 / 6) {
return p + (q - p) * 6 * t;
}
if (t < 1 / 2) {
return q;
}
if (t < 2 / 3) {
return p + (q - p) * (2 / 3 - t) * 6;
}
return p;
}
function hslToRgb(h: number, s: number, l: number): number {
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
var r = hue2rgb(p, q, h + 1 / 3);
var g = hue2rgb(p, q, h);
var b = hue2rgb(p, q, h - 1 / 3);
return (
Math.round(r * 255) << 24 |
Math.round(g * 255) << 16 |
Math.round(b * 255) << 8
);
}
// var INTEGER = '[-+]?\\d+';
var NUMBER = '[-+]?\\d*\\.?\\d+';
var PERCENTAGE = NUMBER + '%';
function call(...args) {
return '\\(\\s*(' + args.join(')\\s*,\\s*(') + ')\\s*\\)';
}
var matchers = {
rgb: new RegExp('rgb' + call(NUMBER, NUMBER, NUMBER)),
rgba: new RegExp('rgba' + call(NUMBER, NUMBER, NUMBER, NUMBER)),
hsl: new RegExp('hsl' + call(NUMBER, PERCENTAGE, PERCENTAGE)),
hsla: new RegExp('hsla' + call(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER)),
hex3: /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
hex4: /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
hex6: /^#([0-9a-fA-F]{6})$/,
hex8: /^#([0-9a-fA-F]{8})$/,
};
function parse255(str: string): number {
var int = parseInt(str, 10);
if (int < 0) {
return 0;
}
if (int > 255) {
return 255;
}
return int;
}
function parse360(str: string): number {
var int = parseFloat(str);
return (((int % 360) + 360) % 360) / 360;
}
function parse1(str: string): number {
var num = parseFloat(str);
if (num < 0) {
return 0;
}
if (num > 1) {
return 255;
}
return Math.round(num * 255);
}
function parsePercentage(str: string): number {
// parseFloat conveniently ignores the final %
var int = parseFloat(str, 10);
if (int < 0) {
return 0;
}
if (int > 100) {
return 1;
}
return int / 100;
}
var names = {
/* @edit start */
currentcolor: 'currentcolor',
inherit: 'inherit',
/* @edit end */
transparent: 0x00000000,
// http://www.w3.org/TR/css3-color/#svg-color
aliceblue: 0xf0f8ffff,
antiquewhite: 0xfaebd7ff,
aqua: 0x00ffffff,
aquamarine: 0x7fffd4ff,
azure: 0xf0ffffff,
beige: 0xf5f5dcff,
bisque: 0xffe4c4ff,
black: 0x000000ff,
blanchedalmond: 0xffebcdff,
blue: 0x0000ffff,
blueviolet: 0x8a2be2ff,
brown: 0xa52a2aff,
burlywood: 0xdeb887ff,
burntsienna: 0xea7e5dff,
cadetblue: 0x5f9ea0ff,
chartreuse: 0x7fff00ff,
chocolate: 0xd2691eff,
coral: 0xff7f50ff,
cornflowerblue: 0x6495edff,
cornsilk: 0xfff8dcff,
crimson: 0xdc143cff,
cyan: 0x00ffffff,
darkblue: 0x00008bff,
darkcyan: 0x008b8bff,
darkgoldenrod: 0xb8860bff,
darkgray: 0xa9a9a9ff,
darkgreen: 0x006400ff,
darkgrey: 0xa9a9a9ff,
darkkhaki: 0xbdb76bff,
darkmagenta: 0x8b008bff,
darkolivegreen: 0x556b2fff,
darkorange: 0xff8c00ff,
darkorchid: 0x9932ccff,
darkred: 0x8b0000ff,
darksalmon: 0xe9967aff,
darkseagreen: 0x8fbc8fff,
darkslateblue: 0x483d8bff,
darkslategray: 0x2f4f4fff,
darkslategrey: 0x2f4f4fff,
darkturquoise: 0x00ced1ff,
darkviolet: 0x9400d3ff,
deeppink: 0xff1493ff,
deepskyblue: 0x00bfffff,
dimgray: 0x696969ff,
dimgrey: 0x696969ff,
dodgerblue: 0x1e90ffff,
firebrick: 0xb22222ff,
floralwhite: 0xfffaf0ff,
forestgreen: 0x228b22ff,
fuchsia: 0xff00ffff,
gainsboro: 0xdcdcdcff,
ghostwhite: 0xf8f8ffff,
gold: 0xffd700ff,
goldenrod: 0xdaa520ff,
gray: 0x808080ff,
green: 0x008000ff,
greenyellow: 0xadff2fff,
grey: 0x808080ff,
honeydew: 0xf0fff0ff,
hotpink: 0xff69b4ff,
indianred: 0xcd5c5cff,
indigo: 0x4b0082ff,
ivory: 0xfffff0ff,
khaki: 0xf0e68cff,
lavender: 0xe6e6faff,
lavenderblush: 0xfff0f5ff,
lawngreen: 0x7cfc00ff,
lemonchiffon: 0xfffacdff,
lightblue: 0xadd8e6ff,
lightcoral: 0xf08080ff,
lightcyan: 0xe0ffffff,
lightgoldenrodyellow: 0xfafad2ff,
lightgray: 0xd3d3d3ff,
lightgreen: 0x90ee90ff,
lightgrey: 0xd3d3d3ff,
lightpink: 0xffb6c1ff,
lightsalmon: 0xffa07aff,
lightseagreen: 0x20b2aaff,
lightskyblue: 0x87cefaff,
lightslategray: 0x778899ff,
lightslategrey: 0x778899ff,
lightsteelblue: 0xb0c4deff,
lightyellow: 0xffffe0ff,
lime: 0x00ff00ff,
limegreen: 0x32cd32ff,
linen: 0xfaf0e6ff,
magenta: 0xff00ffff,
maroon: 0x800000ff,
mediumaquamarine: 0x66cdaaff,
mediumblue: 0x0000cdff,
mediumorchid: 0xba55d3ff,
mediumpurple: 0x9370dbff,
mediumseagreen: 0x3cb371ff,
mediumslateblue: 0x7b68eeff,
mediumspringgreen: 0x00fa9aff,
mediumturquoise: 0x48d1ccff,
mediumvioletred: 0xc71585ff,
midnightblue: 0x191970ff,
mintcream: 0xf5fffaff,
mistyrose: 0xffe4e1ff,
moccasin: 0xffe4b5ff,
navajowhite: 0xffdeadff,
navy: 0x000080ff,
oldlace: 0xfdf5e6ff,
olive: 0x808000ff,
olivedrab: 0x6b8e23ff,
orange: 0xffa500ff,
orangered: 0xff4500ff,
orchid: 0xda70d6ff,
palegoldenrod: 0xeee8aaff,
palegreen: 0x98fb98ff,
paleturquoise: 0xafeeeeff,
palevioletred: 0xdb7093ff,
papayawhip: 0xffefd5ff,
peachpuff: 0xffdab9ff,
peru: 0xcd853fff,
pink: 0xffc0cbff,
plum: 0xdda0ddff,
powderblue: 0xb0e0e6ff,
purple: 0x800080ff,
rebeccapurple: 0x663399ff,
red: 0xff0000ff,
rosybrown: 0xbc8f8fff,
royalblue: 0x4169e1ff,
saddlebrown: 0x8b4513ff,
salmon: 0xfa8072ff,
sandybrown: 0xf4a460ff,
seagreen: 0x2e8b57ff,
seashell: 0xfff5eeff,
sienna: 0xa0522dff,
silver: 0xc0c0c0ff,
skyblue: 0x87ceebff,
slateblue: 0x6a5acdff,
slategray: 0x708090ff,
slategrey: 0x708090ff,
snow: 0xfffafaff,
springgreen: 0x00ff7fff,
steelblue: 0x4682b4ff,
tan: 0xd2b48cff,
teal: 0x008080ff,
thistle: 0xd8bfd8ff,
tomato: 0xff6347ff,
turquoise: 0x40e0d0ff,
violet: 0xee82eeff,
wheat: 0xf5deb3ff,
white: 0xffffffff,
whitesmoke: 0xf5f5f5ff,
yellow: 0xffff00ff,
yellowgreen: 0x9acd32ff,
};
module.exports = normalizeColor;

View File

@@ -2,7 +2,7 @@ import { PropTypes } from 'react';
const { number, oneOf, oneOfType, string } = PropTypes;
const AnimationPropTypes = process.env.NODE_ENV !== 'production' ? {
const AnimationPropTypes = {
animationDelay: string,
animationDirection: oneOf([ 'alternate', 'alternate-reverse', 'normal', 'reverse' ]),
animationDuration: string,
@@ -11,6 +11,6 @@ const AnimationPropTypes = process.env.NODE_ENV !== 'production' ? {
animationName: string,
animationPlayState: oneOf([ 'paused', 'running' ]),
animationTimingFunction: string
} : {};
};
module.exports = AnimationPropTypes;

View File

@@ -1,13 +1,13 @@
import { PropTypes } from 'react';
const { array, bool, number, object, oneOf, oneOfType, string } = PropTypes;
const BaseComponentPropTypes = process.env.NODE_ENV !== 'production' ? {
const BaseComponentPropTypes = {
accessibilityLabel: string,
accessibilityLiveRegion: oneOf([ 'assertive', 'off', 'polite' ]),
accessibilityRole: string,
accessible: bool,
style: oneOfType([ array, number, object ]),
testID: string
} : {};
};
module.exports = BaseComponentPropTypes;

View File

@@ -4,7 +4,7 @@ import { PropTypes } from 'react';
const numberOrString = PropTypes.oneOfType([ PropTypes.number, PropTypes.string ]);
const BorderStylePropType = PropTypes.oneOf([ 'solid', 'dotted', 'dashed' ]);
const BorderPropTypes = process.env.NODE_ENV !== 'production' ? {
const BorderPropTypes = {
borderColor: ColorPropType,
borderTopColor: ColorPropType,
borderRightColor: ColorPropType,
@@ -29,6 +29,6 @@ const BorderPropTypes = process.env.NODE_ENV !== 'production' ? {
borderBottomRightRadius$noI18n: numberOrString,
borderLeftStyle$noI18n: BorderStylePropType,
borderRightStyle$noI18n: BorderStylePropType
} : {};
};
module.exports = BorderPropTypes;

View File

@@ -13,7 +13,7 @@
import { PropTypes } from 'react'
var colorPropType = function(isRequired, props, propName, componentName, location, propFullName) {
var normalizeColor = require('../modules/normalizeColor');
var normalizeColor = require('normalize-css-color');
var ReactPropTypeLocationNames = require('react-dom/lib/ReactPropTypeLocationNames');
var color = props[propName];
if (color === undefined || color === null) {
@@ -34,6 +34,10 @@ var colorPropType = function(isRequired, props, propName, componentName, locatio
return;
}
if (color === 'currentcolor' || color === 'inherit') {
return;
}
if (normalizeColor(color) === null) {
var locationName = ReactPropTypeLocationNames[location];
return new Error(

View File

@@ -14,11 +14,11 @@
var PropTypes = require('react').PropTypes;
var EdgeInsetsPropType = process.env.NODE_ENV !== 'production' ? require('./createStrictShapeTypeChecker')({
var EdgeInsetsPropType = require('./createStrictShapeTypeChecker')({
top: PropTypes.number,
left: PropTypes.number,
bottom: PropTypes.number,
right: PropTypes.number,
}) : function () {};
});
module.exports = EdgeInsetsPropType;

View File

@@ -3,7 +3,7 @@ import { PropTypes } from 'react';
const { number, oneOf, oneOfType, string } = PropTypes;
const numberOrString = oneOfType([ number, string ]);
const LayoutPropTypes = process.env.NODE_ENV !== 'production' ? {
const LayoutPropTypes = {
// box model
borderWidth: numberOrString,
borderBottomWidth: numberOrString,
@@ -58,6 +58,6 @@ const LayoutPropTypes = process.env.NODE_ENV !== 'production' ? {
paddingLeft$noI18n: numberOrString,
paddingRight$noI18n: numberOrString,
right$noI18n: numberOrString
} : {};
};
module.exports = LayoutPropTypes;

View File

@@ -14,9 +14,9 @@
var PropTypes = require('react').PropTypes;
var PointPropType = process.env.NODE_ENV !== 'production' ? require('./createStrictShapeTypeChecker')({
var PointPropType = require('./createStrictShapeTypeChecker')({
x: PropTypes.number,
y: PropTypes.number,
}) : function () {};
});
module.exports = PointPropType;

View File

@@ -5,7 +5,7 @@
* @flow
*/
module.exports = process.env.NODE_ENV !== 'production' ? function StyleSheetPropType(shape) {
module.exports = function StyleSheetPropType(shape) {
const createStrictShapeTypeChecker = require('./createStrictShapeTypeChecker');
const StyleSheet = require('../apis/StyleSheet');
@@ -19,4 +19,4 @@ module.exports = process.env.NODE_ENV !== 'production' ? function StyleSheetProp
}
return shapePropType(newProps, propName, componentName, location);
};
} : function () {};
};

View File

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

View File

@@ -10,7 +10,7 @@ import { PropTypes } from 'react';
const { arrayOf, number, oneOfType, shape, string } = PropTypes;
const numberOrString = oneOfType([ number, string ]);
const TransformPropTypes = process.env.NODE_ENV !== 'production' ? {
const TransformPropTypes = {
transform: arrayOf(
oneOfType([
shape({ perspective: numberOrString }),
@@ -28,7 +28,8 @@ const TransformPropTypes = process.env.NODE_ENV !== 'production' ? {
shape({ translateZ: numberOrString }),
shape({ translate3d: string })
])
)
} : {};
),
transformOrigin: string
};
module.exports = TransformPropTypes;

View File

@@ -2,12 +2,11 @@ const path = require('path')
const webpack = require('webpack')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const SRC_DIRECTORY = './src'
const DIST_DIRECTORY = './dist'
module.exports = {
entry: {
main: DIST_DIRECTORY
},
entry: SRC_DIRECTORY,
externals: [
{
react: {
@@ -18,6 +17,21 @@ module.exports = {
}
}
],
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: { cacheDirectory: true }
},
{
test: /\.(gif|jpe?g|png|svg)$/,
loader: 'url-loader',
query: { name: '[name].[ext]' }
}
]
},
output: {
filename: 'ReactNative.js',
library: 'ReactNative',

View File

@@ -895,9 +895,9 @@ babel-plugin-transform-react-jsx@^6.3.13, babel-plugin-transform-react-jsx@^6.5.
babel-plugin-syntax-jsx "^6.8.0"
babel-runtime "^6.0.0"
babel-plugin-transform-react-remove-prop-types:
version "0.2.11"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.2.11.tgz#05eb7cc4670d6506d801680576589c7abcd51b00"
babel-plugin-transform-react-remove-prop-types@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.3.0.tgz#88baefdb530c95c37c6e685f591e263db9fe5585"
babel-plugin-transform-regenerator@6.16.1, babel-plugin-transform-regenerator@^6.16.0, babel-plugin-transform-regenerator@^6.5.0, babel-plugin-transform-regenerator@^6.6.0:
version "6.16.1"
@@ -1923,6 +1923,10 @@ duplexer2@^0.1.4:
dependencies:
readable-stream "^2.0.2"
duplexer@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
ecc-jsbn@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
@@ -1933,9 +1937,9 @@ ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
ejs@^2.5.2:
version "2.5.2"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.2.tgz#21444ba09386f0c65b6eafb96a3d51bcb3be80d1"
ejs@^2.5.5:
version "2.5.5"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.5.tgz#6ef4e954ea7dcf54f66aad2fe7aa421932d9ed77"
element-class@^0.2.0:
version "0.2.2"
@@ -2299,18 +2303,7 @@ fb-watchman@^1.8.0, fb-watchman@^1.9.0:
dependencies:
bser "^1.0.2"
fbjs@^0.8.1, fbjs@^0.8.4:
version "0.8.6"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.6.tgz#7eb67d6986b2d5007a9b6e92e0e7cb6f75cad290"
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
ua-parser-js "^0.7.9"
fbjs@^0.8.8:
fbjs@^0.8.1, fbjs@^0.8.4, fbjs@^0.8.8:
version "0.8.8"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.8.tgz#02f1b6e0ea0d46c24e0b51a2d24df069563a5ad6"
dependencies:
@@ -2621,6 +2614,12 @@ growly@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
gzip-size@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-3.0.0.tgz#546188e9bdc337f673772f81660464b389dce520"
dependencies:
duplexer "^0.1.1"
handlebars@^4.0.1, handlebars@^4.0.3:
version "4.0.6"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.6.tgz#2ce4484850537f9c97a8026d5399b935c4ed4ed7"
@@ -3689,7 +3688,7 @@ lodash.words@^3.0.0:
dependencies:
lodash._root "^3.0.0"
lodash@4.x.x, lodash@^4.0.0, lodash@^4.16.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.6.1:
lodash@4.x.x, lodash@^4.0.0, lodash@^4.16.4, lodash@^4.17.2, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.6.1:
version "4.17.2"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.2.tgz#34a3055babe04ce42467b607d700072c7ff6bf42"
@@ -4029,9 +4028,9 @@ nopt@3.x, nopt@~3.0.6:
dependencies:
abbrev "1"
normalize-css-color@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/normalize-css-color/-/normalize-css-color-1.0.1.tgz#792f59cae25036950a9127cfcfddc073048f4f9d"
normalize-css-color@^1.0.1, normalize-css-color@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/normalize-css-color/-/normalize-css-color-1.0.2.tgz#02991e97cccec6623fe573afbbf0de6a1f3e9f8d"
normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
version "2.3.5"
@@ -5698,17 +5697,18 @@ webidl-conversions@^3.0.0, webidl-conversions@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
webpack-bundle-analyzer:
version "1.5.3"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-1.5.3.tgz#d1109bdd0a0067bba88ea6aa642533b4de926965"
webpack-bundle-analyzer@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.2.1.tgz#a90edc00eb9cea917d2af009529decf71d7f4a84"
dependencies:
acorn "^4.0.3"
chalk "^1.1.3"
commander "^2.9.0"
ejs "^2.5.2"
ejs "^2.5.5"
express "^4.14.0"
filesize "^3.3.0"
lodash "^4.16.4"
gzip-size "^3.0.0"
lodash "^4.17.2"
mkdirp "^0.5.1"
opener "^1.4.2"