Updates from Mon 6 Apr

- [ReactNative] Revert D1965911 | Christopher Chedeau
- [ReactNative] Remove experimental Portal only needed for android right now. | Spencer Ahrens
- [ReactNative] rename Animation to AnimationExperimental with warning docs | Spencer Ahrens
- navigator.getCurrentRoutes() | Eric Vicenti
- Fixing jsdoc parsing of functions that are defined over multiple lines (Fixes #410) | Christopher Chedeau
- Added constraint of child type to touchablewithoutfeedback | Christopher Chedeau
- [react-packager] Deprecate global image namespace in favor of CommonJS resolution | Amjad Masad
- [react-packager] Don't cache rejected promise | Amjad Masad
- [ReactNative] Start Navigator gesture config, disable gesture in AdsManager | Eric Vicenti
- [Flow] Clean react-native-github for Flow v0.8.0 | Gabe Levi
- add maximumValue and minimumValue as valid attributes for native Slider | Christopher Chedeau
- react-packager: Add ES6 import statement support to DependencyGraph. | Amjad Masad
- Remove false annotation | Christopher Chedeau
- [madman] prevent pulling the content down inconsistently when the keyboard shows up | Kevin Gozali
- add @flow back to View.js | Basil Hosmer
- [ReactNative] Turn of lint warning for constant conditions | Eric Vicenti
- [UIExplorer] Fixed 'Push View Example' in NavigatorIOS example | Christopher Chedeau
- SliderIOS.js comments - grammar correction | Christopher Chedeau
This commit is contained in:
Christopher Chedeau 2015-04-06 08:38:56 -07:00
parent 12698ed4af
commit 85e1ad6b61
32 changed files with 966 additions and 464 deletions

View File

@ -37,7 +37,7 @@
"rules": { "rules": {
"no-cond-assign": 1, // disallow assignment in conditional expressions "no-cond-assign": 1, // disallow assignment in conditional expressions
"no-console": 0, // disallow use of console (off by default in the node environment) "no-console": 0, // disallow use of console (off by default in the node environment)
"no-constant-condition": 1, // disallow use of constant expressions in conditions "no-constant-condition": 0, // disallow use of constant expressions in conditions
"no-comma-dangle": 0, // disallow trailing commas in object literals "no-comma-dangle": 0, // disallow trailing commas in object literals
"no-control-regex": 1, // disallow control characters in regular expressions "no-control-regex": 1, // disallow control characters in regular expressions
"no-debugger": 1, // disallow use of debugger "no-debugger": 1, // disallow use of debugger

View File

@ -7,23 +7,16 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
13ACB6741AC2117000FF4204 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13ACB6711AC2113600FF4204 /* libRCTAnimation.a */; };
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
1461632D1AC3E23900C2F5AD /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1461632C1AC3E22900C2F5AD /* libReact.a */; }; 1461632D1AC3E23900C2F5AD /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1461632C1AC3E22900C2F5AD /* libReact.a */; };
58C1E40E1ACF54E9006D1A47 /* libRCTAnimationExperimental.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C1E40B1ACF54B4006D1A47 /* libRCTAnimationExperimental.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
13ACB6701AC2113600FF4204 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 13ACB66C1AC2113500FF4204 /* RCTAnimation.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTAnimation;
};
1461632B1AC3E22900C2F5AD /* PBXContainerItemProxy */ = { 1461632B1AC3E22900C2F5AD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy; isa = PBXContainerItemProxy;
containerPortal = 146163271AC3E22900C2F5AD /* React.xcodeproj */; containerPortal = 146163271AC3E22900C2F5AD /* React.xcodeproj */;
@ -31,6 +24,13 @@
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
remoteInfo = React; remoteInfo = React;
}; };
58C1E40A1ACF54B4006D1A47 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 13ACB66C1AC2113500FF4204 /* RCTAnimationExperimental.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTAnimationExperimental;
};
832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy; isa = PBXContainerItemProxy;
containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
@ -41,7 +41,7 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
13ACB66C1AC2113500FF4204 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = ../../Libraries/Animation/RCTAnimation.xcodeproj; sourceTree = "<group>"; }; 13ACB66C1AC2113500FF4204 /* RCTAnimationExperimental.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimationExperimental.xcodeproj; path = ../../Libraries/Animation/RCTAnimationExperimental.xcodeproj; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* 2048.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = 2048.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* 2048.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = 2048.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = 2048/AppDelegate.h; sourceTree = "<group>"; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = 2048/AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = 2048/AppDelegate.m; sourceTree = "<group>"; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = 2048/AppDelegate.m; sourceTree = "<group>"; };
@ -59,7 +59,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
1461632D1AC3E23900C2F5AD /* libReact.a in Frameworks */, 1461632D1AC3E23900C2F5AD /* libReact.a in Frameworks */,
13ACB6741AC2117000FF4204 /* libRCTAnimation.a in Frameworks */, 58C1E40E1ACF54E9006D1A47 /* libRCTAnimationExperimental.a in Frameworks */,
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -67,14 +67,6 @@
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
13ACB66D1AC2113500FF4204 /* Products */ = {
isa = PBXGroup;
children = (
13ACB6711AC2113600FF4204 /* libRCTAnimation.a */,
);
name = Products;
sourceTree = "<group>";
};
13B07FAE1A68108700A75B9A /* 2048 */ = { 13B07FAE1A68108700A75B9A /* 2048 */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -96,12 +88,20 @@
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
58C1E4071ACF54B4006D1A47 /* Products */ = {
isa = PBXGroup;
children = (
58C1E40B1ACF54B4006D1A47 /* libRCTAnimationExperimental.a */,
);
name = Products;
sourceTree = "<group>";
};
832341AE1AAA6A7D00B99B32 /* Libraries */ = { 832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
146163271AC3E22900C2F5AD /* React.xcodeproj */, 146163271AC3E22900C2F5AD /* React.xcodeproj */,
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
13ACB66C1AC2113500FF4204 /* RCTAnimation.xcodeproj */, 13ACB66C1AC2113500FF4204 /* RCTAnimationExperimental.xcodeproj */,
); );
name = Libraries; name = Libraries;
sourceTree = "<group>"; sourceTree = "<group>";
@ -175,8 +175,8 @@
projectDirPath = ""; projectDirPath = "";
projectReferences = ( projectReferences = (
{ {
ProductGroup = 13ACB66D1AC2113500FF4204 /* Products */; ProductGroup = 58C1E4071ACF54B4006D1A47 /* Products */;
ProjectRef = 13ACB66C1AC2113500FF4204 /* RCTAnimation.xcodeproj */; ProjectRef = 13ACB66C1AC2113500FF4204 /* RCTAnimationExperimental.xcodeproj */;
}, },
{ {
ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; ProductGroup = 832341B11AAA6A8300B99B32 /* Products */;
@ -195,13 +195,6 @@
/* End PBXProject section */ /* End PBXProject section */
/* Begin PBXReferenceProxy section */ /* Begin PBXReferenceProxy section */
13ACB6711AC2113600FF4204 /* libRCTAnimation.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTAnimation.a;
remoteRef = 13ACB6701AC2113600FF4204 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
1461632C1AC3E22900C2F5AD /* libReact.a */ = { 1461632C1AC3E22900C2F5AD /* libReact.a */ = {
isa = PBXReferenceProxy; isa = PBXReferenceProxy;
fileType = archive.ar; fileType = archive.ar;
@ -209,6 +202,13 @@
remoteRef = 1461632B1AC3E22900C2F5AD /* PBXContainerItemProxy */; remoteRef = 1461632B1AC3E22900C2F5AD /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR; sourceTree = BUILT_PRODUCTS_DIR;
}; };
58C1E40B1ACF54B4006D1A47 /* libRCTAnimationExperimental.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTAnimationExperimental.a;
remoteRef = 58C1E40A1ACF54B4006D1A47 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
832341B51AAA6A8300B99B32 /* libRCTText.a */ = { 832341B51AAA6A8300B99B32 /* libRCTText.a */ = {
isa = PBXReferenceProxy; isa = PBXReferenceProxy;
fileType = archive.ar; fileType = archive.ar;
@ -266,6 +266,10 @@
); );
INFOPLIST_FILE = "$(SRCROOT)/2048/Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/2048/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"/Users/sahrens/src/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Animation/build/Debug-iphoneos",
);
OTHER_LDFLAGS = "-ObjC"; OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = 2048; PRODUCT_NAME = 2048;
}; };
@ -282,6 +286,10 @@
); );
INFOPLIST_FILE = "$(SRCROOT)/2048/Info.plist"; INFOPLIST_FILE = "$(SRCROOT)/2048/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"/Users/sahrens/src/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Animation/build/Debug-iphoneos",
);
OTHER_LDFLAGS = "-ObjC"; OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = 2048; PRODUCT_NAME = 2048;
}; };

View File

