Compare commits

..

11 Commits

Author SHA1 Message Date
Nicolas Gallagher
f5f9389728 0.0.53 2016-11-22 17:46:57 -08:00
Nicolas Gallagher
fdbd19a4af [fix] PropTypes production error
See: https://github.com/oliviertassinari/babel-plugin-transform-react-remove-prop-types/issues/68
2016-11-22 17:44:48 -08:00
Nicolas Gallagher
36eafbc2f5 0.0.52 2016-11-22 17:10:14 -08:00
Nicolas Gallagher
bca3398c1c Correct devDependencies 2016-11-22 17:08:04 -08:00
Nicolas Gallagher
722d77e8e5 Smaller production builds
Builds on the exclusion of PropTypes from production builds:

- Remove 'lodash' and use smaller modules for equivalent functions.
- Remove use of some unnecessary Facebook utilities.
- Remove 'TouchableBounce'; it isn't part of React Native anymore.
- Remove stray import of 'react-dom/server'.
- Exclude 'StyleSheetValidation' from production.

Measuring the UMD build (gzip)…

Before: ~100KB
After: ~60KB
2016-11-22 16:59:20 -08:00
Nicolas Gallagher
d65c92eea9 [change] prepare for react-dom@15.4.0
Don't depend directly on the 'react-dom' module as it will be prebuilt
in 15.4. Leave server-side rendering to 'react-dom/server'.
2016-11-22 16:57:28 -08:00
Nicolas Gallagher
8dd39c681c [change] allow propTypes to be removed in production builds
Fix #254
2016-11-22 16:57:22 -08:00
Nicolas Gallagher
0b1759363d [add] promote ScrollView content to new layer 2016-11-22 13:08:11 -08:00
Nicolas Gallagher
abd1227a94 [change] ScrollView props and event handling
- Update 'scrollEventThrottle' prop
- Filter non-DOM props
- Persist debounced scroll events.

Fix #209
2016-11-21 21:39:08 -08:00
Nicolas Gallagher
8352c7cbda Use yarn for dependency management 2016-11-21 17:10:50 -08:00
Nicolas Gallagher
89f5a13891 [change] TextInput uses DOM elements
This patch changes TextInput to use DOM inputs directly, rather than
trying to reimplement 'placeholder'. Removes support for
'placeholderTextColor'.

Fix #54
Fix #224
Fix #229
Fix #235
Fix #253
2016-11-21 16:52:40 -08:00
50 changed files with 6153 additions and 728 deletions

View File

@@ -1,5 +1,8 @@
{
"presets": [
"react-native"
],
"plugins": [
[ "transform-react-remove-prop-types", { "mode": "wrap" } ]
]
}

View File

@@ -19,6 +19,12 @@ Fork, then clone the repo:
git clone https://github.com/your-username/react-native-web.git
```
Install dependencies (requires [yarn](https://yarnpkg.com/en/docs/install):
```
yarn
```
Run the examples:
```

View File

@@ -13,14 +13,11 @@ into `runApplication`. These should always be used as a pair.
## Methods
(web) static **prerenderApplication**(appKey:string, appParameters: object)
(web) static **getApplication**(appKey:string, appParameters: object)
Renders the given application to an HTML string. Use this for server-side
rendering. Return object is of type `{ html: string; style: string;
styleElement: ReactComponent }`. `html` is the prerendered HTML, `style` is the
prerendered style sheet, and `styleElement` is a React Component. It's
recommended that you use `styleElement` to render the style sheet in an app
shell.
Returns the given application element. Use this for server-side rendering.
Return object is of type `{ element: ReactElement; stylesheet: ReactElement }`.
It's recommended that you use `sheetsheet` to render the style sheet in an app
static **registerConfig**(config: Array<AppConfig>)

View File

@@ -6,12 +6,10 @@ such as auto-complete, auto-focus, placeholder text, and event callbacks.
Note: some props are exclusive to or excluded from `multiline`.
Unsupported React Native props:
`autoCapitalize`,
`autoCorrect`,
`onEndEditing`,
`onSubmitEditing`,
`clearButtonMode` (ios),
`enablesReturnKeyAutomatically` (ios),
`placeholderTextColor`,
`returnKeyType` (ios),
`selectionState` (ios),
`underlineColorAndroid` (android)
@@ -128,10 +126,6 @@ Callback that is called when the keyboard's submit button is pressed.
The string that will be rendered in an empty `TextInput` before text has been
entered.
**placeholderTextColor**: string
The text color of the placeholder string.
**secureTextEntry**: bool = false
If true, the text input obscures the text entered so that sensitive text like

View File

@@ -43,12 +43,7 @@ import ReactNative from 'react-native'
// component that renders the app
const AppHeaderContainer = (props) => { /* ... */ }
// DOM render
ReactNative.render(<AppHeaderContainer />, document.getElementById('react-app-header'))
// Server render
ReactNative.renderToString(<AppHeaderContainer />)
ReactNative.renderToStaticMarkup(<AppHeaderContainer />)
```
Rendering using the `AppRegistry`:
@@ -63,7 +58,6 @@ const AppContainer = (props) => { /* ... */ }
// register the app
AppRegistry.registerComponent('App', () => AppContainer)
// DOM render
AppRegistry.runApplication('App', {
initialProps: {},
rootTag: document.getElementById('react-app')
@@ -72,3 +66,22 @@ AppRegistry.runApplication('App', {
// prerender the app
const { html, styleElement } = AppRegistry.prerenderApplication('App', { initialProps })
```
## Server-side rendering
Rendering using the `AppRegistry`:
```
import ReactDOMServer from 'react-dom/server'
import ReactNative, { AppRegistry } from 'react-native'
// component that renders the app
const AppContainer = (props) => { /* ... */ }
// register the app
AppRegistry.registerComponent('App', () => AppContainer)
// prerender the app
const { element, stylesheet } = AppRegistry.getApplication('App', { initialProps });
const initialHTML = ReactDOMServer.renderToString(element);
```

View File