@ -18,13 +18,13 @@
var React = require('react-native'); var React = require('react-native');
var { var {
Animation,
AppRegistry, AppRegistry,
StyleSheet, StyleSheet,
Text, Text,
View, View,
} = React; } = React;
var AnimationExperimental = require('AnimationExperimental');
var GameBoard = require('GameBoard'); var GameBoard = require('GameBoard');
var TouchableBounce = require('TouchableBounce'); var TouchableBounce = require('TouchableBounce');
@ -77,17 +77,15 @@ class Tile extends React.Component {
animationPosition(tile.toColumn()), animationPosition(tile.toColumn()),
animationPosition(tile.toRow()), animationPosition(tile.toRow()),
]; ];
Animation.startAnimation(this.refs['this'], 100, 0, 'easeInOutQuad', {position: point}); AnimationExperimental.startAnimation(this.refs['this'], 100, 0, 'easeInOutQuad', {position: point});
} }
return offset; return offset;
} }
componentDidMount() { componentDidMount() {
setTimeout(() => { AnimationExperimental.startAnimation(this.refs['this'], 100, 0, 'easeInOutQuad', {opacity: 1});
Animation.startAnimation(this.refs['this'], 300, 0, 'easeInOutQuad', {scaleXY: [1, 1]});
Animation.startAnimation(this.refs['this'], 100, 0, 'easeInOutQuad', {opacity: 1});
}, 0);
} }
render() { render() {

View File

@ -52,26 +52,45 @@ var ROUTE_STACK = [
var INIT_ROUTE_INDEX = 1; var INIT_ROUTE_INDEX = 1;
class JumpingNavBar extends React.Component { class JumpingNavBar extends React.Component {
constructor(props) {
super(props);
this.state = {
tabIndex: props.initTabIndex,
};
}
handleWillFocus(route) {
var tabIndex = ROUTE_STACK.indexOf(route);
this.setState({ tabIndex, });
}
render() { render() {
return ( return (
<View style={styles.tabs}> <View style={styles.tabs}>
<TabBarIOS> <TabBarIOS>
<TabBarIOS.Item <TabBarIOS.Item
icon={require('image!tabnav_notification')} icon={require('image!tabnav_notification')}
selected={this.props.tabIndex === 0} selected={this.state.tabIndex === 0}
onPress={() => { this.props.onTabIndex(0); }}> onPress={() => {
this.props.onTabIndex(0);
this.setState({ tabIndex: 0, });
}}>
<View /> <View />
</TabBarIOS.Item> </TabBarIOS.Item>
<TabBarIOS.Item <TabBarIOS.Item
icon={require('image!tabnav_list')} icon={require('image!tabnav_list')}
selected={this.props.tabIndex === 1} selected={this.state.tabIndex === 1}
onPress={() => { this.props.onTabIndex(1); }}> onPress={() => {
this.props.onTabIndex(1);
this.setState({ tabIndex: 1, });
}}>
<View /> <View />
</TabBarIOS.Item> </TabBarIOS.Item>
<TabBarIOS.Item <TabBarIOS.Item
icon={require('image!tabnav_settings')} icon={require('image!tabnav_settings')}
selected={this.props.tabIndex === 2} selected={this.state.tabIndex === 2}
onPress={() => { this.props.onTabIndex(2); }}> onPress={() => {
this.props.onTabIndex(2);
this.setState({ tabIndex: 2, });
}}>
<View /> <View />
</TabBarIOS.Item> </TabBarIOS.Item>
</TabBarIOS> </TabBarIOS>
@ -81,12 +100,6 @@ class JumpingNavBar extends React.Component {
} }
var JumpingNavSample = React.createClass({ var JumpingNavSample = React.createClass({
getInitialState: function() {
return {
tabIndex: INIT_ROUTE_INDEX,
};
},
render: function() { render: function() {
return ( return (
<Navigator <Navigator
@ -98,23 +111,19 @@ var JumpingNavSample = React.createClass({
initialRoute={ROUTE_STACK[INIT_ROUTE_INDEX]} initialRoute={ROUTE_STACK[INIT_ROUTE_INDEX]}
initialRouteStack={ROUTE_STACK} initialRouteStack={ROUTE_STACK}
renderScene={this.renderScene} renderScene={this.renderScene}
configureScene={() => ({
...Navigator.SceneConfigs.HorizontalSwipeJump,
})}
navigationBar={ navigationBar={
<JumpingNavBar <JumpingNavBar
ref={(navBar) => { this.navBar = navBar; }}
initTabIndex={INIT_ROUTE_INDEX}
routeStack={ROUTE_STACK} routeStack={ROUTE_STACK}
tabIndex={this.state.tabIndex}
onTabIndex={(index) => { onTabIndex={(index) => {
this.setState({ tabIndex: index }, () => { this._navigator.jumpTo(ROUTE_STACK[index]);
this._navigator.jumpTo(ROUTE_STACK[index]);
});
}} }}
/> />
} }
onWillFocus={(route) => {
this.setState({
tabIndex: ROUTE_STACK.indexOf(route),
});
}}
shouldJumpOnBackstackPop={true}
/> />
); );
}, },

View File

@ -17,6 +17,7 @@
var React = require('react-native'); var React = require('react-native');
var ViewExample = require('./ViewExample'); var ViewExample = require('./ViewExample');
var createExamplePage = require('./createExamplePage');
var { var {
PixelRatio, PixelRatio,
ScrollView, ScrollView,
@ -77,7 +78,7 @@ var NavigatorIOSExample = React.createClass({
{this._renderRow('Push View Example', () => { {this._renderRow('Push View Example', () => {
this.props.navigator.push({ this.props.navigator.push({
title: 'Very Long Custom View Example Title', title: 'Very Long Custom View Example Title',
component: ViewExample, component: createExamplePage(null, ViewExample),
}); });
})} })}
{this._renderRow('Custom Right Button', () => { {this._renderRow('Custom Right Button', () => {

View File

@ -38,7 +38,7 @@ var NavigatorIOSExample = React.createClass({
_previousLeft: 0, _previousLeft: 0,
_previousTop: 0, _previousTop: 0,
_circleStyles: {}, _circleStyles: {},
circle: (null : ?React.Element), circle: (null : ?{ setNativeProps(props: Object): void }),
componentWillMount: function() { componentWillMount: function() {
this._panResponder = PanResponder.create({ this._panResponder = PanResponder.create({

View File

@ -6,18 +6,25 @@
* LICENSE file in the root directory of this source tree. An additional grant * 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. * of patent rights can be found in the PATENTS file in the same directory.
* *
* @providesModule Animation * @providesModule AnimationExperimental
* @flow * @flow
*/ */
'use strict'; 'use strict';
var RCTAnimationManager = require('NativeModules').AnimationManager; var RCTAnimationManager = require('NativeModules').AnimationExperimentalManager;
var AnimationUtils = require('AnimationUtils'); var AnimationUtils = require('AnimationUtils');
type EasingFunction = (t: number) => number; type EasingFunction = (t: number) => number;
var Animation = { /**
Mixin: require('AnimationMixin'), * This is an experimental module that is under development, incomplete,
* potentially buggy, not used in any production apps, and will probably change
* in non-backward compatible ways.
*
* Use at your own risk.
*/
var AnimationExperimental = {
Mixin: require('AnimationExperimentalMixin'),
startAnimation: function( startAnimation: function(
node: any, node: any,
@ -28,7 +35,14 @@ var Animation = {
): number { ): number {
var nodeHandle = +node.getNodeHandle(); var nodeHandle = +node.getNodeHandle();
var easingSample = AnimationUtils.evaluateEasingFunction(duration, easing); var easingSample = AnimationUtils.evaluateEasingFunction(duration, easing);
var tag: number = RCTAnimationManager.startAnimation(nodeHandle, AnimationUtils.allocateTag(), duration, delay, easingSample, properties); var tag: number = RCTAnimationManager.startAnimation(
nodeHandle,
AnimationUtils.allocateTag(),
duration,
delay,
easingSample,
properties
);
return tag; return tag;
}, },
@ -37,4 +51,4 @@ var Animation = {
}, },
}; };
module.exports = Animation; module.exports = AnimationExperimental;

View File

@ -6,19 +6,26 @@
* LICENSE file in the root directory of this source tree. An additional grant * 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. * of patent rights can be found in the PATENTS file in the same directory.
* *
* @providesModule AnimationMixin * @providesModule AnimationExperimentalMixin
* @flow * @flow
*/ */
'use strict'; 'use strict';
var AnimationUtils = require('AnimationUtils'); var AnimationUtils = require('AnimationUtils');
var RCTAnimationManager = require('NativeModules').AnimationManager; var RCTAnimationManager = require('NativeModules').AnimationExperimentalManager;
var invariant = require('invariant'); var invariant = require('invariant');
type EasingFunction = (t: number) => number; type EasingFunction = (t: number) => number;
var AnimationMixin = { /**
* This is an experimental module that is under development, incomplete,
* potentially buggy, not used in any production apps, and will probably change
* in non-backward compatible ways.
*
* Use at your own risk.
*/
var AnimationExperimentalMixin = {
getInitialState: function(): Object { getInitialState: function(): Object {
return {}; return {};
}, },
@ -48,4 +55,4 @@ var AnimationMixin = {
}, },
}; };
module.exports = AnimationMixin; module.exports = AnimationExperimentalMixin;

View File

@ -7,7 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
13BE3DEE1AC21097009241FE /* RCTAnimationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* RCTAnimationManager.m */; }; 13BE3DEE1AC21097009241FE /* RCTAnimationExperimentalManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* RCTAnimationExperimentalManager.m */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
@ -23,9 +23,9 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
134814201AA4EA6300B7C361 /* libRCTAnimation.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTAnimation.a; sourceTree = BUILT_PRODUCTS_DIR; }; 134814201AA4EA6300B7C361 /* libRCTAnimationExperimental.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTAnimationExperimental.a; sourceTree = BUILT_PRODUCTS_DIR; };
13BE3DEC1AC21097009241FE /* RCTAnimationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAnimationManager.h; sourceTree = "<group>"; }; 13BE3DEC1AC21097009241FE /* RCTAnimationExperimentalManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAnimationExperimentalManager.h; sourceTree = "<group>"; };
13BE3DED1AC21097009241FE /* RCTAnimationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAnimationManager.m; sourceTree = "<group>"; }; 13BE3DED1AC21097009241FE /* RCTAnimationExperimentalManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAnimationExperimentalManager.m; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -42,7 +42,7 @@
134814211AA4EA7D00B7C361 /* Products */ = { 134814211AA4EA7D00B7C361 /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
134814201AA4EA6300B7C361 /* libRCTAnimation.a */, 134814201AA4EA6300B7C361 /* libRCTAnimationExperimental.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -50,8 +50,8 @@
58B511D21A9E6C8500147676 = { 58B511D21A9E6C8500147676 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
13BE3DEC1AC21097009241FE /* RCTAnimationManager.h */, 13BE3DEC1AC21097009241FE /* RCTAnimationExperimentalManager.h */,
13BE3DED1AC21097009241FE /* RCTAnimationManager.m */, 13BE3DED1AC21097009241FE /* RCTAnimationExperimentalManager.m */,
134814211AA4EA7D00B7C361 /* Products */, 134814211AA4EA7D00B7C361 /* Products */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
@ -59,9 +59,9 @@
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
58B511DA1A9E6C8500147676 /* RCTAnimation */ = { 58B511DA1A9E6C8500147676 /* RCTAnimationExperimental */ = {
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTAnimation" */; buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTAnimationExperimental" */;
buildPhases = ( buildPhases = (
58B511D71A9E6C8500147676 /* Sources */, 58B511D71A9E6C8500147676 /* Sources */,
58B511D81A9E6C8500147676 /* Frameworks */, 58B511D81A9E6C8500147676 /* Frameworks */,
@ -71,9 +71,9 @@
); );
dependencies = ( dependencies = (
); );
name = RCTAnimation; name = RCTAnimationExperimental;
productName = RCTDataManager; productName = RCTDataManager;
productReference = 134814201AA4EA6300B7C361 /* libRCTAnimation.a */; productReference = 134814201AA4EA6300B7C361 /* libRCTAnimationExperimental.a */;
productType = "com.apple.product-type.library.static"; productType = "com.apple.product-type.library.static";
}; };
/* End PBXNativeTarget section */ /* End PBXNativeTarget section */
@ -90,7 +90,7 @@
}; };
}; };
}; };
buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTAnimation" */; buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTAnimationExperimental" */;
compatibilityVersion = "Xcode 3.2"; compatibilityVersion = "Xcode 3.2";
developmentRegion = English; developmentRegion = English;
hasScannedForEncodings = 0; hasScannedForEncodings = 0;
@ -102,7 +102,7 @@
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";
targets = ( targets = (
58B511DA1A9E6C8500147676 /* RCTAnimation */, 58B511DA1A9E6C8500147676 /* RCTAnimationExperimental */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
@ -112,7 +112,7 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
13BE3DEE1AC21097009241FE /* RCTAnimationManager.m in Sources */, 13BE3DEE1AC21097009241FE /* RCTAnimationExperimentalManager.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -203,7 +203,7 @@
); );
LIBRARY_SEARCH_PATHS = "$(inherited)"; LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC"; OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = RCTAnimation; PRODUCT_NAME = RCTAnimationExperimental;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
}; };
name = Debug; name = Debug;
@ -218,7 +218,7 @@
); );
LIBRARY_SEARCH_PATHS = "$(inherited)"; LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC"; OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = RCTAnimation; PRODUCT_NAME = RCTAnimationExperimental;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
}; };
name = Release; name = Release;
@ -226,7 +226,7 @@
/* End XCBuildConfiguration section */ /* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */ /* Begin XCConfigurationList section */
58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTAnimation" */ = { 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTAnimationExperimental" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
58B511ED1A9E6C8500147676 /* Debug */, 58B511ED1A9E6C8500147676 /* Debug */,
@ -235,7 +235,7 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTAnimation" */ = { 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTAnimationExperimental" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
58B511F01A9E6C8500147676 /* Debug */, 58B511F01A9E6C8500147676 /* Debug */,

View File

@ -12,6 +12,6 @@
#import "RCTBridgeModule.h" #import "RCTBridgeModule.h"
@interface RCTAnimationManager : NSObject <RCTBridgeModule> @interface RCTAnimationExperimentalManager : NSObject <RCTBridgeModule>
@end @end

View File

@ -7,7 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
#import "RCTAnimationManager.h" #import "RCTAnimationExperimentalManager.h"
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@ -20,7 +20,7 @@
#define CG_APPEND(PREFIX, SUFFIX_F, SUFFIX_D) PREFIX##SUFFIX_F #define CG_APPEND(PREFIX, SUFFIX_F, SUFFIX_D) PREFIX##SUFFIX_F
#endif #endif
@implementation RCTAnimationManager @implementation RCTAnimationExperimentalManager
{ {
RCTSparseArray *_animationRegistry; // Main thread only; animation tag -> view tag RCTSparseArray *_animationRegistry; // Main thread only; animation tag -> view tag
} }
@ -65,9 +65,9 @@
{ {
RCT_EXPORT(startAnimation); RCT_EXPORT(startAnimation);
__weak RCTAnimationManager *weakSelf = self; __weak RCTAnimationExperimentalManager *weakSelf = self;
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { [_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
RCTAnimationManager *strongSelf = weakSelf; RCTAnimationExperimentalManager *strongSelf = weakSelf;
UIView *view = viewRegistry[reactTag]; UIView *view = viewRegistry[reactTag];
if (!view) { if (!view) {
@ -182,9 +182,9 @@
{ {
RCT_EXPORT(stopAnimation); RCT_EXPORT(stopAnimation);
__weak RCTAnimationManager *weakSelf = self; __weak RCTAnimationExperimentalManager *weakSelf = self;
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { [_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
RCTAnimationManager *strongSelf = weakSelf; RCTAnimationExperimentalManager *strongSelf = weakSelf;
NSNumber *reactTag = strongSelf->_animationRegistry[animationTag]; NSNumber *reactTag = strongSelf->_animationRegistry[animationTag];
if (!reactTag) return; if (!reactTag) return;

View File

@ -364,10 +364,16 @@ var ScrollResponderMixin = {
/** /**
* This method should be used as the callback to onFocus in a TextInputs' * This method should be used as the callback to onFocus in a TextInputs'
* parent view. Note that any module using this mixin needs to return * parent view. Note that any module using this mixin needs to return
* the parent view's ref in getScrollViewRef() in order to use this method * the parent view's ref in getScrollViewRef() in order to use this method.
* @param {any} nodeHandle The TextInput node handle
* @param {number} additionalOffset The scroll view's top "contentInset".
* Default is 0.
* @param {bool} preventNegativeScrolling Whether to allow pulling the content
* down to make it meet the keyboard's top. Default is false.
*/ */
scrollResponderScrollNativeHandleToKeyboard: function(nodeHandle: any, additionalOffset?: number) { scrollResponderScrollNativeHandleToKeyboard: function(nodeHandle: any, additionalOffset?: number, preventNegativeScrollOffset?: bool) {
this.additionalScrollOffset = additionalOffset || 0; this.additionalScrollOffset = additionalOffset || 0;
this.preventNegativeScrollOffset = !!preventNegativeScrollOffset;
RCTUIManager.measureLayout( RCTUIManager.measureLayout(
nodeHandle, nodeHandle,
this.getNodeHandle(), this.getNodeHandle(),
@ -386,14 +392,23 @@ var ScrollResponderMixin = {
* @param {number} width Width of the text input. * @param {number} width Width of the text input.
* @param {number} height Height of the text input. * @param {number} height Height of the text input.
*/ */
scrollResponderInputMeasureAndScrollToKeyboard: function(left: number, top: number, width: number, height: number) { scrollResponderInputMeasureAndScrollToKeyboard: function(left: number, top: number, width: number, height: number) {
if (this.keyboardWillOpenTo) { if (this.keyboardWillOpenTo) {
var scrollOffsetY = var scrollOffsetY =
top - this.keyboardWillOpenTo.endCoordinates.screenY + height + top - this.keyboardWillOpenTo.endCoordinates.screenY + height +
this.additionalScrollOffset; this.additionalScrollOffset;
// By default, this can scroll with negative offset, pulling the content
// down so that the target component's bottom meets the keyboard's top.
// If requested otherwise, cap the offset at 0 minimum to avoid content
// shifting down.
if (this.preventNegativeScrollOffset) {
scrollOffsetY = Math.max(0, scrollOffsetY);
}
this.scrollResponderScrollTo(0, scrollOffsetY); this.scrollResponderScrollTo(0, scrollOffsetY);
} }
this.additionalOffset = 0; this.additionalOffset = 0;
this.preventNegativeScrollOffset = false;
}, },
scrollResponderTextInputFocusError: function(e: Event) { scrollResponderTextInputFocusError: function(e: Event) {

View File

@ -40,7 +40,7 @@ var SliderIOS = React.createClass({
* Default value is 0. * Default value is 0.
* *
* *This is not a controlled component*, e.g. if you don't update * *This is not a controlled component*, e.g. if you don't update
* the value, the component won't be reset to it's inital value. * the value, the component won't be reset to its inital value.
*/ */
value: PropTypes.number, value: PropTypes.number,
@ -82,6 +82,8 @@ var SliderIOS = React.createClass({
<RCTSlider <RCTSlider
style={[styles.slider, this.props.style]} style={[styles.slider, this.props.style]}
value={this.props.value} value={this.props.value}
maximumValue={this.props.maximumValue}
minimumValue={this.props.minimumValue}
onChange={this._onValueChange} onChange={this._onValueChange}
/> />
); );
@ -94,8 +96,15 @@ var styles = StyleSheet.create({
}, },
}); });
var validAttributes = {
...ReactIOSViewAttributes.UIView,
value: true,
minimumValue: true,
maximumValue: true,
};
var RCTSlider = createReactIOSNativeComponentClass({ var RCTSlider = createReactIOSNativeComponentClass({
validAttributes: merge(ReactIOSViewAttributes.UIView, {value: true}), validAttributes: validAttributes,
uiViewClassName: 'RCTSlider', uiViewClassName: 'RCTSlider',
}); });

View File

@ -217,8 +217,6 @@ var TextInput = React.createClass({
*/ */
onFocus: PropTypes.func, onFocus: PropTypes.func,
/** /**
* (text: string) => void
*
* Callback that is called when the text input's text changes. * Callback that is called when the text input's text changes.
*/ */
onChange: PropTypes.func, onChange: PropTypes.func,

View File

@ -14,7 +14,7 @@
var NativeMethodsMixin = require('NativeMethodsMixin'); var NativeMethodsMixin = require('NativeMethodsMixin');
var React = require('React'); var React = require('React');
var POPAnimation = require('POPAnimation'); var POPAnimation = require('POPAnimation');
var Animation = require('Animation'); var AnimationExperimental = require('AnimationExperimental');
var Touchable = require('Touchable'); var Touchable = require('Touchable');
var merge = require('merge'); var merge = require('merge');
@ -79,7 +79,7 @@ var TouchableBounce = React.createClass({
this.state.animationID = POPAnimation.createSpringAnimation(anim); this.state.animationID = POPAnimation.createSpringAnimation(anim);
this.addAnimation(this.state.animationID, callback); this.addAnimation(this.state.animationID, callback);
} else { } else {
Animation.startAnimation(this, 300, 0, 'easeOutBack', {scaleXY: [value, value]}); AnimationExperimental.startAnimation(this, 300, 0, 'easeOutBack', {scaleXY: [value, value]});
if (fromValue && typeof fromValue === 'function') { if (fromValue && typeof fromValue === 'function') {
callback = fromValue; callback = fromValue;
} }

View File

@ -13,7 +13,6 @@
var React = require('React'); var React = require('React');
var Touchable = require('Touchable'); var Touchable = require('Touchable');
var onlyChild = require('onlyChild'); var onlyChild = require('onlyChild');
/** /**
@ -78,10 +77,8 @@ var TouchableWithoutFeedback = React.createClass({
}, },
render: function(): ReactElement { render: function(): ReactElement {
// Note(vjeux): use cloneWithProps once React has been upgraded
var child = onlyChild(this.props.children);
// Note(avik): remove dynamic typecast once Flow has been upgraded // Note(avik): remove dynamic typecast once Flow has been upgraded
return (React: any).cloneElement(child, { return (React: any).cloneElement(onlyChild(this.props.children), {
accessible: true, accessible: true,
testID: this.props.testID, testID: this.props.testID,
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder, onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
* *
* @providesModule View * @providesModule View
* @flow
*/ */
'use strict'; 'use strict';

View File

@ -32,38 +32,6 @@ var invariant = require('invariant');
var isEmpty = require('isEmpty'); var isEmpty = require('isEmpty');
var warning = require('warning'); var warning = require('warning');
/**
* ListViewDataSource - Provides efficient data processing and access to the
* ListView component. A ListViewDataSource is created with functions for
* extracting data from the input blob, and comparing elements (with default
* implementations for convenience). The input blob can be as simple as an
* array of strings, or an object with rows nested inside section objects.
*
* To update the data in the datasource, use `cloneWithRows` (or
* `cloneWithRowsAndSections` if you care about sections). The data in the
* data source is immutable, so you can't modify it directly. The clone methods
* suck in the new data and compute a diff for each row so ListView knows
* whether to re-render it or not.
*
* In this example, a component receives data in chunks, handled by
* `_onDataArrived`, which concats the new data onto the old data and updates the
* data source. We use `concat` to create a new array - mutating `this._data`,
* e.g. with `this._data.push(newRowData)`, would be an error. `_rowHasChanged`
* understands the shape of the row data and knows how to efficiently compare
* it.
*
* getInitialState: function() {
* var ds = new ListViewDataSource({rowHasChanged: this._rowHasChanged});
* return {ds};
* },
* _onDataArrived(newData) {
* this._data = this._data.concat(newData);
* this.setState({
* ds: this.state.ds.cloneWithRows(this._data)
* });
* }
*/
function defaultGetRowData( function defaultGetRowData(
dataBlob: any, dataBlob: any,
sectionID: number | string, sectionID: number | string,
@ -88,15 +56,58 @@ type ParamType = {
getSectionHeaderData: ?typeof defaultGetSectionHeaderData; getSectionHeaderData: ?typeof defaultGetSectionHeaderData;
} }
/**
* Provides efficient data processing and access to the
* `ListView` component. A `ListViewDataSource` is created with functions for
* extracting data from the input blob, and comparing elements (with default
* implementations for convenience). The input blob can be as simple as an
* array of strings, or an object with rows nested inside section objects.
*
* To update the data in the datasource, use `cloneWithRows` (or
* `cloneWithRowsAndSections` if you care about sections). The data in the
* data source is immutable, so you can't modify it directly. The clone methods
* suck in the new data and compute a diff for each row so ListView knows
* whether to re-render it or not.
*
* In this example, a component receives data in chunks, handled by
* `_onDataArrived`, which concats the new data onto the old data and updates the
* data source. We use `concat` to create a new array - mutating `this._data`,
* e.g. with `this._data.push(newRowData)`, would be an error. `_rowHasChanged`
* understands the shape of the row data and knows how to efficiently compare
* it.
*
* ```
* getInitialState: function() {
* var ds = new ListViewDataSource({rowHasChanged: this._rowHasChanged});
* return {ds};
* },
* _onDataArrived(newData) {
* this._data = this._data.concat(newData);
* this.setState({
* ds: this.state.ds.cloneWithRows(this._data)
* });
* }
* ```
*/
class ListViewDataSource { class ListViewDataSource {
/** /**
* @param {ParamType} params * You can provide custom extraction and `hasChanged` functions for section
*
* You can provide custom extraction and 'hasChanged' functions for section
* headers and rows. If absent, data will be extracted with the * headers and rows. If absent, data will be extracted with the
* `defaultGetRowData` and `defaultGetSectionHeaderData` functions. * `defaultGetRowData` and `defaultGetSectionHeaderData` functions.
* *
* The default extractor expects data of one of the following forms:
*
* { sectionID_1: { rowID_1: <rowData1>, ... }, ... }
*
* or
*
* [ [ <rowData1>, <rowData2>, ... ], ... ]
*
* The constructor takes in a params argument that can contain any of the
* following:
*
* - getRowData(dataBlob, sectionID, rowID); * - getRowData(dataBlob, sectionID, rowID);
* - getSectionHeaderData(dataBlob, sectionID); * - getSectionHeaderData(dataBlob, sectionID);
* - rowHasChanged(prevRowData, nextRowData); * - rowHasChanged(prevRowData, nextRowData);
@ -125,14 +136,25 @@ class ListViewDataSource {
} }
/** /**
* @param {object} dataBlob -- This is an arbitrary blob of data. An extractor * Clones this `ListViewDataSource` with the specified `dataBlob` and
* function was defined at construction time. The default extractor assumes * `rowIdentities`. The `dataBlob` is just an aribitrary blob of data. At
* the data is a plain array or keyed object. * construction an extractor to get the interesting informatoin was defined
*/ * (or the default was used).
cloneWithRows( *
dataBlob: Array<any> | {[key: string]: any}, * The `rowIdentities` is is a 2D array of identifiers for rows.
rowIdentities: ?Array<string> * ie. [['a1', 'a2'], ['b1', 'b2', 'b3'], ...]. If not provided, it's
): ListViewDataSource { * assumed that the keys of the section data are the row identities.
*
* Note: This function does NOT clone the data in this data source. It simply
* passes the functions defined at construction to a new data source with
* the data specified. If you wish to maintain the existing data you must
* handle merging of old and new data separately and then pass that into
* this function as the `dataBlob`.
*/
cloneWithRows(
dataBlob: Array<any> | {[key: string]: any},
rowIdentities: ?Array<string>
): ListViewDataSource {
var rowIds = rowIdentities ? [rowIdentities] : null; var rowIds = rowIdentities ? [rowIdentities] : null;
if (!this._sectionHeaderHasChanged) { if (!this._sectionHeaderHasChanged) {
this._sectionHeaderHasChanged = () => false; this._sectionHeaderHasChanged = () => false;
@ -141,29 +163,20 @@ class ListViewDataSource {
} }
/** /**
* @param {object} dataBlob -- This is an arbitrary blob of data. An extractor * This performs the same function as the `cloneWithRows` function but here
* function was defined at construction time. The default extractor assumes * you also specify what your `sectionIdentities` are. If you don't care
* the data is a nested array or keyed object of the form: * about sections you should safely be able to use `cloneWithRows`.
* *
* { sectionID_1: { rowID_1: <rowData1>, ... }, ... } * `sectionIdentities` is an array of identifiers for sections.
* * ie. ['s1', 's2', ...]. If not provided, it's assumed that the
* or * keys of dataBlob are the section identities.
*
* [ [ <rowData1>, <rowData2>, ... ], ... ]
*
* @param {array} sectionIdentities -- This is an array of identifiers for
* sections. ie. ['s1', 's2', ...]. If not provided, it's assumed that the
* keys of dataBlob are the section identities.
* @param {array} rowIdentities -- This is a 2D array of identifiers for rows.
* ie. [['a1', 'a2'], ['b1', 'b2', 'b3'], ...]. If not provided, it's
* assumed that the keys of the section data are the row identities.
* *
* Note: this returns a new object! * Note: this returns a new object!
*/ */
cloneWithRowsAndSections( cloneWithRowsAndSections(
dataBlob: any, dataBlob: any,
sectionIdentities: ?Array<string>, sectionIdentities: ?Array<string>,
rowIdentities: ?Array<Array<string>> rowIdentities: ?Array<Array<string>>
): ListViewDataSource { ): ListViewDataSource {
invariant( invariant(
typeof this._sectionHeaderHasChanged === 'function', typeof this._sectionHeaderHasChanged === 'function',
@ -205,9 +218,6 @@ class ListViewDataSource {
} }
/** /**
* @param {number} sectionIndex
* @param {number} rowIndex
*
* Returns if the row is dirtied and needs to be rerendered * Returns if the row is dirtied and needs to be rerendered
*/ */
rowShouldUpdate(sectionIndex: number, rowIndex: number): bool { rowShouldUpdate(sectionIndex: number, rowIndex: number): bool {
@ -218,9 +228,6 @@ class ListViewDataSource {
} }
/** /**
* @param {number} sectionIndex
* @param {number} rowIndex
*
* Gets the data required to render the row. * Gets the data required to render the row.
*/ */
getRowData(sectionIndex: number, rowIndex: number): any { getRowData(sectionIndex: number, rowIndex: number): any {
@ -234,8 +241,6 @@ class ListViewDataSource {
} }
/** /**
* @param {number} index
*
* Gets the rowID at index provided if the dataSource arrays were flattened, * Gets the rowID at index provided if the dataSource arrays were flattened,
* or null of out of range indexes. * or null of out of range indexes.
*/ */
@ -252,8 +257,6 @@ class ListViewDataSource {
} }
/** /**
* @param {number} index
*
* Gets the sectionID at index provided if the dataSource arrays were flattened, * Gets the sectionID at index provided if the dataSource arrays were flattened,
* or null for out of range indexes. * or null for out of range indexes.
*/ */
@ -281,8 +284,6 @@ class ListViewDataSource {
} }
/** /**
* @param {number} sectionIndex
*
* Returns if the section header is dirtied and needs to be rerendered * Returns if the section header is dirtied and needs to be rerendered
*/ */
sectionHeaderShouldUpdate(sectionIndex: number): bool { sectionHeaderShouldUpdate(sectionIndex: number): bool {
@ -293,8 +294,6 @@ class ListViewDataSource {
} }
/** /**
* @param {number} sectionIndex
*
* Gets the data required to render the section header * Gets the data required to render the section header
*/ */
getSectionHeaderData(sectionIndex: number): any { getSectionHeaderData(sectionIndex: number): any {

View File

@ -54,8 +54,6 @@ var SCREEN_HEIGHT = Dimensions.get('window').height;
var OFF_SCREEN = {style: {opacity: 0}}; var OFF_SCREEN = {style: {opacity: 0}};
var NAVIGATION_BAR_REF = 'navigationBar_ref';
var __uid = 0; var __uid = 0;
function getuid() { function getuid() {
return __uid++; return __uid++;
@ -94,6 +92,12 @@ var styles = StyleSheet.create({
} }
}); });
var GESTURE_ACTIONS = [
'pop',
'jumpBack',
'jumpForward',
];
/** /**
* Use `Navigator` to transition between different scenes in your app. To * Use `Navigator` to transition between different scenes in your app. To
* accomplish this, provide route objects to the navigator to identify each * accomplish this, provide route objects to the navigator to identify each
@ -314,6 +318,7 @@ var Navigator = React.createClass({
popToRoute: this.popToRoute, popToRoute: this.popToRoute,
popToTop: this.popToTop, popToTop: this.popToTop,
parentNavigator: this.props.navigator, parentNavigator: this.props.navigator,
getCurrentRoutes: this.getCurrentRoutes,
// We want to bubble focused routes to the top navigation stack. If we // We want to bubble focused routes to the top navigation stack. If we
// are a child navigator, this allows us to call props.navigator.on*Focus // are a child navigator, this allows us to call props.navigator.on*Focus
// of the topmost Navigator // of the topmost Navigator
@ -457,15 +462,18 @@ var Navigator = React.createClass({
_completeTransition: function() { _completeTransition: function() {
if (this.spring.getCurrentValue() === 1) { if (this.spring.getCurrentValue() === 1) {
var presentedIndex = this.state.toIndex; var presentedIndex = this.state.toIndex;
this.state.fromIndex = presentedIndex;
this.state.presentedIndex = presentedIndex; this.state.presentedIndex = presentedIndex;
this.state.fromIndex = presentedIndex;
this._emitDidFocus(presentedIndex); this._emitDidFocus(presentedIndex);
this._removePoppedRoutes(); this._removePoppedRoutes();
if (AnimationsDebugModule) { if (AnimationsDebugModule) {
AnimationsDebugModule.stopRecordingFps(Date.now()); AnimationsDebugModule.stopRecordingFps(Date.now());
} }
this._hideOtherScenes(presentedIndex); } else {
this.state.fromIndex = this.state.presentedIndex;
this.state.toIndex = this.state.presentedIndex;
} }
this._hideOtherScenes(presentedIndex);
}, },
_transitionToToIndexWithVelocity: function(v) { _transitionToToIndexWithVelocity: function(v) {
@ -499,6 +507,10 @@ var Navigator = React.createClass({
_emitWillFocus: function(index) { _emitWillFocus: function(index) {
var route = this.state.routeStack[index]; var route = this.state.routeStack[index];
var navBar = this._navBar;
if (navBar && navBar.handleWillFocus) {
navBar.handleWillFocus(route);
}
if (this.props.onWillFocus) { if (this.props.onWillFocus) {
this.props.onWillFocus(route); this.props.onWillFocus(route);
} else if (this.props.navigator && this.props.navigator.onWillFocus) { } else if (this.props.navigator && this.props.navigator.onWillFocus) {
@ -532,95 +544,170 @@ var Navigator = React.createClass({
_handleMoveShouldSetPanResponder: function(e, gestureState) { _handleMoveShouldSetPanResponder: function(e, gestureState) {
var currentRoute = this.state.routeStack[this.state.presentedIndex]; var currentRoute = this.state.routeStack[this.state.presentedIndex];
var animationConfig = this.state.sceneConfigStack[this.state.presentedIndex]; var sceneConfig = this.state.sceneConfigStack[this.state.presentedIndex];
if (!animationConfig.enableGestures) { this._expectingGestureGrant = this._matchGestureAction(sceneConfig.gestures, gestureState);
return false; return !! this._expectingGestureGrant;
} },
var currentLoc = animationConfig.isVertical ? gestureState.moveY : gestureState.moveX;
var travelDist = animationConfig.isVertical ? gestureState.dy : gestureState.dx; _doesGestureOverswipe: function(gestureName) {
var oppositeAxisTravelDist = var wouldOverswipeBack = this.state.presentedIndex <= 0 &&
animationConfig.isVertical ? gestureState.dx : gestureState.dy; (gestureName === 'pop' || gestureName === 'jumpBack');
var moveStartedInRegion = currentLoc < animationConfig.edgeHitWidth; var wouldOverswipeForward = this.state.presentedIndex >= this.state.routeStack.length - 1 &&
var moveTravelledFarEnough = gestureName === 'jumpForward';
travelDist >= animationConfig.gestureDetectMovement && return wouldOverswipeForward || wouldOverswipeBack;
travelDist > oppositeAxisTravelDist * animationConfig.directionRatio;
return (
!this.state.isResponderOnlyToBlockTouches &&
moveStartedInRegion &&
!this.state.isAnimating &&
this.state.presentedIndex > 0 &&
moveTravelledFarEnough
);
}, },
_handlePanResponderGrant: function(e, gestureState) { _handlePanResponderGrant: function(e, gestureState) {
invariant(
this._expectingGestureGrant,
'Responder granted unexpectedly.'
);
this._activeGestureAction = this._expectingGestureGrant;
this._expectingGestureGrant = null;
this.state.isResponderOnlyToBlockTouches = this.state.isAnimating; this.state.isResponderOnlyToBlockTouches = this.state.isAnimating;
if (!this.state.isAnimating) { if (!this.state.isAnimating) {
this.state.fromIndex = this.state.presentedIndex; this.state.fromIndex = this.state.presentedIndex;
this.state.toIndex = this.state.presentedIndex - 1; var gestureSceneDelta = this._deltaForGestureAction(this._activeGestureAction);
this.state.toIndex = this.state.presentedIndex + gestureSceneDelta;
}
},
_deltaForGestureAction: function(gestureAction) {
switch (gestureAction) {
case 'pop':
case 'jumpBack':
return -1;
case 'jumpForward':
return 1;
default:
invariant(false, 'Unsupported gesture action ' + gestureAction);
return;
} }
}, },
_handlePanResponderRelease: function(e, gestureState) { _handlePanResponderRelease: function(e, gestureState) {
var sceneConfig = this.state.sceneConfigStack[this.state.presentedIndex];
var releaseGestureAction = this._activeGestureAction;
this._activeGestureAction = null;
if (this.state.isResponderOnlyToBlockTouches) { if (this.state.isResponderOnlyToBlockTouches) {
this.state.isResponderOnlyToBlockTouches = false; this.state.isResponderOnlyToBlockTouches = false;
return; return;
} }
var animationConfig = this.state.sceneConfigStack[this.state.presentedIndex]; var releaseGesture = sceneConfig.gestures[releaseGestureAction];
var velocity = animationConfig.isVertical ? gestureState.vy : gestureState.vx;
// It's not the real location. There is no *real* location - that's the
// point of the pan gesture.
var pseudoLocation = animationConfig.isVertical ?
gestureState.y0 + gestureState.dy :
gestureState.x0 + gestureState.dx;
var still = Math.abs(velocity) < animationConfig.notMoving;
if (this.spring.getCurrentValue() === 0) { if (this.spring.getCurrentValue() === 0) {
// The spring is at zero, so the gesture is already complete
this.spring.setCurrentValue(0).setAtRest(); this.spring.setCurrentValue(0).setAtRest();
this._completeTransition(); this._completeTransition();
return; return;
} }
var transitionVelocity = var isTravelVertical = releaseGesture.direction === 'top-to-bottom' || releaseGesture.direction === 'bottom-to-top';
still && animationConfig.pastPointOfNoReturn(pseudoLocation) ? animationConfig.snapVelocity : var isTravelInverted = releaseGesture.direction === 'right-to-left' || releaseGesture.direction === 'bottom-to-top';
still && !animationConfig.pastPointOfNoReturn(pseudoLocation) ? -animationConfig.snapVelocity : var velocity, gestureDistance;
clamp(-10, velocity, 10); // What are Rebound UoM? if (isTravelVertical) {
velocity = isTravelInverted ? -gestureState.vy : gestureState.vy;
gestureDistance = isTravelInverted ? -gestureState.dy : gestureState.dy;
} else {
velocity = isTravelInverted ? -gestureState.vx : gestureState.vx;
gestureDistance = isTravelInverted ? -gestureState.dx : gestureState.dx;
}
var transitionVelocity = clamp(-10, velocity, 10);
if (Math.abs(velocity) < releaseGesture.notMoving) {
// The gesture velocity is so slow, is "not moving"
var hasGesturedEnoughToComplete = gestureDistance > releaseGesture.fullDistance * releaseGesture.stillCompletionRatio;
transitionVelocity = hasGesturedEnoughToComplete ? releaseGesture.snapVelocity : -releaseGesture.snapVelocity;
}
this.spring.setOvershootClampingEnabled(true); this.spring.setOvershootClampingEnabled(true);
if (transitionVelocity < 0) { if (transitionVelocity < 0 || this._doesGestureOverswipe(releaseGestureAction)) {
this._transitionToFromIndexWithVelocity(transitionVelocity); this._transitionToFromIndexWithVelocity(transitionVelocity);
} else { } else {
this._manuallyPopBackstack(1);
this._transitionToToIndexWithVelocity(transitionVelocity); this._transitionToToIndexWithVelocity(transitionVelocity);
} }
}, },
_handlePanResponderTerminate: function(e, gestureState) { _handlePanResponderTerminate: function(e, gestureState) {
this._activeGestureAction = null;
this.state.isResponderOnlyToBlockTouches = false; this.state.isResponderOnlyToBlockTouches = false;
this._transitionToFromIndexWithVelocity(0); this._transitionToFromIndexWithVelocity(0);
}, },
_handlePanResponderMove: function(e, gestureState) { _handlePanResponderMove: function(e, gestureState) {
if (!this.state.isResponderOnlyToBlockTouches) { if (!this.state.isResponderOnlyToBlockTouches) {
var animationConfig = this.state.sceneConfigStack[this.state.presentedIndex]; var sceneConfig = this.state.sceneConfigStack[this.state.presentedIndex];
var distance = animationConfig.isVertical ? gestureState.dy : gestureState.dx; var gesture = sceneConfig.gestures[this._activeGestureAction];
var gestureDetectMovement = animationConfig.gestureDetectMovement; var isTravelVertical = gesture.direction === 'top-to-bottom' || gesture.direction === 'bottom-to-top';
var isTravelInverted = gesture.direction === 'right-to-left' || gesture.direction === 'bottom-to-top';
var distance = isTravelVertical ? gestureState.dy : gestureState.dx;
distance = isTravelInverted ? - distance : distance;
var gestureDetectMovement = gesture.gestureDetectMovement;
var nextProgress = (distance - gestureDetectMovement) / var nextProgress = (distance - gestureDetectMovement) /
(animationConfig.screenDimension - gestureDetectMovement); (gesture.fullDistance - gestureDetectMovement);
if (this._doesGestureOverswipe(this._activeGestureAction)) {
var frictionConstant = gesture.overswipe.frictionConstant;
var frictionByDistance = gesture.overswipe.frictionByDistance;
var frictionRatio = 1 / ((frictionConstant) + (Math.abs(nextProgress) * frictionByDistance));
nextProgress *= frictionRatio;
}
this.spring.setCurrentValue(clamp(0, nextProgress, 1)); this.spring.setCurrentValue(clamp(0, nextProgress, 1));
} }
}, },
_matchGestureAction: function(gestures, gestureState) {
if (!gestures) {
return null;
}
if (this.state.isResponderOnlyToBlockTouches || this.state.isAnimating) {
return null;
}
var matchedGesture = null;
GESTURE_ACTIONS.some((gestureName) => {
var gesture = gestures[gestureName];
if (!gesture) {
return;
}
if (gesture.overswipe == null && this._doesGestureOverswipe(gestureName)) {
// cannot swipe past first or last scene without overswiping
return false;
}
var isTravelVertical = gesture.direction === 'top-to-bottom' || gesture.direction === 'bottom-to-top';
var isTravelInverted = gesture.direction === 'right-to-left' || gesture.direction === 'bottom-to-top';
var currentLoc = isTravelVertical ? gestureState.moveY : gestureState.moveX;
var travelDist = isTravelVertical ? gestureState.dy : gestureState.dx;
var oppositeAxisTravelDist =
isTravelVertical ? gestureState.dx : gestureState.dy;
if (isTravelInverted) {
currentLoc = -currentLoc;
travelDist = -travelDist;
oppositeAxisTravelDist = -oppositeAxisTravelDist;
}
var moveStartedInRegion = gesture.edgeHitWidth == null ||
currentLoc < gesture.edgeHitWidth;
var moveTravelledFarEnough =
travelDist >= gesture.gestureDetectMovement &&
travelDist > oppositeAxisTravelDist * gesture.directionRatio;
if (moveStartedInRegion && moveTravelledFarEnough) {
matchedGesture = gestureName;
return true;
}
});
return matchedGesture;
},
_transitionSceneStyle: function(fromIndex, toIndex, progress, index) { _transitionSceneStyle: function(fromIndex, toIndex, progress, index) {
var viewAtIndex = this.refs['scene_' + index]; var viewAtIndex = this.refs['scene_' + index];
if (viewAtIndex === null || viewAtIndex === undefined) { if (viewAtIndex === null || viewAtIndex === undefined) {
return; return;
} }
// Use toIndex animation when we move forwards. Use fromIndex when we move back // Use toIndex animation when we move forwards. Use fromIndex when we move back
var animationIndex = this.state.presentedIndex < toIndex ? toIndex : fromIndex; var sceneConfigIndex = this.state.presentedIndex < toIndex ? toIndex : fromIndex;
var animationConfig = this.state.sceneConfigStack[animationIndex]; var sceneConfig = this.state.sceneConfigStack[sceneConfigIndex];
// this happens for overswiping when there is no scene at toIndex
if (!sceneConfig) {
sceneConfig = this.state.sceneConfigStack[sceneConfigIndex - 1];
}
var styleToUse = {}; var styleToUse = {};
var useFn = index < fromIndex || index < toIndex ? var useFn = index < fromIndex || index < toIndex ?
animationConfig.interpolators.out : sceneConfig.animationInterpolators.out :
animationConfig.interpolators.into; sceneConfig.animationInterpolators.into;
var directionAdjustedProgress = fromIndex < toIndex ? progress : 1 - progress; var directionAdjustedProgress = fromIndex < toIndex ? progress : 1 - progress;
var didChange = useFn(styleToUse, directionAdjustedProgress); var didChange = useFn(styleToUse, directionAdjustedProgress);
if (didChange) { if (didChange) {
@ -631,7 +718,7 @@ var Navigator = React.createClass({
_transitionBetween: function(fromIndex, toIndex, progress) { _transitionBetween: function(fromIndex, toIndex, progress) {
this._transitionSceneStyle(fromIndex, toIndex, progress, fromIndex); this._transitionSceneStyle(fromIndex, toIndex, progress, fromIndex);
this._transitionSceneStyle(fromIndex, toIndex, progress, toIndex); this._transitionSceneStyle(fromIndex, toIndex, progress, toIndex);
var navBar = this.refs[NAVIGATION_BAR_REF]; var navBar = this._navBar;
if (navBar && navBar.updateProgress) { if (navBar && navBar.updateProgress) {
navBar.updateProgress(progress, fromIndex, toIndex); navBar.updateProgress(progress, fromIndex, toIndex);
} }
@ -912,6 +999,10 @@ var Navigator = React.createClass({
} }
}, },
getCurrentRoutes: function() {
return this.state.routeStack;
},
_onItemRef: function(itemId, ref) { _onItemRef: function(itemId, ref) {
this._itemRefs[itemId] = ref; this._itemRefs[itemId] = ref;
var itemIndex = this.state.idStack.indexOf(itemId); var itemIndex = this.state.idStack.indexOf(itemId);
@ -989,7 +1080,7 @@ var Navigator = React.createClass({
return null; return null;
} }
return React.cloneElement(this.props.navigationBar, { return React.cloneElement(this.props.navigationBar, {
ref: NAVIGATION_BAR_REF, ref: (navBar) => { this._navBar = navBar; },
navigator: this.navigatorActions, navigator: this.navigatorActions,
navState: this.state, navState: this.state,
}); });

View File

@ -30,7 +30,6 @@ var Dimensions = require('Dimensions');
var PixelRatio = require('PixelRatio'); var PixelRatio = require('PixelRatio');
var buildStyleInterpolator = require('buildStyleInterpolator'); var buildStyleInterpolator = require('buildStyleInterpolator');
var merge = require('merge');
var SCREEN_WIDTH = Dimensions.get('window').width; var SCREEN_WIDTH = Dimensions.get('window').width;
var SCREEN_HEIGHT = Dimensions.get('window').height; var SCREEN_HEIGHT = Dimensions.get('window').height;
@ -220,32 +219,12 @@ var FromTheFront = {
}, },
}; };
var BaseOverswipeConfig = {
var Interpolators = { frictionConstant: 1,
Vertical: { frictionByDistance: 1.5,
into: buildStyleInterpolator(FromTheFront),
out: buildStyleInterpolator(ToTheBack),
},
Horizontal: {
into: buildStyleInterpolator(FromTheRight),
out: buildStyleInterpolator(ToTheLeft),
},
}; };
var BaseLeftToRightGesture = {
// These are meant to mimic iOS default behavior
var PastPointOfNoReturn = {
horizontal: function(location) {
return location > SCREEN_WIDTH * 3 / 5;
},
vertical: function(location) {
return location > SCREEN_HEIGHT * 3 / 5;
},
};
var BaseConfig = {
// When false, all gestures are ignored for this scene
enableGestures: true,
// How far the swipe must drag to start transitioning // How far the swipe must drag to start transitioning
gestureDetectMovement: 2, gestureDetectMovement: 2,
@ -253,48 +232,88 @@ var BaseConfig = {
// Amplitude of release velocity that is considered still // Amplitude of release velocity that is considered still
notMoving: 0.3, notMoving: 0.3,
// Velocity to start at when transitioning without gesture
defaultTransitionVelocity: 1.5,
// Fraction of directional move required. // Fraction of directional move required.
directionRatio: 0.66, directionRatio: 0.66,
// Velocity to transition with when the gesture release was "not moving" // Velocity to transition with when the gesture release was "not moving"
snapVelocity: 2, snapVelocity: 2,
// Region that can trigger swipe. iOS default is 30px from the left edge
edgeHitWidth: 30,
// Ratio of gesture completion when non-velocity release will cause action
stillCompletionRatio: 3 / 5,
fullDistance: SCREEN_WIDTH,
direction: 'left-to-right',
};
var BaseRightToLeftGesture = {
...BaseLeftToRightGesture,
direction: 'right-to-left',
};
var BaseConfig = {
// A list of all gestures that are enabled on this scene
gestures: {
pop: BaseLeftToRightGesture,
},
// Rebound spring parameters when transitioning FROM this scene // Rebound spring parameters when transitioning FROM this scene
springFriction: 26, springFriction: 26,
springTension: 200, springTension: 200,
// Defaults for horizontal transitioning: // Velocity to start at when transitioning without gesture
defaultTransitionVelocity: 1.5,
isVertical: false, // Animation interpolators for horizontal transitioning:
screenDimension: SCREEN_WIDTH, animationInterpolators: {
into: buildStyleInterpolator(FromTheRight),
// Region that can trigger swipe. iOS default is 30px from the left edge out: buildStyleInterpolator(ToTheLeft),
edgeHitWidth: 30, },
// Point at which a non-velocity release will cause nav pop
pastPointOfNoReturn: PastPointOfNoReturn.horizontal,
// Animation interpolators for this transition
interpolators: Interpolators.Horizontal,
}; };
var NavigatorSceneConfigs = { var NavigatorSceneConfigs = {
PushFromRight: merge(BaseConfig, { PushFromRight: {
...BaseConfig,
// We will want to customize this soon // We will want to customize this soon
}), },
FloatFromRight: merge(BaseConfig, { FloatFromRight: {
...BaseConfig,
// We will want to customize this soon // We will want to customize this soon
}), },
FloatFromBottom: merge(BaseConfig, { FloatFromBottom: {
edgeHitWidth: 150, ...BaseConfig,
interpolators: Interpolators.Vertical, gestures: {
isVertical: true, pop: {
pastPointOfNoReturn: PastPointOfNoReturn.vertical, ...BaseLeftToRightGesture,
screenDimension: SCREEN_HEIGHT, edgeHitWidth: 150,
}), direction: 'top-to-bottom',
fullDistance: SCREEN_HEIGHT,
}
},
animationInterpolators: {
into: buildStyleInterpolator(FromTheFront),
out: buildStyleInterpolator(ToTheBack),
},
},
HorizontalSwipeJump: {
...BaseConfig,
gestures: {
jumpBack: {
...BaseLeftToRightGesture,
overswipe: BaseOverswipeConfig,
edgeHitWidth: null,
},
jumpForward: {
...BaseRightToLeftGesture,
overswipe: BaseOverswipeConfig,
edgeHitWidth: null,
},
}
}
}; };
module.exports = NavigatorSceneConfigs; module.exports = NavigatorSceneConfigs;

View File

@ -1,70 +0,0 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule Portal
* @flow
*/
'use strict';
var React = require('React');
var StyleSheet = require('StyleSheet');
var View = require('View');
var _portalRef: any;
/*
* A container that renders all the modals on top of everything else in the application.
*
* Portal makes it possible for application code to pass modal views all the way up to
* the root element created in `renderApplication`.
*
* Never use `<Portal>` in your code. There is only one Portal instance rendered
* by the top-level `renderApplication`.
*/
var Portal = React.createClass({
statics: {
showModal: function(component) {
if (!_portalRef) {
console.error('Calling showModal but no Portal has been rendered');
return;
}
_portalRef.setState({modal: component});
},
closeModal: function() {
if (!_portalRef) {
console.error('Calling closeModal but no Portal has been rendered');
return;
}
_portalRef.setState({modal: null});
},
},
getInitialState: function() {
return {modal: (null: any)};
},
render: function() {
_portalRef = this;
if (!this.state.modal) {
return <View />;
}
return (
<View style={styles.modalsContainer}>
{this.state.modal}
</View>
);
}
});
var styles = StyleSheet.create({
modalsContainer: {
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0,
},
});
module.exports = Portal;

View File

@ -11,10 +11,7 @@
*/ */
'use strict'; 'use strict';
var Portal = require('Portal');
var React = require('React'); var React = require('React');
var StyleSheet = require('StyleSheet');
var View = require('View');
var invariant = require('invariant'); var invariant = require('invariant');
@ -28,26 +25,11 @@ function renderApplication<D, P, S>(
'Expect to have a valid rootTag, instead got ', rootTag 'Expect to have a valid rootTag, instead got ', rootTag
); );
React.render( React.render(
<View style={styles.appContainer}> <RootComponent
<RootComponent {...initialProps}
{...initialProps} />,
/>
<Portal />
</View>,
rootTag rootTag
); );
} }
var styles = StyleSheet.create({
// This is needed so the application covers the whole screen
// and therefore the contents of the Portal are not clipped.
appContainer: {
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0,
},
});
module.exports = renderApplication; module.exports = renderApplication;

View File

@ -20,32 +20,28 @@ var DEFAULT_BUTTON = {
}; };
/** /**
* AlertIOS manages native iOS alerts, option sheets, and share dialogs * Launches an alert dialog with the specified title and message.
*
* Optionally provide a list of buttons. Tapping any button will fire the
* respective onPress callback and dismiss the alert. By default, the only
* button will be an 'OK' button
*
* The last button in the list will be considered the 'Primary' button and
* it will appear bold.
*
* ```
* AlertIOS.alert(
* 'Foo Title',
* 'My Alert Msg',
* [
* {text: 'Foo', onPress: () => console.log('Foo Pressed!')},
* {text: 'Bar', onPress: () => console.log('Bar Pressed!')},
* ]
* )}
* ```
*/ */
class AlertIOS { class AlertIOS {
/**
* Launches an alert dialog with the specified title and message.
*
* Optionally provide a list of buttons. Tapping any button will fire the
* respective onPress callback and dismiss the alert. By default, the only
* button will be an 'OK' button
*
* The last button in the list will be considered the 'Primary' button and
* it will appear bold.
*
* ```
* AlertIOS.alert(
* 'Foo Title',
* 'My Alert Msg',
* [
* {text: 'Foo', onPress: () => console.log('Foo Pressed!')},
* {text: 'Bar', onPress: () => console.log('Bar Pressed!')},
* ]
* )}
* ```
*/
static alert( static alert(
title: ?string, title: ?string,
message?: ?string, message?: ?string,

View File

@ -41,7 +41,6 @@ var ReactNative = Object.assign(Object.create(require('React')), {
// APIs // APIs
AlertIOS: require('AlertIOS'), AlertIOS: require('AlertIOS'),
Animation: require('Animation'),
AppRegistry: require('AppRegistry'), AppRegistry: require('AppRegistry'),
AppStateIOS: require('AppStateIOS'), AppStateIOS: require('AppStateIOS'),
AsyncStorage: require('AsyncStorage'), AsyncStorage: require('AsyncStorage'),

View File

@ -44,9 +44,9 @@ Pod::Spec.new do |s|
ss.preserve_paths = "Libraries/AdSupport/*.js" ss.preserve_paths = "Libraries/AdSupport/*.js"
end end
s.subspec 'RCTAnimation' do |ss| s.subspec 'RCTAnimationExperimental' do |ss|
ss.dependency 'React/Core' ss.dependency 'React/Core'
ss.source_files = "Libraries/Animation/*.{h,m}" ss.source_files = "Libraries/Animation/RCTAnimationExperimental*.{h,m}"
ss.preserve_paths = "Libraries/Animation/*.js" ss.preserve_paths = "Libraries/Animation/*.js"
end end

View File

@ -99,7 +99,7 @@ middleware. Takes the following options:
* `projectRoots` array (required): Is the roots where your JavaScript * `projectRoots` array (required): Is the roots where your JavaScript
file will exist file will exist
* `blacklistRE` regexp: Is a pattern to ignore certain paths from the * `blacklistRE` regexp: Is a patter to ignore certain paths from the
packager packager
* `polyfillModuleName` array: Paths to polyfills you want to be * `polyfillModuleName` array: Paths to polyfills you want to be
included at the start of the bundle included at the start of the bundle

View File

@ -13,7 +13,7 @@ jest
.dontMock('path') .dontMock('path')
.dontMock('absolute-path') .dontMock('absolute-path')
.dontMock('../docblock') .dontMock('../docblock')
.dontMock('../../requirePattern') .dontMock('../../replacePatterns')
.setMock('../../../ModuleDescriptor', function(data) {return data;}); .setMock('../../../ModuleDescriptor', function(data) {return data;});
describe('DependencyGraph', function() { describe('DependencyGraph', function() {
@ -64,7 +64,7 @@ describe('DependencyGraph', function() {
}); });
}); });
pit('should get dependencies', function() { pit('should get dependencies with deprecated assets', function() {
var root = '/root'; var root = '/root';
fs.__setMockFilesystem({ fs.__setMockFilesystem({
'root': { 'root': {
@ -83,7 +83,7 @@ describe('DependencyGraph', function() {
var dgraph = new DependencyGraph({ var dgraph = new DependencyGraph({
roots: [root], roots: [root],
fileWatcher: fileWatcher, fileWatcher: fileWatcher,
assetRoots: ['/root/imgs'] assetRoots_DEPRECATED: ['/root/imgs'],
}); });
return dgraph.load().then(function() { return dgraph.load().then(function() {
expect(dgraph.getOrderedDependencies('/root/index.js')) expect(dgraph.getOrderedDependencies('/root/index.js'))
@ -98,6 +98,97 @@ describe('DependencyGraph', function() {
}); });
}); });
pit('should get dependencies with relative assets', function() {
var root = '/root';
fs.__setMockFilesystem({
'root': {
'index.js': [
'/**',
' * @providesModule index',
' */',
'require("./imgs/a.png")'
].join('\n'),
'imgs': {
'a.png': ''
},
'package.json': JSON.stringify({
name: 'rootPackage'
}),
}
});
var dgraph = new DependencyGraph({
roots: [root],
fileWatcher: fileWatcher,
});
return dgraph.load().then(function() {
expect(dgraph.getOrderedDependencies('/root/index.js'))
.toEqual([
{
id: 'index',
altId: 'rootPackage/index',
path: '/root/index.js',
dependencies: ['./imgs/a.png']
},
{ id: 'rootPackage/imgs/a.png',
path: '/root/imgs/a.png',
dependencies: [],
isAsset: true
},
]);
});
});
pit('Deprecated and relative assets can live together', function() {
var root = '/root';
fs.__setMockFilesystem({
'root': {
'index.js': [
'/**',
' * @providesModule index',
' */',
'require("./imgs/a.png")',
'require("image!a")',
].join('\n'),
'imgs': {
'a.png': ''
},
'package.json': JSON.stringify({
name: 'rootPackage'
}),
}
});
var dgraph = new DependencyGraph({
roots: [root],
fileWatcher: fileWatcher,
assetRoots_DEPRECATED: ['/root/imgs'],
});
return dgraph.load().then(function() {
expect(dgraph.getOrderedDependencies('/root/index.js'))
.toEqual([
{
id: 'index',
altId: 'rootPackage/index',
path: '/root/index.js',
dependencies: ['./imgs/a.png', 'image!a']
},
{
id: 'rootPackage/imgs/a.png',
path: '/root/imgs/a.png',
dependencies: [],
isAsset: true
},
{
id: 'image!a',
path: '/root/imgs/a.png',
dependencies: [],
isAsset: true
},
]);
});
});
pit('should get recursive dependencies', function() { pit('should get recursive dependencies', function() {
var root = '/root'; var root = '/root';
fs.__setMockFilesystem({ fs.__setMockFilesystem({
@ -821,7 +912,7 @@ describe('DependencyGraph', function() {
}); });
}); });
pit('updates module dependencies on asset add', function() { pit('updates module dependencies on deprecated asset add', function() {
var root = '/root'; var root = '/root';
var filesystem = fs.__setMockFilesystem({ var filesystem = fs.__setMockFilesystem({
'root': { 'root': {
@ -836,7 +927,7 @@ describe('DependencyGraph', function() {
var dgraph = new DependencyGraph({ var dgraph = new DependencyGraph({
roots: [root], roots: [root],
assetRoots: [root], assetRoots_DEPRECATED: [root],
assetExts: ['png'], assetExts: ['png'],
fileWatcher: fileWatcher fileWatcher: fileWatcher
}); });
@ -870,6 +961,57 @@ describe('DependencyGraph', function() {
}); });
}); });
pit('updates module dependencies on relative asset add', function() {
var root = '/root';
var filesystem = fs.__setMockFilesystem({
'root': {
'index.js': [
'/**',
' * @providesModule index',
' */',
'require("./foo.png")'
].join('\n'),
'package.json': JSON.stringify({
name: 'aPackage'
}),
},
});
var dgraph = new DependencyGraph({
roots: [root],
assetExts: ['png'],
fileWatcher: fileWatcher
});
return dgraph.load().then(function() {
expect(dgraph.getOrderedDependencies('/root/index.js'))
.toEqual([
{ id: 'index', altId: 'aPackage/index',
path: '/root/index.js',
dependencies: ['./foo.png']
}
]);
filesystem.root['foo.png'] = '';
triggerFileChange('add', 'foo.png', root);
return dgraph.load().then(function() {
expect(dgraph.getOrderedDependencies('/root/index.js'))
.toEqual([
{ id: 'index', altId: 'aPackage/index',
path: '/root/index.js',
dependencies: ['./foo.png']
},
{ id: 'aPackage/foo.png',
path: '/root/foo.png',
dependencies: [],
isAsset: true,
},
]);
});
});
});
pit('runs changes through ignore filter', function() { pit('runs changes through ignore filter', function() {
var root = '/root'; var root = '/root';
var filesystem = fs.__setMockFilesystem({ var filesystem = fs.__setMockFilesystem({

View File

@ -12,7 +12,7 @@ var ModuleDescriptor = require('../../ModuleDescriptor');
var Promise = require('bluebird'); var Promise = require('bluebird');
var fs = require('fs'); var fs = require('fs');
var docblock = require('./docblock'); var docblock = require('./docblock');
var requirePattern = require('../requirePattern'); var replacePatterns = require('../replacePatterns');
var path = require('path'); var path = require('path');
var isAbsolutePath = require('absolute-path'); var isAbsolutePath = require('absolute-path');
var debug = require('debug')('DependecyGraph'); var debug = require('debug')('DependecyGraph');
@ -37,7 +37,7 @@ var validateOpts = declareOpts({
type: 'object', type: 'object',
required: true, required: true,
}, },
assetRoots: { assetRoots_DEPRECATED: {
type: 'array', type: 'array',
default: [], default: [],
}, },
@ -51,7 +51,7 @@ function DependecyGraph(options) {
var opts = validateOpts(options); var opts = validateOpts(options);
this._roots = opts.roots; this._roots = opts.roots;
this._assetRoots = opts.assetRoots; this._assetRoots_DEPRECATED = opts.assetRoots_DEPRECATED;
this._assetExts = opts.assetExts; this._assetExts = opts.assetExts;
this._ignoreFilePath = opts.ignoreFilePath; this._ignoreFilePath = opts.ignoreFilePath;
this._fileWatcher = options.fileWatcher; this._fileWatcher = options.fileWatcher;
@ -64,6 +64,10 @@ function DependecyGraph(options) {
this._moduleById = Object.create(null); this._moduleById = Object.create(null);
this._debugUpdateEvents = []; this._debugUpdateEvents = [];
this._moduleExtPattern = new RegExp(
'.' + ['js'].concat(this._assetExts).join('|') + '$'
);
// Kick off the search process to precompute the dependency graph. // Kick off the search process to precompute the dependency graph.
this._init(); this._init();
} }
@ -75,7 +79,7 @@ DependecyGraph.prototype.load = function() {
this._loading = Promise.all([ this._loading = Promise.all([
this._search(), this._search(),
this._buildAssetMap(), this._buildAssetMap_DEPRECATED(),
]); ]);
return this._loading; return this._loading;
@ -147,15 +151,15 @@ DependecyGraph.prototype.resolveDependency = function(
fromModule, fromModule,
depModuleId depModuleId
) { ) {
if (this._assetMap != null) { if (this._assetMap_DEPRECATED != null) {
// Process asset requires.
var assetMatch = depModuleId.match(/^image!(.+)/); var assetMatch = depModuleId.match(/^image!(.+)/);
// Process DEPRECATED global asset requires.
if (assetMatch && assetMatch[1]) { if (assetMatch && assetMatch[1]) {
if (!this._assetMap[assetMatch[1]]) { if (!this._assetMap_DEPRECATED[assetMatch[1]]) {
debug('WARINING: Cannot find asset:', assetMatch[1]); debug('WARINING: Cannot find asset:', assetMatch[1]);
return null; return null;
} }
return this._assetMap[assetMatch[1]]; return this._assetMap_DEPRECATED[assetMatch[1]];
} }
} }
@ -218,7 +222,11 @@ DependecyGraph.prototype.resolveDependency = function(
// fromModule.path: /x/y/z // fromModule.path: /x/y/z
// modulePath: /x/y/a/b // modulePath: /x/y/a/b
var dir = path.dirname(fromModule.path); var dir = path.dirname(fromModule.path);
modulePath = withExtJs(path.join(dir, depModuleId)); modulePath = path.join(dir, depModuleId);
if (this._assetExts.indexOf(extname(modulePath)) === -1) {
modulePath = withExtJs(modulePath);
}
dep = this._graph[modulePath]; dep = this._graph[modulePath];
@ -287,7 +295,7 @@ DependecyGraph.prototype._search = function() {
return false; return false;
} }
return filePath.match(/\.js$/); return filePath.match(self._moduleExtPattern);
}); });
var processing = self._findAndProcessPackage(files, dir) var processing = self._findAndProcessPackage(files, dir)
@ -370,11 +378,21 @@ DependecyGraph.prototype._removePackageFromIndices = function(packageJson) {
* Parse a module and update indices. * Parse a module and update indices.
*/ */
DependecyGraph.prototype._processModule = function(modulePath) { DependecyGraph.prototype._processModule = function(modulePath) {
var moduleData = { path: path.resolve(modulePath) };
var module;
if (this._assetExts.indexOf(extname(modulePath)) > -1) {
moduleData.id = this._lookupName(modulePath);
moduleData.isAsset = true;
moduleData.dependencies = [];
module = Promise.resolve(new ModuleDescriptor(moduleData));
this._updateGraphWithModule(module);
}
var self = this; var self = this;
return readFile(modulePath, 'utf8') return readFile(modulePath, 'utf8')
.then(function(content) { .then(function(content) {
var moduleDocBlock = docblock.parseAsObject(content); var moduleDocBlock = docblock.parseAsObject(content);
var moduleData = { path: path.resolve(modulePath) };
if (moduleDocBlock.providesModule || moduleDocBlock.provides) { if (moduleDocBlock.providesModule || moduleDocBlock.provides) {
moduleData.id = moduleData.id =
moduleDocBlock.providesModule || moduleDocBlock.provides; moduleDocBlock.providesModule || moduleDocBlock.provides;
@ -387,7 +405,7 @@ DependecyGraph.prototype._processModule = function(modulePath) {
} }
moduleData.dependencies = extractRequires(content); moduleData.dependencies = extractRequires(content);
var module = new ModuleDescriptor(moduleData); module = new ModuleDescriptor(moduleData);
self._updateGraphWithModule(module); self._updateGraphWithModule(module);
return module; return module;
}); });
@ -497,8 +515,8 @@ DependecyGraph.prototype._processFileChange = function(
this._debugUpdateEvents.push({event: eventType, path: filePath}); this._debugUpdateEvents.push({event: eventType, path: filePath});
if (this._assetExts.indexOf(extname(filePath)) > -1) { if (this._assetExts.indexOf(extname(filePath)) > -1) {
this._processAssetChange(eventType, absPath); this._processAssetChange_DEPRECATED(eventType, absPath);
return; // Fall through because new-style assets are actually modules.
} }
var isPackage = path.basename(filePath) === 'package.json'; var isPackage = path.basename(filePath) === 'package.json';
@ -554,27 +572,28 @@ DependecyGraph.prototype._getAbsolutePath = function(filePath) {
return null; return null;
}; };
DependecyGraph.prototype._buildAssetMap = function() { DependecyGraph.prototype._buildAssetMap_DEPRECATED = function() {
if (this._assetRoots == null || this._assetRoots.length === 0) { if (this._assetRoots_DEPRECATED == null ||
this._assetRoots_DEPRECATED.length === 0) {
return Promise.resolve(); return Promise.resolve();
} }
this._assetMap = Object.create(null); this._assetMap_DEPRECATED = Object.create(null);
return buildAssetMap( return buildAssetMap_DEPRECATED(
this._assetRoots, this._assetRoots_DEPRECATED,
this._processAsset.bind(this) this._processAsset_DEPRECATED.bind(this)
); );
}; };
DependecyGraph.prototype._processAsset = function(file) { DependecyGraph.prototype._processAsset_DEPRECATED = function(file) {
var ext = extname(file); var ext = extname(file);
if (this._assetExts.indexOf(ext) !== -1) { if (this._assetExts.indexOf(ext) !== -1) {
var name = assetName(file, ext); var name = assetName(file, ext);
if (this._assetMap[name] != null) { if (this._assetMap_DEPRECATED[name] != null) {
debug('Conflcting assets', name); debug('Conflcting assets', name);
} }
this._assetMap[name] = new ModuleDescriptor({ this._assetMap_DEPRECATED[name] = new ModuleDescriptor({
id: 'image!' + name, id: 'image!' + name,
path: path.resolve(file), path: path.resolve(file),
isAsset: true, isAsset: true,
@ -583,18 +602,18 @@ DependecyGraph.prototype._processAsset = function(file) {
} }
}; };
DependecyGraph.prototype._processAssetChange = function(eventType, file) { DependecyGraph.prototype._processAssetChange_DEPRECATED = function(eventType, file) {
if (this._assetMap == null) { if (this._assetMap_DEPRECATED == null) {
return; return;
} }
var name = assetName(file, extname(file)); var name = assetName(file, extname(file));
if (eventType === 'change' || eventType === 'delete') { if (eventType === 'change' || eventType === 'delete') {
delete this._assetMap[name]; delete this._assetMap_DEPRECATED[name];
} }
if (eventType === 'change' || eventType === 'add') { if (eventType === 'change' || eventType === 'add') {
this._processAsset(file); this._processAsset_DEPRECATED(file);
} }
}; };
@ -609,7 +628,11 @@ function extractRequires(code) {
code code
.replace(blockCommentRe, '') .replace(blockCommentRe, '')
.replace(lineCommentRe, '') .replace(lineCommentRe, '')
.replace(requirePattern, function(match, _, dep) { .replace(replacePatterns.IMPORT_RE, function(match, pre, quot, dep, post) {
deps.push(dep);
return match;
})
.replace(replacePatterns.REQUIRE_RE, function(match, pre, quot, dep, post) {
deps.push(dep); deps.push(dep);
}); });
@ -669,7 +692,7 @@ function readAndStatDir(dir) {
* Given a list of roots and list of extensions find all the files in * Given a list of roots and list of extensions find all the files in
* the directory with that extension and build a map of those assets. * the directory with that extension and build a map of those assets.
*/ */
function buildAssetMap(roots, processAsset) { function buildAssetMap_DEPRECATED(roots, processAsset) {
var queue = roots.slice(0); var queue = roots.slice(0);
function search() { function search() {

View File

@ -10,7 +10,7 @@
jest.dontMock('../') jest.dontMock('../')
.dontMock('q') .dontMock('q')
.dontMock('../requirePattern') .dontMock('../replacePatterns')
.setMock('../../ModuleDescriptor', function(data) {return data;}); .setMock('../../ModuleDescriptor', function(data) {return data;});
var Promise = require('bluebird'); var Promise = require('bluebird');
@ -228,13 +228,148 @@ describe('HasteDependencyResolver', function() {
var depGraph = depResolver._depGraph; var depGraph = depResolver._depGraph;
var dependencies = ['x', 'y', 'z', 'a', 'b']; var dependencies = ['x', 'y', 'z', 'a', 'b'];
/*eslint-disable */
var code = [ var code = [
"import'x';",
"import 'x';",
"import 'x' ;",
"import Default from 'x';",
"import * as All from 'x';",
"import {} from 'x';",
"import { } from 'x';",
"import {Foo} from 'x';",
"import { Foo } from 'x';",
"import { Foo, } from 'x';",
"import {Foo as Bar} from 'x';",
"import { Foo as Bar } from 'x';",
"import { Foo as Bar, } from 'x';",
"import { Foo, Bar } from 'x';",
"import { Foo, Bar, } from 'x';",
"import { Foo as Bar, Baz } from 'x';",
"import { Foo as Bar, Baz, } from 'x';",
"import { Foo, Bar as Baz } from 'x';",
"import { Foo, Bar as Baz, } from 'x';",
"import { Foo as Bar, Baz as Qux } from 'x';",
"import { Foo as Bar, Baz as Qux, } from 'x';",
"import { Foo, Bar, Baz } from 'x';",
"import { Foo, Bar, Baz, } from 'x';",
"import { Foo as Bar, Baz, Qux } from 'x';",
"import { Foo as Bar, Baz, Qux, } from 'x';",
"import { Foo, Bar as Baz, Qux } from 'x';",
"import { Foo, Bar as Baz, Qux, } from 'x';",
"import { Foo, Bar, Baz as Qux } from 'x';",
"import { Foo, Bar, Baz as Qux, } from 'x';",
"import { Foo as Bar, Baz as Qux, Norf } from 'x';",
"import { Foo as Bar, Baz as Qux, Norf, } from 'x';",
"import { Foo as Bar, Baz, Qux as Norf } from 'x';",
"import { Foo as Bar, Baz, Qux as Norf, } from 'x';",
"import { Foo, Bar as Baz, Qux as Norf } from 'x';",
"import { Foo, Bar as Baz, Qux as Norf, } from 'x';",
"import { Foo as Bar, Baz as Qux, Norf as Enuf } from 'x';",
"import { Foo as Bar, Baz as Qux, Norf as Enuf, } from 'x';",
"import Default, * as All from 'x';",
"import Default, { } from 'x';",
"import Default, { Foo } from 'x';",
"import Default, { Foo, } from 'x';",
"import Default, { Foo as Bar } from 'x';",
"import Default, { Foo as Bar, } from 'x';",
"import Default, { Foo, Bar } from 'x';",
"import Default, { Foo, Bar, } from 'x';",
"import Default, { Foo as Bar, Baz } from 'x';",
"import Default, { Foo as Bar, Baz, } from 'x';",
"import Default, { Foo, Bar as Baz } from 'x';",
"import Default, { Foo, Bar as Baz, } from 'x';",
"import Default, { Foo as Bar, Baz as Qux } from 'x';",
"import Default, { Foo as Bar, Baz as Qux, } from 'x';",
"import Default, { Foo, Bar, Baz } from 'x';",
"import Default, { Foo, Bar, Baz, } from 'x';",
"import Default, { Foo as Bar, Baz, Qux } from 'x';",
"import Default, { Foo as Bar, Baz, Qux, } from 'x';",
"import Default, { Foo, Bar as Baz, Qux } from 'x';",
"import Default, { Foo, Bar as Baz, Qux, } from 'x';",
"import Default, { Foo, Bar, Baz as Qux } from 'x';",
"import Default, { Foo, Bar, Baz as Qux, } from 'x';",
"import Default, { Foo as Bar, Baz as Qux, Norf } from 'x';",
"import Default, { Foo as Bar, Baz as Qux, Norf, } from 'x';",
"import Default, { Foo as Bar, Baz, Qux as Norf } from 'x';",
"import Default, { Foo as Bar, Baz, Qux as Norf, } from 'x';",
"import Default, { Foo, Bar as Baz, Qux as Norf } from 'x';",
"import Default, { Foo, Bar as Baz, Qux as Norf, } from 'x';",
"import Default, { Foo as Bar, Baz as Qux, Norf as NoMore } from 'x';",
"import Default, { Foo as Bar, Baz as Qux, Norf as NoMore, } from 'x';",
"import Default , { } from 'x';",
'import "x";',
'import Default from "x";',
'import * as All from "x";',
'import { } from "x";',
'import { Foo } from "x";',
'import { Foo, } from "x";',
'import { Foo as Bar } from "x";',
'import { Foo as Bar, } from "x";',
'import { Foo, Bar } from "x";',
'import { Foo, Bar, } from "x";',
'import { Foo as Bar, Baz } from "x";',
'import { Foo as Bar, Baz, } from "x";',
'import { Foo, Bar as Baz } from "x";',
'import { Foo, Bar as Baz, } from "x";',
'import { Foo as Bar, Baz as Qux } from "x";',
'import { Foo as Bar, Baz as Qux, } from "x";',
'import { Foo, Bar, Baz } from "x";',
'import { Foo, Bar, Baz, } from "x";',
'import { Foo as Bar, Baz, Qux } from "x";',
'import { Foo as Bar, Baz, Qux, } from "x";',
'import { Foo, Bar as Baz, Qux } from "x";',
'import { Foo, Bar as Baz, Qux, } from "x";',
'import { Foo, Bar, Baz as Qux } from "x";',
'import { Foo, Bar, Baz as Qux, } from "x";',
'import { Foo as Bar, Baz as Qux, Norf } from "x";',
'import { Foo as Bar, Baz as Qux, Norf, } from "x";',
'import { Foo as Bar, Baz, Qux as Norf } from "x";',
'import { Foo as Bar, Baz, Qux as Norf, } from "x";',
'import { Foo, Bar as Baz, Qux as Norf } from "x";',
'import { Foo, Bar as Baz, Qux as Norf, } from "x";',
'import { Foo as Bar, Baz as Qux, Norf as NoMore } from "x";',
'import { Foo as Bar, Baz as Qux, Norf as NoMore, } from "x";',
'import Default, * as All from "x";',
'import Default, { } from "x";',
'import Default, { Foo } from "x";',
'import Default, { Foo, } from "x";',
'import Default, { Foo as Bar } from "x";',
'import Default, { Foo as Bar, } from "x";',
'import Default, { Foo, Bar } from "x";',
'import Default, { Foo, Bar, } from "x";',
'import Default, { Foo as Bar, Baz } from "x";',
'import Default, { Foo as Bar, Baz, } from "x";',
'import Default, { Foo, Bar as Baz } from "x";',
'import Default, { Foo, Bar as Baz, } from "x";',
'import Default, { Foo as Bar, Baz as Qux } from "x";',
'import Default, { Foo as Bar, Baz as Qux, } from "x";',
'import Default, { Foo, Bar, Baz } from "x";',
'import Default, { Foo, Bar, Baz, } from "x";',
'import Default, { Foo as Bar, Baz, Qux } from "x";',
'import Default, { Foo as Bar, Baz, Qux, } from "x";',
'import Default, { Foo, Bar as Baz, Qux } from "x";',
'import Default, { Foo, Bar as Baz, Qux, } from "x";',
'import Default, { Foo, Bar, Baz as Qux } from "x";',
'import Default, { Foo, Bar, Baz as Qux, } from "x";',
'import Default, { Foo as Bar, Baz as Qux, Norf } from "x";',
'import Default, { Foo as Bar, Baz as Qux, Norf, } from "x";',
'import Default, { Foo as Bar, Baz, Qux as Norf } from "x";',
'import Default, { Foo as Bar, Baz, Qux as Norf, } from "x";',
'import Default, { Foo, Bar as Baz, Qux as Norf } from "x";',
'import Default, { Foo, Bar as Baz, Qux as Norf, } from "x";',
'import Default, { Foo as Bar, Baz as Qux, Norf as Enuf } from "x";',
'import Default, { Foo as Bar, Baz as Qux, Norf as Enuf, } from "x";',
'import Default from "y";',
'import * as All from \'z\';',
'require("x")', 'require("x")',
'require("y")', 'require("y")',
'require( "z" )', 'require( \'z\' )',
'require( "a")', 'require( "a")',
'require("b" )', 'require("b" )',
].join('\n'); ].join('\n');
/*eslint-disable */
depGraph.resolveDependency.mockImpl(function(fromModule, toModuleName) { depGraph.resolveDependency.mockImpl(function(fromModule, toModuleName) {
if (toModuleName === 'x') { if (toModuleName === 'x') {
@ -242,7 +377,7 @@ describe('HasteDependencyResolver', function() {
id: 'changed' id: 'changed'
}; };
} else if (toModuleName === 'y') { } else if (toModuleName === 'y') {
return { id: 'y' }; return { id: 'Y' };
} }
return null; return null;
}); });
@ -254,13 +389,145 @@ describe('HasteDependencyResolver', function() {
}, code); }, code);
expect(processedCode).toEqual([ expect(processedCode).toEqual([
'__d(\'test module\',["changed","y"],function(global,' + '__d(\'test module\',["changed","Y"],function(global,' +
' require, requireDynamic, requireLazy, module, exports) {' + ' require, requireDynamic, requireLazy, module, exports) { ' +
' require(\'changed\')', "import'x';",
'require(\'y\')', "import 'changed';",
'require("z")', "import 'changed' ;",
'require("a")', "import Default from 'changed';",
'require("b")});', "import * as All from 'changed';",
"import {} from 'changed';",
"import { } from 'changed';",
"import {Foo} from 'changed';",
"import { Foo } from 'changed';",
"import { Foo, } from 'changed';",
"import {Foo as Bar} from 'changed';",
"import { Foo as Bar } from 'changed';",
"import { Foo as Bar, } from 'changed';",
"import { Foo, Bar } from 'changed';",
"import { Foo, Bar, } from 'changed';",
"import { Foo as Bar, Baz } from 'changed';",
"import { Foo as Bar, Baz, } from 'changed';",
"import { Foo, Bar as Baz } from 'changed';",
"import { Foo, Bar as Baz, } from 'changed';",
"import { Foo as Bar, Baz as Qux } from 'changed';",
"import { Foo as Bar, Baz as Qux, } from 'changed';",
"import { Foo, Bar, Baz } from 'changed';",
"import { Foo, Bar, Baz, } from 'changed';",
"import { Foo as Bar, Baz, Qux } from 'changed';",
"import { Foo as Bar, Baz, Qux, } from 'changed';",
"import { Foo, Bar as Baz, Qux } from 'changed';",
"import { Foo, Bar as Baz, Qux, } from 'changed';",
"import { Foo, Bar, Baz as Qux } from 'changed';",
"import { Foo, Bar, Baz as Qux, } from 'changed';",
"import { Foo as Bar, Baz as Qux, Norf } from 'changed';",
"import { Foo as Bar, Baz as Qux, Norf, } from 'changed';",
"import { Foo as Bar, Baz, Qux as Norf } from 'changed';",
"import { Foo as Bar, Baz, Qux as Norf, } from 'changed';",
"import { Foo, Bar as Baz, Qux as Norf } from 'changed';",
"import { Foo, Bar as Baz, Qux as Norf, } from 'changed';",
"import { Foo as Bar, Baz as Qux, Norf as Enuf } from 'changed';",
"import { Foo as Bar, Baz as Qux, Norf as Enuf, } from 'changed';",
"import Default, * as All from 'changed';",
"import Default, { } from 'changed';",
"import Default, { Foo } from 'changed';",
"import Default, { Foo, } from 'changed';",
"import Default, { Foo as Bar } from 'changed';",
"import Default, { Foo as Bar, } from 'changed';",
"import Default, { Foo, Bar } from 'changed';",
"import Default, { Foo, Bar, } from 'changed';",
"import Default, { Foo as Bar, Baz } from 'changed';",
"import Default, { Foo as Bar, Baz, } from 'changed';",
"import Default, { Foo, Bar as Baz } from 'changed';",
"import Default, { Foo, Bar as Baz, } from 'changed';",
"import Default, { Foo as Bar, Baz as Qux } from 'changed';",
"import Default, { Foo as Bar, Baz as Qux, } from 'changed';",
"import Default, { Foo, Bar, Baz } from 'changed';",
"import Default, { Foo, Bar, Baz, } from 'changed';",
"import Default, { Foo as Bar, Baz, Qux } from 'changed';",
"import Default, { Foo as Bar, Baz, Qux, } from 'changed';",
"import Default, { Foo, Bar as Baz, Qux } from 'changed';",
"import Default, { Foo, Bar as Baz, Qux, } from 'changed';",
"import Default, { Foo, Bar, Baz as Qux } from 'changed';",
"import Default, { Foo, Bar, Baz as Qux, } from 'changed';",
"import Default, { Foo as Bar, Baz as Qux, Norf } from 'changed';",
"import Default, { Foo as Bar, Baz as Qux, Norf, } from 'changed';",
"import Default, { Foo as Bar, Baz, Qux as Norf } from 'changed';",
"import Default, { Foo as Bar, Baz, Qux as Norf, } from 'changed';",
"import Default, { Foo, Bar as Baz, Qux as Norf } from 'changed';",
"import Default, { Foo, Bar as Baz, Qux as Norf, } from 'changed';",
"import Default, { Foo as Bar, Baz as Qux, Norf as NoMore } from 'changed';",
"import Default, { Foo as Bar, Baz as Qux, Norf as NoMore, } from 'changed';",
"import Default , { } from 'changed';",
'import "changed";',
'import Default from "changed";',
'import * as All from "changed";',
'import { } from "changed";',
'import { Foo } from "changed";',
'import { Foo, } from "changed";',
'import { Foo as Bar } from "changed";',
'import { Foo as Bar, } from "changed";',
'import { Foo, Bar } from "changed";',
'import { Foo, Bar, } from "changed";',
'import { Foo as Bar, Baz } from "changed";',
'import { Foo as Bar, Baz, } from "changed";',
'import { Foo, Bar as Baz } from "changed";',
'import { Foo, Bar as Baz, } from "changed";',
'import { Foo as Bar, Baz as Qux } from "changed";',
'import { Foo as Bar, Baz as Qux, } from "changed";',
'import { Foo, Bar, Baz } from "changed";',
'import { Foo, Bar, Baz, } from "changed";',
'import { Foo as Bar, Baz, Qux } from "changed";',
'import { Foo as Bar, Baz, Qux, } from "changed";',
'import { Foo, Bar as Baz, Qux } from "changed";',
'import { Foo, Bar as Baz, Qux, } from "changed";',
'import { Foo, Bar, Baz as Qux } from "changed";',
'import { Foo, Bar, Baz as Qux, } from "changed";',
'import { Foo as Bar, Baz as Qux, Norf } from "changed";',
'import { Foo as Bar, Baz as Qux, Norf, } from "changed";',
'import { Foo as Bar, Baz, Qux as Norf } from "changed";',
'import { Foo as Bar, Baz, Qux as Norf, } from "changed";',
'import { Foo, Bar as Baz, Qux as Norf } from "changed";',
'import { Foo, Bar as Baz, Qux as Norf, } from "changed";',
'import { Foo as Bar, Baz as Qux, Norf as NoMore } from "changed";',
'import { Foo as Bar, Baz as Qux, Norf as NoMore, } from "changed";',
'import Default, * as All from "changed";',
'import Default, { } from "changed";',
'import Default, { Foo } from "changed";',
'import Default, { Foo, } from "changed";',
'import Default, { Foo as Bar } from "changed";',
'import Default, { Foo as Bar, } from "changed";',
'import Default, { Foo, Bar } from "changed";',
'import Default, { Foo, Bar, } from "changed";',
'import Default, { Foo as Bar, Baz } from "changed";',
'import Default, { Foo as Bar, Baz, } from "changed";',
'import Default, { Foo, Bar as Baz } from "changed";',
'import Default, { Foo, Bar as Baz, } from "changed";',
'import Default, { Foo as Bar, Baz as Qux } from "changed";',
'import Default, { Foo as Bar, Baz as Qux, } from "changed";',
'import Default, { Foo, Bar, Baz } from "changed";',
'import Default, { Foo, Bar, Baz, } from "changed";',
'import Default, { Foo as Bar, Baz, Qux } from "changed";',
'import Default, { Foo as Bar, Baz, Qux, } from "changed";',
'import Default, { Foo, Bar as Baz, Qux } from "changed";',
'import Default, { Foo, Bar as Baz, Qux, } from "changed";',
'import Default, { Foo, Bar, Baz as Qux } from "changed";',
'import Default, { Foo, Bar, Baz as Qux, } from "changed";',
'import Default, { Foo as Bar, Baz as Qux, Norf } from "changed";',
'import Default, { Foo as Bar, Baz as Qux, Norf, } from "changed";',
'import Default, { Foo as Bar, Baz, Qux as Norf } from "changed";',
'import Default, { Foo as Bar, Baz, Qux as Norf, } from "changed";',
'import Default, { Foo, Bar as Baz, Qux as Norf } from "changed";',
'import Default, { Foo, Bar as Baz, Qux as Norf, } from "changed";',
'import Default, { Foo as Bar, Baz as Qux, Norf as Enuf } from "changed";',
'import Default, { Foo as Bar, Baz as Qux, Norf as Enuf, } from "changed";',
'import Default from "Y";',
'import * as All from \'z\';',
'require("changed")',
'require("Y")',
'require( \'z\' )',
'require( "a")',
'require("b" )});',
].join('\n')); ].join('\n'));
}); });
}); });

View File

@ -10,7 +10,7 @@
var path = require('path'); var path = require('path');
var DependencyGraph = require('./DependencyGraph'); var DependencyGraph = require('./DependencyGraph');
var requirePattern = require('./requirePattern'); var replacePatterns = require('./replacePatterns');
var ModuleDescriptor = require('../ModuleDescriptor'); var ModuleDescriptor = require('../ModuleDescriptor');
var declareOpts = require('../../lib/declareOpts'); var declareOpts = require('../../lib/declareOpts');
@ -61,7 +61,7 @@ function HasteDependencyResolver(options) {
this._depGraph = new DependencyGraph({ this._depGraph = new DependencyGraph({
roots: opts.projectRoots, roots: opts.projectRoots,
assetRoots: opts.assetRoots, assetRoots_DEPRECATED: opts.assetRoots,
ignoreFilePath: function(filepath) { ignoreFilePath: function(filepath) {
return filepath.indexOf('__tests__') !== -1 || return filepath.indexOf('__tests__') !== -1 ||
(opts.blacklistRE && opts.blacklistRE.test(filepath)); (opts.blacklistRE && opts.blacklistRE.test(filepath));
@ -144,20 +144,20 @@ HasteDependencyResolver.prototype.wrapModule = function(module, code) {
} }
} }
var relativizedCode = var relativizeCode = function(codeMatch, pre, quot, depName, post) {
code.replace(requirePattern, function(codeMatch, _, depName) { var depId = resolvedDeps[depName];
var depId = resolvedDeps[depName]; if (depId) {
if (depId != null) { return pre + quot + depId + post;
return 'require(\'' + depId + '\')'; } else {
} else { return codeMatch;
return codeMatch.replace(/\s+/g, ''); }
} };
});
return DEFINE_MODULE_CODE.replace(DEFINE_MODULE_REPLACE_RE, function(key) { return DEFINE_MODULE_CODE.replace(DEFINE_MODULE_REPLACE_RE, function(key) {
return { return {
'_moduleName_': module.id, '_moduleName_': module.id,
'_code_': relativizedCode, '_code_': code.replace(replacePatterns.IMPORT_RE, relativizeCode)
.replace(replacePatterns.REQUIRE_RE, relativizeCode),
'_deps_': JSON.stringify(resolvedDepsArr), '_deps_': JSON.stringify(resolvedDepsArr),
}[key]; }[key];
}); });

View File

@ -9,6 +9,5 @@
'use strict'; 'use strict';
var REQUIRE_RE = /\brequire\s*?\(\s*?([\'"])([^"\']+)\1\s*?\)/g; exports.IMPORT_RE = /(\bimport\s+?(?:.+\s+?from\s+?)?)(['"])([^'"]+)(\2)/g;
exports.REQUIRE_RE = /(\brequire\s*?\(\s*?)(['"])([^'"]+)(\2\s*?\))/g;
module.exports = REQUIRE_RE;

View File

@ -61,9 +61,7 @@ function Transformer(options) {
projectRoots: options.projectRoots, projectRoots: options.projectRoots,
}); });
if (options.transformModulePath == null) { if (options.transformModulePath != null) {
this._failedToStart = Promise.reject(new Error('No transfrom module'));
} else {
this._workers = workerFarm( this._workers = workerFarm(
{autoStart: true, maxConcurrentCallsPerWorker: 1}, {autoStart: true, maxConcurrentCallsPerWorker: 1},
options.transformModulePath options.transformModulePath
@ -83,8 +81,8 @@ Transformer.prototype.invalidateFile = function(filePath) {
}; };
Transformer.prototype.loadFileAndTransform = function(filePath) { Transformer.prototype.loadFileAndTransform = function(filePath) {
if (this._failedToStart) { if (this._transform == null) {
return this._failedToStart; return Promise.reject(new Error('No transfrom module'));
} }
var transform = this._transform; var transform = this._transform;