@@ -7,8 +7,8 @@ storiesOf('component: ScrollView', module)
<View style={styles.scrollViewContainer}>
<ScrollView
contentContainerStyle={styles.scrollViewContentContainerStyle}
onScroll={e => console.log('ScrollView.onScroll', e)}
scrollEventThrottle={1} // 1 event per second
onScroll={e => { console.log('ScrollView.onScroll', e); } }
scrollEventThrottle={1000} // 1 event per second
style={styles.scrollViewStyle}
>
{Array.from({ length: 50 }).map((item, i) => (

View File

@@ -210,25 +210,16 @@ class TokenizedTextExample extends React.Component {
}
parts.push(_text);
//highlight hashtags
parts = parts.map((text) => {
if (/^#/.test(text)) {
return <Text key={text} style={styles.hashtag}>{text}</Text>;
} else {
return text;
}
});
return (
<View>
<TextInput
value={parts.join('')}
multiline={true}
style={styles.multiline}
onChangeText={(text) => {
this.setState({text});
}}>
<Text>{parts}</Text>
</TextInput>
}}
/>
</View>
);
}
@@ -279,7 +270,7 @@ class BlurOnSubmitExample extends React.Component {
<TextInput
ref="5"
style={styles.default}
keyboardType="numbers-and-punctuation"
keyboardType="numeric"
placeholder="blurOnSubmit = true"
returnKeyType="done"
/>
@@ -519,15 +510,15 @@ const examples = [
render: function() {
var keyboardTypes = [
'default',
'ascii-capable',
'numbers-and-punctuation',
//'ascii-capable',
//'numbers-and-punctuation',
'url',
'number-pad',
'phone-pad',
'name-phone-pad',
//'name-phone-pad',
'email-address',
'decimal-pad',
'twitter',
//'decimal-pad',
//'twitter',
'web-search',
'numeric',
];
@@ -776,14 +767,6 @@ const examples = [
style={styles.multiline}
dataDetectorTypes="phoneNumber"
/>
<TextInput
placeholder="multiline with children"
multiline={true}
enablesReturnKeyAutomatically={true}
returnKeyType="go"
style={styles.multiline}>
<View style={styles.multilineChild}/>
</TextInput>
</View>
);
}

View File

@@ -23,7 +23,7 @@ var {
AppRegistry,
StyleSheet,
Text,
TouchableBounce,
TouchableOpacity,
View,
} = ReactNative;
@@ -139,9 +139,9 @@ class GameEndOverlay extends React.Component {
return (
<View style={styles.overlay}>
<Text style={styles.overlayMessage}>{message}</Text>
<TouchableBounce onPress={this.props.onRestart} style={styles.tryAgain}>
<TouchableOpacity onPress={this.props.onRestart} style={styles.tryAgain}>
<Text style={styles.tryAgainText}>Try Again?</Text>
</TouchableBounce>
</TouchableOpacity>
</View>
);
}

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-web",
"version": "0.0.51",
"version": "0.0.53",
"description": "React Native for Web",
"main": "dist/index.js",
"files": [
@@ -19,10 +19,12 @@
},
"dependencies": {
"animated": "^0.1.3",
"array-find-index": "^1.0.2",
"babel-runtime": "^6.11.6",
"debounce": "^1.0.0",
"deep-assign": "^2.0.0",
"fbjs": "^0.8.4",
"inline-style-prefixer": "^2.0.1",
"lodash": "^4.15.0",
"react-dom": "~15.3.2",
"react-textarea-autosize": "^4.0.4",
"react-timer-mixin": "^0.13.3"
@@ -33,6 +35,7 @@
"babel-core": "^6.14.0",
"babel-eslint": "^6.1.2",
"babel-loader": "^6.2.5",
"babel-plugin-transform-react-remove-prop-types": "^0.2.11",
"babel-preset-react-native": "^1.9.0",
"del-cli": "^0.2.0",
"enzyme": "^2.4.1",
@@ -47,7 +50,8 @@
"react-addons-test-utils": "~15.3.2",
"react-test-renderer": "~15.3.2",
"url-loader": "^0.5.7",
"webpack": "^1.13.2"
"webpack": "^1.13.2",
"webpack-bundle-analyzer": "^1.5.3"
},
"peerDependencies": {
"react": "~15.3.2"

View File

@@ -1,15 +1,15 @@
/* eslint-env jasmine, jest */
import { prerenderApplication } from '../renderApplication';
import { getApplication } from '../renderApplication';
import React from 'react';
const component = () => <div />;
describe('apis/AppRegistry/renderApplication', () => {
test('prerenderApplication', () => {
const { html, styleElement } = prerenderApplication(component, {});
test('getApplication', () => {
const { element, stylesheet } = getApplication(component, {});
expect(html.indexOf('<div ') > -1).toBeTruthy();
expect(styleElement.type).toEqual('style');
expect(element).toBeTruthy();
expect(stylesheet.type).toEqual('style');
});
});

View File

@@ -8,8 +8,8 @@
import { Component } from 'react';
import invariant from 'fbjs/lib/invariant';
import ReactDOM from 'react-dom';
import renderApplication, { prerenderApplication } from './renderApplication';
import { unmountComponentAtNode } from 'react/lib/ReactMount';
import renderApplication, { getApplication } from './renderApplication';
const runnables = {};
@@ -29,20 +29,20 @@ class AppRegistry {
return Object.keys(runnables);
}
static prerenderApplication(appKey: string, appParameters?: Object): string {
static getApplication(appKey: string, appParameters?: Object): string {
invariant(
runnables[appKey] && runnables[appKey].prerender,
runnables[appKey] && runnables[appKey].getApplication,
`Application ${appKey} has not been registered. ` +
'This is either due to an import error during initialization or failure to call AppRegistry.registerComponent.'
);
return runnables[appKey].prerender(appParameters);
return runnables[appKey].getApplication(appParameters);
}
static registerComponent(appKey: string, getComponentFunc: ComponentProvider): string {
runnables[appKey] = {
run: ({ initialProps, rootTag }) => renderApplication(getComponentFunc(), initialProps, rootTag),
prerender: ({ initialProps } = {}) => prerenderApplication(getComponentFunc(), initialProps)
getApplication: ({ initialProps } = {}) => getApplication(getComponentFunc(), initialProps),
run: ({ initialProps, rootTag }) => renderApplication(getComponentFunc(), initialProps, rootTag)
};
return appKey;
}
@@ -85,7 +85,7 @@ class AppRegistry {
}
static unmountApplicationComponentAtRootTag(rootTag) {
ReactDOM.unmountComponentAtNode(rootTag);
unmountComponentAtNode(rootTag);
}
}

View File

@@ -7,8 +7,7 @@
*/
import invariant from 'fbjs/lib/invariant';
import ReactDOM from 'react-dom';
import ReactDOMServer from 'react-dom/server';
import { render } from 'react/lib/ReactMount';
import ReactNativeApp from './ReactNativeApp';
import StyleSheet from '../../apis/StyleSheet';
import React, { Component } from 'react';
@@ -23,17 +22,16 @@ export default function renderApplication(RootComponent: Component, initialProps
rootTag={rootTag}
/>
);
ReactDOM.render(component, rootTag);
render(component, rootTag);
}
export function prerenderApplication(RootComponent: Component, initialProps: Object): string {
const component = (
export function getApplication(RootComponent: Component, initialProps: Object): Object {
const element = (
<ReactNativeApp
initialProps={initialProps}
rootComponent={RootComponent}
/>
);
const html = ReactDOMServer.renderToString(component);
const styleElement = StyleSheet.render();
return { html, styleElement };
const stylesheet = StyleSheet.render();
return { element, stylesheet };
}

View File

@@ -1,5 +1,5 @@
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import findIndex from 'lodash/findIndex';
import findIndex from 'array-find-index';
import invariant from 'fbjs/lib/invariant';
const EVENT_TYPES = [ 'change' ];

View File

@@ -3,7 +3,7 @@
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*/
import merge from 'lodash/merge';
import merge from 'deep-assign';
const mergeLocalStorageItem = (key, value) => {
const oldValue = window.localStorage.getItem(key);

View File

@@ -6,7 +6,7 @@
* @flow
*/
import debounce from 'lodash/debounce';
import debounce from 'debounce';
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import invariant from 'fbjs/lib/invariant';

View File

@@ -6,13 +6,12 @@
*/
import invariant from 'fbjs/lib/invariant';
import keyMirror from 'fbjs/lib/keyMirror';
const InteractionManager = {
Events: keyMirror({
interactionStart: true,
interactionComplete: true
}),
Events: {
interactionStart: 'interactionStart',
interactionComplete: 'interactionComplete'
},
/**
* Schedule a function to run after all interactions have completed.

View File

@@ -7,7 +7,7 @@
*/
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import findIndex from 'lodash/findIndex';
import findIndex from 'array-find-index';
import invariant from 'fbjs/lib/invariant';
const connection = ExecutionEnvironment.canUseDOM && (

View File

@@ -1,9 +1,19 @@
/* eslint-env jasmine, jest */
import { getDefaultStyleSheet } from '../css';
import isPlainObject from 'lodash/isPlainObject';
import StyleSheet from '..';
const isPlainObject = (x) => {
const toString = Object.prototype.toString;
let proto;
/* eslint-disable */
return (
toString.call(x) === '[object Object]' &&
(proto = Object.getPrototypeOf(x), proto === null || proto === Object.getPrototypeOf({}))
);
/* eslint-enable */
};
describe('apis/StyleSheet', () => {
beforeEach(() => {
StyleSheet._reset();

View File

@@ -4,7 +4,6 @@ import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import flattenStyle from '../../modules/flattenStyle';
import React from 'react';
import ReactNativePropRegistry from '../../modules/ReactNativePropRegistry';
import StyleSheetValidation from './StyleSheetValidation';
let styleElement;
let shouldInsertStyleSheet = ExecutionEnvironment.canUseDOM;
@@ -52,7 +51,9 @@ module.exports = {
const result = {};
for (const key in styles) {
StyleSheetValidation.validateStyle(key, styles);
if (process.env.NODE_ENV !== 'production') {
require('./StyleSheetValidation').validateStyle(key, styles);
}
result[key] = ReactNativePropRegistry.register(styles[key]);
}
return result;

View File

@@ -7,7 +7,7 @@ import TransformPropTypes from '../../propTypes/TransformPropTypes';
const hiddenOrVisible = PropTypes.oneOf([ 'hidden', 'visible' ]);
module.exports = {
module.exports = process.env.NODE_ENV !== 'production' ? {
...BorderPropTypes,
...LayoutPropTypes,
...TransformPropTypes,
@@ -24,4 +24,4 @@ module.exports = {
* @platform web
*/
visibility: hiddenOrVisible
};
} : {};

View File

@@ -1,13 +1,10 @@
import applyNativeMethods from '../../modules/applyNativeMethods';
import ListViewDataSource from './ListViewDataSource';
import ListViewPropTypes from './ListViewPropTypes';
import pick from 'lodash/pick';
import ScrollView from '../ScrollView';
import View from '../View';
import React, { Component } from 'react';
const scrollViewProps = Object.keys(ScrollView.propTypes);
class ListView extends Component {
static propTypes = ListViewPropTypes;
@@ -90,9 +87,7 @@ class ListView extends Component {
}
}
const props = pick(this.props, scrollViewProps);
return React.cloneElement(this.props.renderScrollComponent(props), {
return React.cloneElement(this.props.renderScrollComponent(this.props), {
ref: this._setScrollViewRef
}, header, children, footer);
}

View File

@@ -6,7 +6,7 @@
* @flow
*/
import debounce from 'lodash/debounce';
import debounce from 'debounce';
import View from '../View';
import React, { Component, PropTypes } from 'react';
@@ -23,12 +23,16 @@ export default class ScrollViewBase extends Component {
onScrollEndDrag: PropTypes.func,
onTouchMove: PropTypes.func,
onWheel: PropTypes.func,
removeClippedSubviews: PropTypes.bool,
scrollEnabled: PropTypes.bool,
scrollEventThrottle: PropTypes.number
scrollEventThrottle: PropTypes.number,
showsHorizontalScrollIndicator: PropTypes.bool,
showsVerticalScrollIndicator: PropTypes.bool
};
static defaultProps = {
scrollEnabled: true
scrollEnabled: true,
scrollEventThrottle: 0
};
constructor(props) {
@@ -48,6 +52,7 @@ export default class ScrollViewBase extends Component {
}
_handleScroll = (e) => {
e.persist();
const { scrollEventThrottle } = this.props;
// A scroll happened, so the scroll bumps the debounce.
this._debouncedOnScrollEnd(e);
@@ -81,12 +86,22 @@ export default class ScrollViewBase extends Component {
_shouldEmitScrollEvent(lastTick, eventThrottle) {
const timeSinceLastTick = Date.now() - lastTick;
return (eventThrottle > 0 && timeSinceLastTick >= (1000 / eventThrottle));
return (eventThrottle > 0 && timeSinceLastTick >= eventThrottle);
}
render() {
const {
onMomentumScrollBegin, onMomentumScrollEnd, onScrollBeginDrag, onScrollEndDrag, scrollEnabled, scrollEventThrottle, // eslint-disable-line
/* eslint-disable */
onMomentumScrollBegin,
onMomentumScrollEnd,
onScrollBeginDrag,
onScrollEndDrag,
removeClippedSubviews,
scrollEnabled,
scrollEventThrottle,
showsHorizontalScrollIndicator,
showsVerticalScrollIndicator,
/* eslint-enable */
...other
} = this.props;

View File

@@ -7,8 +7,8 @@
*/
import dismissKeyboard from '../../modules/dismissKeyboard';
import findNodeHandle from '../../modules/findNodeHandle';
import invariant from 'fbjs/lib/invariant';
import ReactDOM from 'react-dom';
import ScrollResponder from '../../modules/ScrollResponder';
import ScrollViewBase from './ScrollViewBase';
import StyleSheet from '../../apis/StyleSheet';
@@ -21,12 +21,12 @@ import React, { Component, PropTypes } from 'react';
const ScrollView = React.createClass({
propTypes: {
...View.propTypes,
children: View.propTypes.children,
contentContainerStyle: StyleSheetPropType(ViewStylePropTypes),
horizontal: PropTypes.bool,
keyboardDismissMode: PropTypes.oneOf([ 'none', 'interactive', 'on-drag' ]),
onContentSizeChange: PropTypes.func,
onScroll: PropTypes.func,
pagingEnabled: PropTypes.bool,
refreshControl: PropTypes.element,
scrollEnabled: PropTypes.bool,
scrollEventThrottle: PropTypes.number,
@@ -54,11 +54,11 @@ const ScrollView = React.createClass({
},
getScrollableNode(): any {
return ReactDOM.findDOMNode(this._scrollViewRef);
return findNodeHandle(this._scrollViewRef);
},
getInnerViewNode(): any {
return ReactDOM.findDOMNode(this._innerViewRef);
return findNodeHandle(this._innerViewRef);
},
/**
@@ -97,10 +97,13 @@ const ScrollView = React.createClass({
const {
contentContainerStyle,
horizontal,
keyboardDismissMode, // eslint-disable-line
onContentSizeChange,
onScroll, // eslint-disable-line
refreshControl,
/* eslint-disable */
keyboardDismissMode,
onScroll,
pagingEnabled,
/* eslint-enable */
...other
} = this.props;
@@ -233,7 +236,8 @@ const styles = StyleSheet.create({
overflowY: 'hidden'
},
contentContainer: {
flexGrow: 1
flexGrow: 1,
transform: [ { translateZ: 0 } ]
},
contentContainerHorizontal: {
flexDirection: 'row'

View File

@@ -1,7 +1,7 @@
import TextPropTypes from '../../propTypes/TextPropTypes';
import ViewStylePropTypes from '../View/ViewStylePropTypes';
module.exports = {
module.exports = process.env.NODE_ENV !== 'production' ? {
...ViewStylePropTypes,
...TextPropTypes
};
} : {};

View File

@@ -1,15 +1,12 @@
/* eslint-env jasmine, jest */
import React from 'react';
import StyleSheet from '../../../apis/StyleSheet';
import TextareaAutosize from 'react-textarea-autosize';
import TextInput from '..';
import { mount, shallow } from 'enzyme';
const placeholderText = 'placeholderText';
const findNativeInput = (wrapper) => wrapper.find('input');
const findNativeTextarea = (wrapper) => wrapper.find(TextareaAutosize);
const findPlaceholder = (wrapper) => wrapper.find({ children: placeholderText });
const testIfDocumentIsFocused = (message, fn) => {
if (document.hasFocus && document.hasFocus()) {
@@ -184,24 +181,6 @@ describe('components/TextInput', () => {
}
});
test('prop "placeholder"', () => {
let textInput = shallow(<TextInput />);
expect(findPlaceholder(textInput).length).toEqual(0);
textInput = shallow(<TextInput placeholder={placeholderText} />);
expect(findPlaceholder(textInput).length).toEqual(1);
});
test('prop "placeholderTextColor"', () => {
let placeholderElement = findPlaceholder(shallow(<TextInput placeholder={placeholderText} />));
expect(StyleSheet.flatten(placeholderElement.prop('style')).color).toEqual('darkgray');
placeholderElement = findPlaceholder(
shallow(<TextInput placeholder={placeholderText} placeholderTextColor='red' />)
);
expect(StyleSheet.flatten(placeholderElement.prop('style')).color).toEqual('red');
});
test('prop "secureTextEntry"', () => {
let input = findNativeInput(shallow(<TextInput secureTextEntry />));
expect(input.prop('type')).toEqual('password');
@@ -224,20 +203,6 @@ describe('components/TextInput', () => {
// assert.equal(input.node.selectionStart, 0)
});
test('prop "style"', () => {
const styles = StyleSheet.create({
root: {
borderWidth: 1,
textAlign: 'center'
}
});
const textInput = shallow(<TextInput style={styles.root} />);
const input = findNativeInput(textInput);
const borderWidth = StyleSheet.flatten(textInput.prop('style')).borderWidth;
expect(borderWidth).toEqual(1);
expect(input.prop('style').textAlign).toEqual('center');
});
test('prop "value"', () => {
const value = 'value';
const input = findNativeInput(shallow(<TextInput value={value} />));

View File

@@ -1,18 +1,14 @@
import applyLayout from '../../modules/applyLayout';
import applyNativeMethods from '../../modules/applyNativeMethods';
import createDOMElement from '../../modules/createDOMElement';
import findNodeHandle from '../../modules/findNodeHandle';
import omit from 'lodash/omit';
import pick from 'lodash/pick';
import StyleSheet from '../../apis/StyleSheet';
import Text from '../Text';
import TextareaAutosize from 'react-textarea-autosize';
import TextInputState from './TextInputState';
import UIManager from '../../apis/UIManager';
import View from '../View';
import ViewStylePropTypes from '../View/ViewStylePropTypes';
import React, { Component, PropTypes } from 'react';
const viewStyleProps = Object.keys(ViewStylePropTypes);
import { Component, PropTypes } from 'react';
/**
* React Native events differ from W3C events.
@@ -25,7 +21,7 @@ const normalizeEventHandler = (handler) => (e) => {
};
/**
* Determins whether a 'selection' prop differs from a node's existing
* Determines whether a 'selection' prop differs from a node's existing
* selection state.
*/
const isSelectionStale = (node, selection) => {
@@ -64,7 +60,7 @@ class TextInput extends Component {
defaultValue: PropTypes.string,
editable: PropTypes.bool,
keyboardType: PropTypes.oneOf([
'default', 'email-address', 'numeric', 'phone-pad', 'search', 'url', 'web-search'
'default', 'email-address', 'number-pad', 'numeric', 'phone-pad', 'search', 'url', 'web-search'
]),
maxLength: PropTypes.number,
maxNumberOfLines: PropTypes.number,
@@ -85,7 +81,6 @@ class TextInput extends Component {
end: PropTypes.number
}),
style: Text.propTypes.style,
testID: Text.propTypes.testID,
value: PropTypes.string
};
@@ -101,60 +96,63 @@ class TextInput extends Component {
style: {}
};
constructor(props, context) {
super(props, context);
this.state = { showPlaceholder: !props.value && !props.defaultValue };
}
blur() {
TextInputState.blurTextInput(findNodeHandle(this._inputRef));
TextInputState.blurTextInput(this._node);
}
clear() {
this.setNativeProps({ text: '' });
this._node.value = '';
}
focus() {
TextInputState.focusTextInput(findNodeHandle(this._inputRef));
TextInputState.focusTextInput(this._node);
}
isFocused() {
return TextInputState.currentlyFocusedField() === findNodeHandle(this._inputRef);
return TextInputState.currentlyFocusedField() === this._node;
}
setNativeProps(props) {
UIManager.updateView(this._inputRef, props, this);
UIManager.updateView(this._node, props, this);
}
componentDidMount() {
setSelection(findNodeHandle(this._inputRef), this.props.selection);
setSelection(this._node, this.props.selection);
}
componentDidUpdate() {
setSelection(findNodeHandle(this._inputRef), this.props.selection);
setSelection(this._node, this.props.selection);
}
render() {
const {
accessibilityLabel, // eslint-disable-line
autoCapitalize,
autoComplete,
autoCorrect,
autoFocus,
defaultValue,
editable,
keyboardType,
maxLength,
maxNumberOfLines,
multiline,
numberOfLines,
onLayout,
placeholder,
placeholderTextColor,
secureTextEntry,
style,
testID,
value
/* eslint-disable */
blurOnSubmit,
clearTextOnFocus,
dataDetectorTypes,
enablesReturnKeyAutomatically,
keyboardAppearance,
onChangeText,
onContentSizeChange,
onEndEditing,
onLayout,
onSelectionChange,
onSubmitEditing,
placeholderTextColor,
returnKeyType,
selection,
selectionColor,
selectTextOnFocus,
/* eslint-enable */
...other
} = this.props;
let type;
@@ -163,6 +161,7 @@ class TextInput extends Component {
case 'email-address':
type = 'email';
break;
case 'number-pad':
case 'numeric':
type = 'number';
break;
@@ -184,29 +183,22 @@ class TextInput extends Component {
type = 'password';
}
// In order to support 'Text' styles on 'TextInput', we split the 'Text'
// and 'View' styles and apply them to the 'Text' and 'View' components
// used in the implementation
const flattenedStyle = StyleSheet.flatten(style);
const rootStyles = pick(flattenedStyle, viewStyleProps);
const textStyles = omit(flattenedStyle, viewStyleProps);
const component = multiline ? TextareaAutosize : 'input';
const props = {
autoCapitalize,
autoComplete,
...other,
autoCorrect: autoCorrect ? 'on' : 'off',
autoFocus,
defaultValue,
maxLength,
onBlur: normalizeEventHandler(this._handleBlur),
onChange: normalizeEventHandler(this._handleChange),
onFocus: normalizeEventHandler(this._handleFocus),
onKeyPress: normalizeEventHandler(this._handleKeyPress),
onSelect: normalizeEventHandler(this._handleSelectionChange),
readOnly: !editable,
ref: this._setInputRef,
style: [ styles.input, textStyles, { outline: style.outline } ],
value
ref: this._setNode,
style: [
styles.initial,
style
]
};
if (multiline) {
@@ -216,66 +208,27 @@ class TextInput extends Component {
props.type = type;
}
const component = multiline ? TextareaAutosize : 'input';
const optionalPlaceholder = placeholder && this.state.showPlaceholder && (
<View pointerEvents='none' style={styles.placeholder}>
<Text
children={placeholder}
style={[
styles.placeholderText,
textStyles,
placeholderTextColor && { color: placeholderTextColor }
]}
/>
</View>
);
return (
<View
accessibilityLabel={accessibilityLabel}
onClick={this._handleClick}
onLayout={onLayout}
style={[ styles.initial, rootStyles ]}
testID={testID}
>
<View style={styles.wrapper}>
{createDOMElement(component, props)}
{optionalPlaceholder}
</View>
</View>
);
return createDOMElement(component, props);
}
_handleBlur = (e) => {
const { onBlur } = this.props;
const { text } = e.nativeEvent;
this.setState({ showPlaceholder: text === '' });
if (onBlur) { onBlur(e); }
}
_handleChange = (e) => {
const { onChange, onChangeText } = this.props;
const { text } = e.nativeEvent;
this.setState({ showPlaceholder: text === '' });
if (onChange) { onChange(e); }
if (onChangeText) { onChangeText(text); }
}
_handleClick = (e) => {
if (this.props.editable) {
this.focus();
}
}
_handleFocus = (e) => {
const { clearTextOnFocus, onFocus, selectTextOnFocus } = this.props;
const { text } = e.nativeEvent;
const node = findNodeHandle(this._inputRef);
const node = this._node;
if (onFocus) { onFocus(e); }
if (clearTextOnFocus) { this.clear(); }
if (selectTextOnFocus) { node && node.select(); }
this.setState({ showPlaceholder: text === '' });
}
_handleKeyPress = (e) => {
@@ -303,43 +256,24 @@ class TextInput extends Component {
}
}
_setInputRef = (component) => {
this._inputRef = component;
_setNode = (component) => {
this._node = findNodeHandle(component);
}
}
const styles = StyleSheet.create({
initial: {
borderColor: 'black'
},
wrapper: {
flex: 1
},
input: {
appearance: 'none',
backgroundColor: 'transparent',
borderColor: 'black',
borderRadius: 0,
borderWidth: 0,
boxSizing: 'border-box',
color: 'inherit',
flex: 1,
font: 'inherit',
minHeight: '100%', // center small inputs (fix #139)
padding: 0,
zIndex: 1
},
placeholder: {
bottom: 0,
left: 0,
position: 'absolute',
right: 0,
top: 0
},
placeholderText: {
color: 'darkgray',
overflow: 'hidden',
whiteSpace: 'pre'
padding: 0
}
});
module.exports = applyNativeMethods(TextInput);
module.exports = applyLayout(applyNativeMethods(TextInput));

View File

@@ -14,7 +14,6 @@
/* @edit start */
const BoundingDimensions = require('./BoundingDimensions');
const keyMirror = require('fbjs/lib/keyMirror');
const normalizeColor = require('../../modules/normalizeColor');
const Position = require('./Position');
const React = require('react');
@@ -111,16 +110,16 @@ const View = require('../../components/View');
/**
* Touchable states.
*/
var States = keyMirror({
NOT_RESPONDER: null, // Not the responder
RESPONDER_INACTIVE_PRESS_IN: null, // Responder, inactive, in the `PressRect`
RESPONDER_INACTIVE_PRESS_OUT: null, // Responder, inactive, out of `PressRect`
RESPONDER_ACTIVE_PRESS_IN: null, // Responder, active, in the `PressRect`
RESPONDER_ACTIVE_PRESS_OUT: null, // Responder, active, out of `PressRect`
RESPONDER_ACTIVE_LONG_PRESS_IN: null, // Responder, active, in the `PressRect`, after long press threshold
RESPONDER_ACTIVE_LONG_PRESS_OUT: null, // Responder, active, out of `PressRect`, after long press threshold
ERROR: null
});
var States = {
NOT_RESPONDER: 'NOT_RESPONDER', // Not the responder
RESPONDER_INACTIVE_PRESS_IN: 'RESPONDER_INACTIVE_PRESS_IN', // Responder, inactive, in the `PressRect`
RESPONDER_INACTIVE_PRESS_OUT: 'RESPONDER_INACTIVE_PRESS_OUT', // Responder, inactive, out of `PressRect`
RESPONDER_ACTIVE_PRESS_IN: 'RESPONDER_ACTIVE_PRESS_IN', // Responder, active, in the `PressRect`
RESPONDER_ACTIVE_PRESS_OUT: 'RESPONDER_ACTIVE_PRESS_OUT', // Responder, active, out of `PressRect`
RESPONDER_ACTIVE_LONG_PRESS_IN: 'RESPONDER_ACTIVE_LONG_PRESS_IN', // Responder, active, in the `PressRect`, after long press threshold
RESPONDER_ACTIVE_LONG_PRESS_OUT: 'RESPONDER_ACTIVE_LONG_PRESS_OUT', // Responder, active, out of `PressRect`, after long press threshold
ERROR: 'ERROR'
};
/**
* Quick lookup map for states that are considered to be "active"
@@ -147,15 +146,15 @@ var IsLongPressingIn = {
/**
* Inputs to the state machine.
*/
var Signals = keyMirror({
DELAY: null,
RESPONDER_GRANT: null,
RESPONDER_RELEASE: null,
RESPONDER_TERMINATED: null,
ENTER_PRESS_RECT: null,
LEAVE_PRESS_RECT: null,
LONG_PRESS_DETECTED: null,
});
var Signals = {
DELAY: 'DELAY',
RESPONDER_GRANT: 'RESPONDER_GRANT',
RESPONDER_RELEASE: 'RESPONDER_RELEASE',
RESPONDER_TERMINATED: 'RESPONDER_TERMINATED',
ENTER_PRESS_RECT: 'ENTER_PRESS_RECT',
LEAVE_PRESS_RECT: 'LEAVE_PRESS_RECT',
LONG_PRESS_DETECTED: 'LONG_PRESS_DETECTED',
};
/**
* Mapping from States x Signals => States

View File

@@ -1,164 +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 TouchableBounce
* @flow
*/
'use strict';
var Animated = require('../../apis/Animated');
var EdgeInsetsPropType = require('../../propTypes/EdgeInsetsPropType');
var NativeMethodsMixin = require('../../modules/NativeMethodsMixin');
var React = require('react');
var StyleSheet = require('../../apis/StyleSheet');
var Touchable = require('./Touchable');
type Event = Object;
type State = {
animationID: ?number;
scale: Animated.Value;
};
var PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
/**
* Example of using the `TouchableMixin` to play well with other responder
* locking views including `ScrollView`. `TouchableMixin` provides touchable
* hooks (`this.touchableHandle*`) that we forward events to. In turn,
* `TouchableMixin` expects us to implement some abstract methods to handle
* interesting interactions such as `handleTouchablePress`.
*/
var TouchableBounce = React.createClass({
mixins: [Touchable.Mixin, NativeMethodsMixin],
propTypes: {
onPress: React.PropTypes.func,
onPressIn: React.PropTypes.func,
onPressOut: React.PropTypes.func,
// The function passed takes a callback to start the animation which should
// be run after this onPress handler is done. You can use this (for example)
// to update UI before starting the animation.
onPressWithCompletion: React.PropTypes.func,
// the function passed is called after the animation is complete
onPressAnimationComplete: React.PropTypes.func,
/**
* When the scroll view is disabled, this defines how far your touch may
* move off of the button, before deactivating the button. Once deactivated,
* try moving it back and you'll see that the button is once again
* reactivated! Move it back and forth several times while the scroll view
* is disabled. Ensure you pass in a constant to reduce memory allocations.
*/
pressRetentionOffset: EdgeInsetsPropType,
/**
* 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.
*/
hitSlop: EdgeInsetsPropType,
},
getInitialState: function(): State {
return {
...this.touchableGetInitialState(),
scale: new Animated.Value(1),
};
},
bounceTo: function(
value: number,
velocity: number,
bounciness: number,
callback?: ?Function
) {
Animated.spring(this.state.scale, {
toValue: value,
velocity,
bounciness,
}).start(callback);
},
/**
* `Touchable.Mixin` self callbacks. The mixin will invoke these if they are
* defined on your component.
*/
touchableHandleActivePressIn: function(e: Event) {
this.bounceTo(0.93, 0.1, 0);
this.props.onPressIn && this.props.onPressIn(e);
},
touchableHandleActivePressOut: function(e: Event) {
this.bounceTo(1, 0.4, 0);
this.props.onPressOut && this.props.onPressOut(e);
},
touchableHandlePress: function(e: Event) {
var onPressWithCompletion = this.props.onPressWithCompletion;
if (onPressWithCompletion) {
onPressWithCompletion(() => {
this.state.scale.setValue(0.93);
this.bounceTo(1, 10, 10, this.props.onPressAnimationComplete);
});
return;
}
this.bounceTo(1, 10, 10, this.props.onPressAnimationComplete);
this.props.onPress && this.props.onPress(e);
},
touchableGetPressRectOffset: function(): typeof PRESS_RETENTION_OFFSET {
return this.props.pressRetentionOffset || PRESS_RETENTION_OFFSET;
},
touchableGetHitSlop: function(): ?Object {
return this.props.hitSlop;
},
touchableGetHighlightDelayMS: function(): number {
return 0;
},
render: function(): ReactElement {
const scaleTransform = [{ scale: this.state.scale }];
const propsTransform = this.props.style.transform;
const transform = propsTransform && Array.isArray(propsTransform) ? propsTransform.concat(scaleTransform) : scaleTransform;
return (
<Animated.View
accessible={true}
accessibilityLabel={this.props.accessibilityLabel}
accessibilityRole={this.props.accessibilityRole || 'button'}
testID={this.props.testID}
hitSlop={this.props.hitSlop}
onStartShouldSetResponder={this.touchableHandleStartShouldSetResponder}
onResponderTerminationRequest={this.touchableHandleResponderTerminationRequest}
onResponderGrant={this.touchableHandleResponderGrant}
onResponderMove={this.touchableHandleResponderMove}
onResponderRelease={this.touchableHandleResponderRelease}
onResponderTerminate={this.touchableHandleResponderTerminate}
style={[styles.root, this.props.style, { transform }]}
tabIndex='0'
>
{this.props.children}
</Animated.View>
);
}
});
const styles = StyleSheet.create({
root: {
cursor: 'pointer',
userSelect: 'none'
}
});
module.exports = TouchableBounce;

View File

@@ -26,7 +26,6 @@ var View = require('../View');
var ensureComponentIsNative = require('./ensureComponentIsNative');
var ensurePositiveDelayProps = require('./ensurePositiveDelayProps');
var keyOf = require('fbjs/lib/keyOf');
var merge = require('../../modules/merge');
type Event = Object;
@@ -78,7 +77,7 @@ var TouchableHighlight = React.createClass({
* active.
*/
underlayColor: ColorPropType,
style: View.propTypes.style,
style: React.PropTypes.style,
/**
* Called immediately after the underlay is shown
*/
@@ -115,7 +114,7 @@ var TouchableHighlight = React.createClass({
},
getInitialState: function() {
return merge(this.touchableGetInitialState(), this.computeSyntheticState(this.props))
return { ...this.touchableGetInitialState(), ...this.computeSyntheticState(this.props) }
},
componentDidMount: function() {

View File

@@ -16,7 +16,6 @@ var EdgeInsetsPropType = require('../../propTypes/EdgeInsetsPropType');
var React = require('react');
var TimerMixin = require('react-timer-mixin');
var Touchable = require('./Touchable');
var View = require('../View');
var ensurePositiveDelayProps = require('./ensurePositiveDelayProps');
var warning = require('fbjs/lib/warning');
var StyleSheet = require('../../apis/StyleSheet');
@@ -38,9 +37,9 @@ const TouchableWithoutFeedback = React.createClass({
mixins: [TimerMixin, Touchable.Mixin],
propTypes: {
accessible: View.propTypes.accessible,
accessibilityLabel: View.propTypes.accessibilityLabel,
accessibilityRole: View.propTypes.accessibilityRole,
accessible: React.PropTypes.bool,
accessibilityLabel: React.PropTypes.string,
accessibilityRole: React.PropTypes.string,
/**
* If true, disable all interactions for this component.
*/

View File

@@ -8,7 +8,7 @@ const { number, oneOf, string } = PropTypes;
const autoOrHiddenOrVisible = oneOf([ 'auto', 'hidden', 'visible' ]);
const hiddenOrVisible = oneOf([ 'hidden', 'visible' ]);
module.exports = {
module.exports = process.env.NODE_ENV !== 'production' ? {
...BorderPropTypes,
...LayoutPropTypes,
...TransformPropTypes,
@@ -36,4 +36,4 @@ module.exports = {
userSelect: string,
visibility: hiddenOrVisible,
WebkitOverflowScrolling: oneOf([ 'auto', 'touch' ])
};
} : {};

View File

@@ -1,6 +1,5 @@
import findNodeHandle from './modules/findNodeHandle';
import ReactDOM from 'react-dom';
import ReactDOMServer from 'react-dom/server';
import { render, unmountComponentAtNode } from 'react/lib/ReactMount';
// APIs
import I18nManager from './apis/I18nManager';
@@ -14,10 +13,8 @@ import View from './components/View';
const ReactNativeCore = {
findNodeHandle,
render: ReactDOM.render,
renderToStaticMarkup: ReactDOMServer.renderToStaticMarkup,
renderToString: ReactDOMServer.renderToString,
unmountComponentAtNode: ReactDOM.unmountComponentAtNode,
render,
unmountComponentAtNode,
// APIs
I18nManager,
StyleSheet,

View File

@@ -1,6 +1,5 @@
import findNodeHandle from './modules/findNodeHandle';
import ReactDOM from 'react-dom';
import ReactDOMServer from 'react-dom/server';
import { render, unmountComponentAtNode } from 'react/lib/ReactMount';
// APIs
import Animated from './apis/Animated';
@@ -29,7 +28,6 @@ import Switch from './components/Switch';
import Text from './components/Text';
import TextInput from './components/TextInput';
import Touchable from './components/Touchable/Touchable';
import TouchableBounce from './components/Touchable/TouchableBounce';
import TouchableHighlight from './components/Touchable/TouchableHighlight';
import TouchableOpacity from './components/Touchable/TouchableOpacity';
import TouchableWithoutFeedback from './components/Touchable/TouchableWithoutFeedback';
@@ -47,11 +45,8 @@ import PointPropType from './propTypes/PointPropType';
const ReactNative = {
// top-level API
findNodeHandle,
render: ReactDOM.render,
unmountComponentAtNode: ReactDOM.unmountComponentAtNode,
// web-only
renderToStaticMarkup: ReactDOMServer.renderToStaticMarkup,
renderToString: ReactDOMServer.renderToString,
render,
unmountComponentAtNode,
// APIs
Animated,
@@ -80,7 +75,6 @@ const ReactNative = {
Text,
TextInput,
Touchable,
TouchableBounce,
TouchableHighlight,
TouchableOpacity,
TouchableWithoutFeedback,

View File

@@ -7,7 +7,7 @@
*/
import { Component } from 'react';
import ReactDOM from 'react-dom';
import findNodeHandle from '../findNodeHandle';
import UIManager from '../../apis/UIManager';
type MeasureInWindowOnSuccessCallback = (
@@ -38,7 +38,7 @@ const NativeMethodsMixin = {
* Removes focus from an input or view. This is the opposite of `focus()`.
*/
blur() {
UIManager.blur(ReactDOM.findDOMNode(this));
UIManager.blur(findNodeHandle(this));
},
/**
@@ -46,7 +46,7 @@ const NativeMethodsMixin = {
* The exact behavior triggered will depend the type of view.
*/
focus() {
UIManager.focus(ReactDOM.findDOMNode(this));
UIManager.focus(findNodeHandle(this));
},
/**
@@ -54,7 +54,7 @@ const NativeMethodsMixin = {
*/
measure(callback: MeasureOnSuccessCallback) {
UIManager.measure(
ReactDOM.findDOMNode(this),
findNodeHandle(this),
mountSafeCallback(this, callback)
);
},
@@ -76,7 +76,7 @@ const NativeMethodsMixin = {
*/
measureInWindow(callback: MeasureInWindowOnSuccessCallback) {
UIManager.measureInWindow(
ReactDOM.findDOMNode(this),
findNodeHandle(this),
mountSafeCallback(this, callback)
);
},
@@ -90,7 +90,7 @@ const NativeMethodsMixin = {
onFail: () => void /* currently unused */
) {
UIManager.measureLayout(
ReactDOM.findDOMNode(this),
findNodeHandle(this),
relativeToNativeNode,
mountSafeCallback(this, onFail),
mountSafeCallback(this, onSuccess)
@@ -102,7 +102,7 @@ const NativeMethodsMixin = {
*/
setNativeProps(nativeProps: Object) {
UIManager.updateView(
ReactDOM.findDOMNode(this),
findNodeHandle(this),
nativeProps,
this
);

View File

@@ -13,9 +13,9 @@
'use strict';
var Dimensions = require('../../apis/Dimensions');
var findNodeHandle = require('../findNodeHandle');
var Platform = require('../../apis/Platform');
var React = require('react');
var ReactDOM = require('react-dom');
// var Subscribable = require('../Subscribable');
var TextInputState = require('../../components/TextInput/TextInputState');
var UIManager = require('../../apis/UIManager');
@@ -356,7 +356,7 @@ var ScrollResponderMixin = {
scrollResponderGetScrollableNode: function(): any {
return this.getScrollableNode ?
this.getScrollableNode() :
ReactDOM.findDOMNode(this);
findNodeHandle(this);
},
/**
@@ -423,7 +423,7 @@ var ScrollResponderMixin = {
this.preventNegativeScrollOffset = !!preventNegativeScrollOffset;
UIManager.measureLayout(
nodeHandle,
ReactDOM.findDOMNode(this.getInnerViewNode()),
findNodeHandle(this.getInnerViewNode()),
this.scrollResponderTextInputFocusError,
this.scrollResponderInputMeasureAndScrollToKeyboard
);

View File

@@ -12,13 +12,13 @@ const applyLayout = (Component) => {
const componentDidUpdate = Component.prototype.componentDidUpdate || emptyFunction;
Component.prototype.componentDidMount = function () {
componentDidMount();
componentDidMount.call(this);
this._layoutState = {};
this._handleLayout();
};
Component.prototype.componentDidUpdate = function () {
componentDidUpdate();
componentDidUpdate.call(this);
this._handleLayout();
};

View File

@@ -1,3 +1,2 @@
import ReactDOM from 'react-dom';
const findNodeHandle = ReactDOM.findDOMNode;
import findNodeHandle from 'react/lib/findDOMNode';
export default findNodeHandle;

View File

@@ -1,222 +0,0 @@
/* eslint-disable */
/**
* @generated SignedSource<<b68d78236d45828b3f7f7fcc740782a9>>
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !! This file is a check-in of a static_upstream project! !!
* !! !!
* !! You should not modify this file directly. Instead: !!
* !! 1) Use `fjs use-upstream` to temporarily replace this with !!
* !! the latest version from upstream. !!
* !! 2) Make your changes, test them, etc. !!
* !! 3) Use `fjs push-upstream` to copy your changes back to !!
* !! static_upstream. !!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
* Copyright 2013-2014 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @providesModule mergeHelpers
*
* requiresPolyfills: Array.isArray
*/
"use strict";
var invariant = require('fbjs/lib/invariant');
var keyMirror = require('fbjs/lib/keyMirror');
/**
* Maximum number of levels to traverse. Will catch circular structures.
* @const
*/
var MAX_MERGE_DEPTH = 36;
/**
* We won't worry about edge cases like new String('x') or new Boolean(true).
* Functions are considered terminals, and arrays are not.
* @param {*} o The item/object/value to test.
* @return {boolean} true iff the argument is a terminal.
*/
var isTerminal = function(o) {
return typeof o !== 'object' || o === null;
};
var mergeHelpers = {
MAX_MERGE_DEPTH: MAX_MERGE_DEPTH,
isTerminal: isTerminal,
/**
* Converts null/undefined values into empty object.
*
* @param {?Object=} arg Argument to be normalized (nullable optional)
* @return {!Object}
*/
normalizeMergeArg: function(arg) {
return arg === undefined || arg === null ? {} : arg;
},
/**
* If merging Arrays, a merge strategy *must* be supplied. If not, it is
* likely the caller's fault. If this function is ever called with anything
* but `one` and `two` being `Array`s, it is the fault of the merge utilities.
*
* @param {*} one Array to merge into.
* @param {*} two Array to merge from.
*/
checkMergeArrayArgs: function(one, two) {
invariant(
Array.isArray(one) && Array.isArray(two),
'Tried to merge arrays, instead got %s and %s.',
one,
two
);
},
/**
* @param {*} one Object to merge into.
* @param {*} two Object to merge from.
*/
checkMergeObjectArgs: function(one, two) {
mergeHelpers.checkMergeObjectArg(one);
mergeHelpers.checkMergeObjectArg(two);
},
/**
* @param {*} arg
*/
checkMergeObjectArg: function(arg) {
invariant(
!isTerminal(arg) && !Array.isArray(arg),
'Tried to merge an object, instead got %s.',
arg
);
},
/**
* @param {*} arg
*/
checkMergeIntoObjectArg: function(arg) {
invariant(
(!isTerminal(arg) || typeof arg === 'function') && !Array.isArray(arg),
'Tried to merge into an object, instead got %s.',
arg
);
},
/**
* Checks that a merge was not given a circular object or an object that had
* too great of depth.
*
* @param {number} Level of recursion to validate against maximum.
*/
checkMergeLevel: function(level) {
invariant(
level < MAX_MERGE_DEPTH,
'Maximum deep merge depth exceeded. You may be attempting to merge ' +
'circular structures in an unsupported way.'
);
},
/**
* Checks that the supplied merge strategy is valid.
*
* @param {string} Array merge strategy.
*/
checkArrayStrategy: function(strategy) {
invariant(
strategy === undefined || strategy in mergeHelpers.ArrayStrategies,
'You must provide an array strategy to deep merge functions to ' +
'instruct the deep merge how to resolve merging two arrays.'
);
},
/**
* Set of possible behaviors of merge algorithms when encountering two Arrays
* that must be merged together.
* - `clobber`: The left `Array` is ignored.
* - `indexByIndex`: The result is achieved by recursively deep merging at
* each index. (not yet supported.)
*/
ArrayStrategies: keyMirror({
Clobber: true,
IndexByIndex: true
})
};
/**
* @generated SignedSource<<d3caa35be27b17ea4dd4c76bef72d1ab>>
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !! This file is a check-in of a static_upstream project! !!
* !! !!
* !! You should not modify this file directly. Instead: !!
* !! 1) Use `fjs use-upstream` to temporarily replace this with !!
* !! the latest version from upstream. !!
* !! 2) Make your changes, test them, etc. !!
* !! 3) Use `fjs push-upstream` to copy your changes back to !!
* !! static_upstream. !!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
* Copyright 2013-2014 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @providesModule mergeInto
* @typechecks static-only
*/
var checkMergeObjectArg = mergeHelpers.checkMergeObjectArg;
var checkMergeIntoObjectArg = mergeHelpers.checkMergeIntoObjectArg;
/**
* Shallow merges two structures by mutating the first parameter.
*
* @param {object|function} one Object to be merged into.
* @param {?object} two Optional object with properties to merge from.
*/
function mergeInto(one, two) {
checkMergeIntoObjectArg(one);
if (two != null) {
checkMergeObjectArg(two);
for (var key in two) {
if (!two.hasOwnProperty(key)) {
continue;
}
one[key] = two[key];
}
}
}
var merge = function(one, two) {
var result = {};
mergeInto(result, one);
mergeInto(result, two);
return result;
};
module.exports = merge;

View File

@@ -1,13 +1,13 @@
import { PropTypes } from 'react';
const { array, bool, number, object, oneOf, oneOfType, string } = PropTypes;
const BaseComponentPropTypes = {
const BaseComponentPropTypes = process.env.NODE_ENV !== 'production' ? {
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 = {
const BorderPropTypes = process.env.NODE_ENV !== 'production' ? {
borderColor: ColorPropType,
borderTopColor: ColorPropType,
borderRightColor: ColorPropType,
@@ -29,6 +29,6 @@ const BorderPropTypes = {
borderBottomRightRadius$noI18n: numberOrString,
borderLeftStyle$noI18n: BorderStylePropType,
borderRightStyle$noI18n: BorderStylePropType
};
} : {};
module.exports = BorderPropTypes;

View File

@@ -11,11 +11,10 @@
*/
import { PropTypes } from 'react'
import ReactPropTypeLocationNames from 'react/lib/ReactPropTypeLocationNames'
var normalizeColor = require('../modules/normalizeColor');
var colorPropType = function(isRequired, props, propName, componentName, location, propFullName) {
var normalizeColor = require('../modules/normalizeColor');
var ReactPropTypeLocationNames = require('react/lib/ReactPropTypeLocationNames');
var color = props[propName];
if (color === undefined || color === null) {
if (isRequired) {
@@ -56,7 +55,11 @@ var colorPropType = function(isRequired, props, propName, componentName, locatio
}
};
var ColorPropType = colorPropType.bind(null, false /* isRequired */);
ColorPropType.isRequired = colorPropType.bind(null, true /* isRequired */);
if (process.env.NODE_ENV !== 'production') {
var ColorPropType = colorPropType.bind(null, false /* isRequired */);
ColorPropType.isRequired = colorPropType.bind(null, true /* isRequired */);
} else {
var ColorPropType = function () {}
}
module.exports = ColorPropType

View File

@@ -14,13 +14,11 @@
var PropTypes = require('react').PropTypes;
var createStrictShapeTypeChecker = require('./createStrictShapeTypeChecker');
var EdgeInsetsPropType = createStrictShapeTypeChecker({
var EdgeInsetsPropType = process.env.NODE_ENV !== 'production' ? 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 = {
const LayoutPropTypes = process.env.NODE_ENV !== 'production' ? {
// box model
borderWidth: numberOrString,
borderBottomWidth: numberOrString,
@@ -58,6 +58,6 @@ const LayoutPropTypes = {
paddingLeft$noI18n: numberOrString,
paddingRight$noI18n: numberOrString,
right$noI18n: numberOrString
};
} : {};
module.exports = LayoutPropTypes;

View File

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

View File

@@ -5,10 +5,10 @@
* @flow
*/
import createStrictShapeTypeChecker from './createStrictShapeTypeChecker';
import flattenStyle from '../modules/flattenStyle';
module.exports = process.env.NODE_ENV !== 'production' ? function StyleSheetPropType(shape) {
const createStrictShapeTypeChecker = require('./createStrictShapeTypeChecker');
const flattenStyle = require('../modules/flattenStyle');
module.exports = function StyleSheetPropType(shape) {
const shapePropType = createStrictShapeTypeChecker(shape);
return function (props, propName, componentName, location?) {
let newProps = props;
@@ -19,4 +19,4 @@ module.exports = function StyleSheetPropType(shape) {
}
return shapePropType(newProps, propName, componentName, location);
};
};
} : function () {};

View File

@@ -8,7 +8,7 @@ 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 = {
const TextPropTypes = process.env.NODE_ENV !== 'production' ? {
// box model
color: ColorPropType,
fontFamily: string,
@@ -40,6 +40,6 @@ const TextPropTypes = {
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 = {
const TransformPropTypes = process.env.NODE_ENV !== 'production' ? {
transform: arrayOf(
oneOfType([
shape({ perspective: numberOrString }),
@@ -29,6 +29,6 @@ const TransformPropTypes = {
shape({ translate3d: string })
])
)
};
} : {};
module.exports = TransformPropTypes;

View File

@@ -12,7 +12,6 @@
*/
import invariant from 'fbjs/lib/invariant'
import merge from '../modules/merge'
import ReactPropTypeLocationNames from 'react/lib/ReactPropTypeLocationNames'
import ReactPropTypesSecret from 'react/lib/ReactPropTypesSecret'
@@ -43,7 +42,7 @@ function createStrictShapeTypeChecker(
}
// We need to check all keys in case some are required but missing from
// props.
var allKeys = merge(props[propName], shapeTypes);
var allKeys = { ...props[propName], ...shapeTypes };
for (var key in allKeys) {
var checker = shapeTypes[key];
if (!checker) {

View File

@@ -1,5 +1,6 @@
const path = require('path')
const webpack = require('webpack')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const DIST_DIRECTORY = './dist'
@@ -7,6 +8,16 @@ module.exports = {
entry: {
main: DIST_DIRECTORY
},
externals: [
{
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react'
}
}
],
output: {
filename: 'ReactNative.js',
library: 'ReactNative',
@@ -14,6 +25,10 @@ module.exports = {
path: DIST_DIRECTORY
},
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false
}),
new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }),
new webpack.optimize.DedupePlugin(),
// https://github.com/animatedjs/animated/issues/40

5890
yarn.lock Normal file

File diff suppressed because it is too large Load Diff