Adopt NavigationExperimental in UIExplorer
Summary:Use the new Navigation library to make the UIExplorer navigation more flexible. Deep linking examples are coming soon (hint: we just need to convert URIs to UIExplorerActions!) Reviewed By: javache Differential Revision: D2798050 fb-gh-sync-id: c7775393e2d7a30a161d0770192309567dcc8b0c shipit-source-id: c7775393e2d7a30a161d0770192309567dcc8b0c
This commit is contained in:
parent
2551540540
commit
876ecb291f
|
@ -32,8 +32,8 @@ const NavigationBasicReducer = NavigationReducer.StackReducer({
|
|||
initialStates: [
|
||||
{key: 'First Route'}
|
||||
],
|
||||
matchAction: action => true,
|
||||
actionStateMap: actionString => ({key: actionString}),
|
||||
matchAction: action => action.type === 'push',
|
||||
actionStateMap: action => ({key: action.key}),
|
||||
});
|
||||
|
||||
class NavigationAnimatedExample extends React.Component {
|
||||
|
@ -45,7 +45,7 @@ class NavigationAnimatedExample extends React.Component {
|
|||
<NavigationRootContainer
|
||||
reducer={NavigationBasicReducer}
|
||||
ref={navRootContainer => { this.navRootContainer = navRootContainer; }}
|
||||
persistenceKey="NavigationAnimatedExampleState"
|
||||
persistenceKey="NavigationAnimExampleState"
|
||||
renderNavigation={this._renderNavigated}
|
||||
/>
|
||||
);
|
||||
|
@ -85,7 +85,7 @@ class NavigationAnimatedExample extends React.Component {
|
|||
<NavigationExampleRow
|
||||
text="Push!"
|
||||
onPress={() => {
|
||||
onNavigate('Route #' + navigationState.children.length);
|
||||
onNavigate({ type: 'push', key: 'Route #' + navigationState.children.length });
|
||||
}}
|
||||
/>
|
||||
<NavigationExampleRow
|
||||
|
|
|
@ -35,7 +35,7 @@ var EXAMPLES = {
|
|||
'Tic Tac Toe': require('./NavigationTicTacToeExample'),
|
||||
};
|
||||
|
||||
var EXAMPLE_STORAGE_KEY = 'NavigationExampleExample';
|
||||
var EXAMPLE_STORAGE_KEY = 'NavigationExperimentalExample';
|
||||
|
||||
var NavigationExperimentalExample = React.createClass({
|
||||
statics: {
|
||||
|
|
|
@ -31,7 +31,7 @@ const {
|
|||
|
||||
type GameGrid = Array<Array<?string>>;
|
||||
|
||||
const evenOddPlayerMap = ['o', 'x'];
|
||||
const evenOddPlayerMap = ['O', 'X'];
|
||||
const rowLeterMap = ['a', 'b', 'c'];
|
||||
|
||||
function parseGame(game: string): GameGrid {
|
||||
|
@ -99,20 +99,20 @@ function isGameOver(gameString: string): boolean {
|
|||
|
||||
class Cell extends React.Component {
|
||||
cellStyle() {
|
||||
switch (this.props.value) {
|
||||
case 'x':
|
||||
switch (this.props.player) {
|
||||
case 'X':
|
||||
return styles.cellX;
|
||||
case 'o':
|
||||
case 'O':
|
||||
return styles.cellO;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
textStyle() {
|
||||
switch (this.props.value) {
|
||||
case 'x':
|
||||
switch (this.props.player) {
|
||||
case 'X':
|
||||
return styles.cellTextX;
|
||||
case 'o':
|
||||
case 'O':
|
||||
return styles.cellTextO;
|
||||
default:
|
||||
return {};
|
||||
|
@ -171,6 +171,11 @@ function TicTacToeGame(props) {
|
|||
);
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text
|
||||
style={styles.closeButton}
|
||||
onPress={props.onExampleExit}>
|
||||
Close
|
||||
</Text>
|
||||
<Text style={styles.title}>EXTREME T3</Text>
|
||||
<View style={styles.board}>
|
||||
{rows}
|
||||
|
@ -184,18 +189,18 @@ function TicTacToeGame(props) {
|
|||
TicTacToeGame = NavigationContainer.create(TicTacToeGame);
|
||||
|
||||
const GameActions = {
|
||||
Turn: (row, col) => ({gameAction: 'turn', row, col }),
|
||||
Reset: (row, col) => ({gameAction: 'reset' }),
|
||||
Turn: (row, col) => ({type: 'TicTacToeTurnAction', row, col }),
|
||||
Reset: (row, col) => ({type: 'TicTacToeResetAction' }),
|
||||
};
|
||||
|
||||
function GameReducer(lastGame: ?string, action: Object): string {
|
||||
if (!lastGame || !action || !action.gameAction) {
|
||||
return lastGame || '';
|
||||
if (!lastGame) {
|
||||
lastGame = '';
|
||||
}
|
||||
if (action.gameAction === 'reset') {
|
||||
if (action.type === 'TicTacToeResetAction') {
|
||||
return '';
|
||||
}
|
||||
if (!isGameOver(lastGame) && action.gameAction === 'turn') {
|
||||
if (!isGameOver(lastGame) && action.type === 'TicTacToeTurnAction') {
|
||||
return playTurn(lastGame, action.row, action.col);
|
||||
}
|
||||
return lastGame;
|
||||
|
@ -206,10 +211,11 @@ class NavigationTicTacToeExample extends React.Component {
|
|||
return (
|
||||
<NavigationRootContainer
|
||||
reducer={GameReducer}
|
||||
persistenceKey="TicTacToeGame"
|
||||
persistenceKey="TicTacToeGameState"
|
||||
renderNavigation={(game) => (
|
||||
<TicTacToeGame
|
||||
game={game}
|
||||
onExampleExit={this.props.onExampleExit}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
@ -221,6 +227,12 @@ NavigationTicTacToeExample.GameReducer = GameReducer;
|
|||
NavigationTicTacToeExample.GameActions = GameActions;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
closeButton: {
|
||||
position: 'absolute',
|
||||
left: 10,
|
||||
top: 30,
|
||||
fontSize: 14,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
|
@ -257,7 +269,6 @@ const styles = StyleSheet.create({
|
|||
backgroundColor: '#7ebd26',
|
||||
},
|
||||
cellText: {
|
||||
borderRadius: 5,
|
||||
fontSize: 50,
|
||||
fontFamily: 'AvenirNext-Bold',
|
||||
},
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
export type UIExplorerListWithFilterAction = {
|
||||
type: 'UIExplorerListWithFilterAction',
|
||||
filter: ?string;
|
||||
};
|
||||
|
||||
export type UIExplorerExampleAction = {
|
||||
type: 'UIExplorerExampleAction',
|
||||
openExample: string;
|
||||
};
|
||||
|
||||
import type {BackAction} from 'NavigationRootContainer';
|
||||
|
||||
export type UIExplorerAction = BackAction | UIExplorerListWithFilterAction | UIExplorerExampleAction;
|
||||
|
||||
function ExampleListWithFilter(filter: ?string): UIExplorerListWithFilterAction {
|
||||
return {
|
||||
type: 'UIExplorerListWithFilterAction',
|
||||
filter,
|
||||
};
|
||||
}
|
||||
|
||||
function ExampleAction(openExample: string): UIExplorerExampleAction {
|
||||
return {
|
||||
type: 'UIExplorerExampleAction',
|
||||
openExample,
|
||||
};
|
||||
}
|
||||
|
||||
const UIExplorerActions = {
|
||||
ExampleListWithFilter,
|
||||
ExampleAction,
|
||||
};
|
||||
|
||||
module.exports = UIExplorerActions;
|
|
@ -22,84 +22,111 @@ const {
|
|||
BackAndroid,
|
||||
Dimensions,
|
||||
DrawerLayoutAndroid,
|
||||
NavigationExperimental,
|
||||
StyleSheet,
|
||||
ToolbarAndroid,
|
||||
View,
|
||||
StatusBar,
|
||||
} = React;
|
||||
const UIExplorerList = require('./UIExplorerList.android');
|
||||
const {
|
||||
RootContainer: NavigationRootContainer,
|
||||
} = NavigationExperimental;
|
||||
const UIExplorerActions = require('./UIExplorerActions');
|
||||
const UIExplorerExampleList = require('./UIExplorerExampleList');
|
||||
const UIExplorerList = require('./UIExplorerList');
|
||||
const UIExplorerNavigationReducer = require('./UIExplorerNavigationReducer');
|
||||
const UIExplorerStateTitleMap = require('./UIExplorerStateTitleMap');
|
||||
|
||||
const DRAWER_WIDTH_LEFT = 56;
|
||||
var DRAWER_WIDTH_LEFT = 56;
|
||||
|
||||
class UIExplorerApp extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onSelectExample = this.onSelectExample.bind(this);
|
||||
this._handleBackButtonPress = this._handleBackButtonPress.bind(this);
|
||||
this.state = {
|
||||
example: this._getUIExplorerHome(),
|
||||
};
|
||||
}
|
||||
|
||||
_getUIExplorerHome() {
|
||||
return {
|
||||
title: 'UIExplorer',
|
||||
component: this._renderHome(),
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
BackAndroid.addEventListener('hardwareBackPress', this._handleBackButtonPress);
|
||||
BackAndroid.addEventListener('hardwareBackPress', this._handleBackButtonPress.bind(this));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<NavigationRootContainer
|
||||
persistenceKey="UIExplorerStateNavState"
|
||||
ref={navRootRef => { this._navigationRootRef = navRootRef; }}
|
||||
reducer={UIExplorerNavigationReducer}
|
||||
renderNavigation={this._renderApp.bind(this)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_renderApp(navigationState, onNavigate) {
|
||||
if (!navigationState) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<DrawerLayoutAndroid
|
||||
drawerPosition={DrawerLayoutAndroid.positions.Left}
|
||||
drawerWidth={Dimensions.get('window').width - DRAWER_WIDTH_LEFT}
|
||||
keyboardDismissMode="on-drag"
|
||||
onDrawerOpen={() => {
|
||||
this._overrideBackPressForDrawerLayout = true;
|
||||
}}
|
||||
onDrawerClose={() => {
|
||||
this._overrideBackPressForDrawerLayout = false;
|
||||
}}
|
||||
ref={(drawer) => { this.drawer = drawer; }}
|
||||
renderNavigationView={this._renderNavigationView}>
|
||||
{this._renderNavigation()}
|
||||
renderNavigationView={this._renderDrawerContent.bind(this, onNavigate)}>
|
||||
{this._renderNavigation(navigationState, onNavigate)}
|
||||
</DrawerLayoutAndroid>
|
||||
);
|
||||
}
|
||||
|
||||
_renderNavigationView() {
|
||||
_renderDrawerContent(onNavigate) {
|
||||
return (
|
||||
<UIExplorerList
|
||||
onSelectExample={this.onSelectExample}
|
||||
isInDrawer={true}
|
||||
<UIExplorerExampleList
|
||||
list={UIExplorerList}
|
||||
displayTitleRow={true}
|
||||
disableSearch={true}
|
||||
onNavigate={(action) => {
|
||||
this.drawer && this.drawer.closeDrawer();
|
||||
onNavigate(action);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
onSelectExample(example) {
|
||||
this.drawer.closeDrawer();
|
||||
if (example.title === this._getUIExplorerHome().title) {
|
||||
example = this._getUIExplorerHome();
|
||||
_renderNavigation(navigationState, onNavigate) {
|
||||
if (navigationState.externalExample) {
|
||||
var Component = UIExplorerList.Modules[navigationState.externalExample];
|
||||
return (
|
||||
<Component
|
||||
onExampleExit={() => {
|
||||
onNavigate(NavigationRootContainer.getBackAction());
|
||||
}}
|
||||
ref={(example) => { this._exampleRef = example; }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
this.setState({
|
||||
example: example,
|
||||
});
|
||||
}
|
||||
|
||||
_renderHome() {
|
||||
const onSelectExample = this.onSelectExample;
|
||||
return React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerList
|
||||
onSelectExample={onSelectExample}
|
||||
isInDrawer={false}
|
||||
const {stack} = navigationState;
|
||||
const title = UIExplorerStateTitleMap(stack.children[stack.index]);
|
||||
if (stack && stack.children[1]) {
|
||||
const {key} = stack.children[1];
|
||||
const ExampleModule = UIExplorerList.Modules[key];
|
||||
const ExampleComponent = UIExplorerExampleList.makeRenderable(ExampleModule);
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar
|
||||
backgroundColor="#589c90"
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_renderNavigation() {
|
||||
const Component = this.state.example.component;
|
||||
<ToolbarAndroid
|
||||
logo={require('image!launcher_icon')}
|
||||
navIcon={require('image!ic_menu_black_24dp')}
|
||||
onIconClicked={() => this.drawer.openDrawer()}
|
||||
style={styles.toolbar}
|
||||
title={title}
|
||||
/>
|
||||
<ExampleComponent
|
||||
ref={(example) => { this._exampleRef = example; }}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar
|
||||
|
@ -110,16 +137,24 @@ class UIExplorerApp extends React.Component {
|
|||
navIcon={require('image!ic_menu_black_24dp')}
|
||||
onIconClicked={() => this.drawer.openDrawer()}
|
||||
style={styles.toolbar}
|
||||
title={this.state.example.title}
|
||||
title={title}
|
||||
/>
|
||||
<Component
|
||||
ref={(example) => { this._exampleRef = example; }}
|
||||
<UIExplorerExampleList
|
||||
list={UIExplorerList}
|
||||
{...stack.children[0]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_handleBackButtonPress() {
|
||||
if (this._overrideBackPressForDrawerLayout) {
|
||||
// This hack is necessary because drawer layout provides an imperative API
|
||||
// with open and close methods. This code would be cleaner if the drawer
|
||||
// layout provided an `isOpen` prop and allowed us to pass a `onDrawerClose` handler.
|
||||
this.drawer && this.drawer.closeDrawer();
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
this._exampleRef &&
|
||||
this._exampleRef.handleBackAction &&
|
||||
|
@ -127,13 +162,13 @@ class UIExplorerApp extends React.Component {
|
|||
) {
|
||||
return true;
|
||||
}
|
||||
if (this.state.example.title !== this._getUIExplorerHome().title) {
|
||||
this.onSelectExample(this._getUIExplorerHome());
|
||||
return true;
|
||||
if (this._navigationRootRef) {
|
||||
return this._navigationRootRef.handleNavigation(
|
||||
NavigationRootContainer.getBackAction()
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
|
|
@ -12,77 +12,173 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @providesModule UIExplorerApp
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const React = require('react-native');
|
||||
const UIExplorerActions = require('./UIExplorerActions');
|
||||
const UIExplorerList = require('./UIExplorerList.ios');
|
||||
const SetPropertiesExampleApp = require('./SetPropertiesExampleApp');
|
||||
const RootViewSizeFlexibilityExampleApp = require('./RootViewSizeFlexibilityExampleApp');
|
||||
const UIExplorerExampleList = require('./UIExplorerExampleList');
|
||||
const UIExplorerNavigationReducer = require('./UIExplorerNavigationReducer');
|
||||
const UIExplorerStateTitleMap = require('./UIExplorerStateTitleMap');
|
||||
|
||||
const {
|
||||
AppRegistry,
|
||||
NavigatorIOS,
|
||||
NavigationExperimental,
|
||||
SnapshotViewIOS,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
StatusBar,
|
||||
} = React;
|
||||
const {
|
||||
AnimatedView: NavigationAnimatedView,
|
||||
Card: NavigationCard,
|
||||
Header: NavigationHeader,
|
||||
Reducer: NavigationReducer,
|
||||
RootContainer: NavigationRootContainer,
|
||||
} = NavigationExperimental;
|
||||
const StackReducer = NavigationReducer.StackReducer;
|
||||
|
||||
import type {
|
||||
NavigationState,
|
||||
} from 'NavigationStateUtils'
|
||||
|
||||
import type { Value } from 'Animated';
|
||||
import type { Layout } from 'NavigationAnimatedView';
|
||||
import type { UIExplorerNavigationState } from './UIExplorerNavigationReducer';
|
||||
|
||||
import type {
|
||||
UIExplorerExample,
|
||||
} from './UIExplorerList.ios'
|
||||
|
||||
class UIExplorerApp extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
openExternalExample: (null: ?React.Component),
|
||||
};
|
||||
_renderNavigation: Function;
|
||||
componentWillMount() {
|
||||
this._renderNavigation = this._renderNavigation.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.openExternalExample) {
|
||||
const Example = this.state.openExternalExample;
|
||||
return (
|
||||
<NavigationRootContainer
|
||||
persistenceKey="UIExplorerState"
|
||||
reducer={UIExplorerNavigationReducer}
|
||||
renderNavigation={this._renderNavigation}
|
||||
/>
|
||||
);
|
||||
}
|
||||
_renderNavigation(navigationState: UIExplorerNavigationState, onNavigate: Function) {
|
||||
if (!navigationState) {
|
||||
return null;
|
||||
}
|
||||
if (navigationState.externalExample) {
|
||||
var Component = UIExplorerList.Modules[navigationState.externalExample];
|
||||
return (
|
||||
<Example
|
||||
<Component
|
||||
onExampleExit={() => {
|
||||
this.setState({ openExternalExample: null, });
|
||||
onNavigate(NavigationRootContainer.getBackAction());
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const {stack} = navigationState;
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar barStyle="default" />
|
||||
<NavigatorIOS
|
||||
style={styles.container}
|
||||
initialRoute={{
|
||||
title: 'UIExplorer',
|
||||
component: UIExplorerList,
|
||||
passProps: {
|
||||
onExternalExampleRequested: (example) => {
|
||||
this.setState({ openExternalExample: example, });
|
||||
},
|
||||
}
|
||||
}}
|
||||
itemWrapperStyle={styles.itemWrapper}
|
||||
tintColor="#008888"
|
||||
/>
|
||||
</View>
|
||||
<NavigationAnimatedView
|
||||
navigationState={stack}
|
||||
style={styles.container}
|
||||
renderOverlay={this._renderOverlay.bind(this, stack)}
|
||||
renderScene={this._renderSceneContainer.bind(this, stack)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_renderOverlay(
|
||||
navigationState: NavigationState,
|
||||
position: Value,
|
||||
layout: Layout
|
||||
): ReactElement {
|
||||
return (
|
||||
<NavigationHeader
|
||||
navigationState={navigationState}
|
||||
position={position}
|
||||
getTitle={UIExplorerStateTitleMap}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_renderSceneContainer(
|
||||
navigationState: NavigationState,
|
||||
scene: NavigationState,
|
||||
index: number,
|
||||
position: Value,
|
||||
layout: Layout
|
||||
): ReactElement {
|
||||
return (
|
||||
<NavigationCard
|
||||
key={scene.key}
|
||||
index={index}
|
||||
navigationState={navigationState}
|
||||
position={position}
|
||||
layout={layout}>
|
||||
{this._renderScene(scene)}
|
||||
</NavigationCard>
|
||||
);
|
||||
}
|
||||
|
||||
_renderScene(state: Object): ?ReactElement {
|
||||
if (state.key === 'AppList') {
|
||||
return (
|
||||
<UIExplorerExampleList
|
||||
list={UIExplorerList}
|
||||
style={styles.exampleContainer}
|
||||
{...state}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const Example = UIExplorerList.Modules[state.key];
|
||||
if (Example) {
|
||||
const Component = UIExplorerExampleList.makeRenderable(Example);
|
||||
return (
|
||||
<View style={styles.exampleContainer}>
|
||||
<Component />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
itemWrapper: {
|
||||
backgroundColor: '#eaeaea',
|
||||
exampleContainer: {
|
||||
flex: 1,
|
||||
paddingTop: 60,
|
||||
},
|
||||
});
|
||||
|
||||
AppRegistry.registerComponent('SetPropertiesExampleApp', () => SetPropertiesExampleApp);
|
||||
AppRegistry.registerComponent('RootViewSizeFlexibilityExampleApp', () => RootViewSizeFlexibilityExampleApp);
|
||||
AppRegistry.registerComponent('SetPropertiesExampleApp', () => require('./SetPropertiesExampleApp'));
|
||||
AppRegistry.registerComponent('RootViewSizeFlexibilityExampleApp', () => require('./RootViewSizeFlexibilityExampleApp'));
|
||||
AppRegistry.registerComponent('UIExplorerApp', () => UIExplorerApp);
|
||||
UIExplorerList.registerComponents();
|
||||
|
||||
// Register suitable examples for snapshot tests
|
||||
UIExplorerList.ComponentExamples.concat(UIExplorerList.APIExamples).forEach((Example: UIExplorerExample) => {
|
||||
const ExampleModule = Example.module;
|
||||
if (ExampleModule.displayName) {
|
||||
var Snapshotter = React.createClass({
|
||||
render: function() {
|
||||
var Renderable = UIExplorerExampleList.makeRenderable(ExampleModule);
|
||||
return (
|
||||
<SnapshotViewIOS>
|
||||
<Renderable />
|
||||
</SnapshotViewIOS>
|
||||
);
|
||||
},
|
||||
});
|
||||
AppRegistry.registerComponent(ExampleModule.displayName, () => Snapshotter);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = UIExplorerApp;
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const React = require('react-native');
|
||||
const UIExplorerActions = require('./UIExplorerActions');
|
||||
const {
|
||||
ListView,
|
||||
NavigationExperimental,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
} = React;
|
||||
const createExamplePage = require('./createExamplePage');
|
||||
const {
|
||||
Container: NavigationContainer,
|
||||
} = NavigationExperimental;
|
||||
|
||||
import type {
|
||||
UIExplorerExample,
|
||||
} from './UIExplorerList.ios'
|
||||
|
||||
const ds = new ListView.DataSource({
|
||||
rowHasChanged: (r1, r2) => r1 !== r2,
|
||||
sectionHeaderHasChanged: (h1, h2) => h1 !== h2,
|
||||
});
|
||||
|
||||
class UIExplorerExampleList extends React.Component {
|
||||
constuctor(props: {
|
||||
disableTitleRow: ?boolean,
|
||||
onNavigate: Function,
|
||||
filter: ?string,
|
||||
list: {
|
||||
ComponentExamples: Array<UIExplorerExample>,
|
||||
APIExamples: Array<UIExplorerExample>,
|
||||
},
|
||||
style: ?any,
|
||||
}) {
|
||||
|
||||
}
|
||||
render(): ?ReactElement {
|
||||
const filterText = this.props.filter || '';
|
||||
const filterRegex = new RegExp(String(filterText), 'i');
|
||||
const filter = (example) => filterRegex.test(example.module.title);
|
||||
|
||||
const dataSource = ds.cloneWithRowsAndSections({
|
||||
components: this.props.list.ComponentExamples.filter(filter),
|
||||
apis: this.props.list.APIExamples.filter(filter),
|
||||
});
|
||||
return (
|
||||
<View style={[styles.listContainer, this.props.style]}>
|
||||
{this._renderTitleRow()}
|
||||
{this._renderTextInput()}
|
||||
<ListView
|
||||
style={styles.list}
|
||||
dataSource={dataSource}
|
||||
renderRow={this._renderExampleRow.bind(this)}
|
||||
renderSectionHeader={this._renderSectionHeader}
|
||||
keyboardShouldPersistTaps={true}
|
||||
automaticallyAdjustContentInsets={false}
|
||||
keyboardDismissMode="on-drag"
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_renderTitleRow(): ?ReactElement {
|
||||
if (!this.props.displayTitleRow) {
|
||||
return null;
|
||||
}
|
||||
return this._renderRow(
|
||||
'UIExplorer',
|
||||
'React Native Examples',
|
||||
'home_key',
|
||||
() => {
|
||||
this.props.onNavigate(
|
||||
UIExplorerActions.ExampleListWithFilter('')
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
_renderTextInput(): ?ReactElement {
|
||||
if (this.props.disableSearch) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<View style={styles.searchRow}>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
clearButtonMode="always"
|
||||
onChangeText={text => {
|
||||
this.props.onNavigate(UIExplorerActions.ExampleListWithFilter(text));
|
||||
}}
|
||||
placeholder="Search..."
|
||||
style={[styles.searchTextInput, this.props.searchTextInputStyle]}
|
||||
testID="explorer_search"
|
||||
value={this.props.filter}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_renderSectionHeader(data: any, section: string): ?ReactElement {
|
||||
return (
|
||||
<Text style={styles.sectionHeader}>
|
||||
{section.toUpperCase()}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
_renderExampleRow(example: {key: string, module: Object}): ?ReactElement {
|
||||
return this._renderRow(
|
||||
example.module.title,
|
||||
example.module.description,
|
||||
example.key,
|
||||
() => this._handleRowPress(example.key)
|
||||
);
|
||||
}
|
||||
|
||||
_renderRow(title: string, description: string, key: ?string, handler: ?Function): ?ReactElement {
|
||||
return (
|
||||
<View key={key || title}>
|
||||
<TouchableHighlight onPress={handler}>
|
||||
<View style={styles.row}>
|
||||
<Text style={styles.rowTitleText}>
|
||||
{title}
|
||||
</Text>
|
||||
<Text style={styles.rowDetailText}>
|
||||
{description}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
<View style={styles.separator} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_handleRowPress(exampleKey: string): void {
|
||||
this.props.onNavigate(UIExplorerActions.ExampleAction(exampleKey))
|
||||
}
|
||||
}
|
||||
|
||||
function makeRenderable(example: any): ReactClass<any, any, any> {
|
||||
return example.examples ?
|
||||
createExamplePage(null, example) :
|
||||
example;
|
||||
}
|
||||
|
||||
UIExplorerExampleList = NavigationContainer.create(UIExplorerExampleList);
|
||||
UIExplorerExampleList.makeRenderable = makeRenderable;
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
listContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
list: {
|
||||
backgroundColor: '#eeeeee',
|
||||
},
|
||||
sectionHeader: {
|
||||
padding: 5,
|
||||
fontWeight: '500',
|
||||
fontSize: 11,
|
||||
},
|
||||
group: {
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
row: {
|
||||
backgroundColor: 'white',
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 8,
|
||||
},
|
||||
separator: {
|
||||
height: StyleSheet.hairlineWidth,
|
||||
backgroundColor: '#bbbbbb',
|
||||
marginLeft: 15,
|
||||
},
|
||||
rowTitleText: {
|
||||
fontSize: 17,
|
||||
fontWeight: '500',
|
||||
},
|
||||
rowDetailText: {
|
||||
fontSize: 15,
|
||||
color: '#888888',
|
||||
lineHeight: 20,
|
||||
},
|
||||
searchRow: {
|
||||
backgroundColor: '#eeeeee',
|
||||
padding: 10,
|
||||
},
|
||||
searchTextInput: {
|
||||
backgroundColor: 'white',
|
||||
borderColor: '#cccccc',
|
||||
borderRadius: 3,
|
||||
borderWidth: 1,
|
||||
paddingLeft: 8,
|
||||
height: 35,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = UIExplorerExampleList;
|
|
@ -15,102 +15,167 @@
|
|||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
View,
|
||||
} = React;
|
||||
var UIExplorerListBase = require('./UIExplorerListBase');
|
||||
|
||||
var COMPONENTS = [
|
||||
require('./ImageExample'),
|
||||
require('./ListViewExample'),
|
||||
require('./PickerAndroidExample'),
|
||||
require('./ProgressBarAndroidExample'),
|
||||
require('./RefreshControlExample'),
|
||||
require('./ScrollViewSimpleExample'),
|
||||
require('./StatusBarExample'),
|
||||
require('./SwitchExample'),
|
||||
require('./TextExample.android'),
|
||||
require('./TextInputExample.android'),
|
||||
require('./ToolbarAndroidExample'),
|
||||
require('./TouchableExample'),
|
||||
require('./ViewExample'),
|
||||
require('./ViewPagerAndroidExample.android'),
|
||||
require('./WebViewExample'),
|
||||
];
|
||||
|
||||
var APIS = [
|
||||
require('./AccessibilityAndroidExample.android'),
|
||||
require('./AlertExample').AlertExample,
|
||||
require('./AppStateExample'),
|
||||
require('./BorderExample'),
|
||||
require('./CameraRollExample'),
|
||||
require('./ClipboardExample'),
|
||||
require('./DatePickerAndroidExample'),
|
||||
require('./GeolocationExample'),
|
||||
require('./ImageEditingExample'),
|
||||
require('./IntentAndroidExample.android'),
|
||||
require('./LayoutEventsExample'),
|
||||
require('./LayoutExample'),
|
||||
require('./NavigationExperimental/NavigationExperimentalExample'),
|
||||
require('./NetInfoExample'),
|
||||
require('./PanResponderExample'),
|
||||
require('./PointerEventsExample'),
|
||||
require('./TimePickerAndroidExample'),
|
||||
require('./TimerExample'),
|
||||
require('./ToastAndroidExample.android'),
|
||||
require('./XHRExample'),
|
||||
];
|
||||
|
||||
type Props = {
|
||||
onSelectExample: Function,
|
||||
isInDrawer: bool,
|
||||
export type UIExplorerExample = {
|
||||
key: string;
|
||||
module: React.Component;
|
||||
};
|
||||
|
||||
class UIExplorerList extends React.Component {
|
||||
props: Props;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<UIExplorerListBase
|
||||
components={COMPONENTS}
|
||||
apis={APIS}
|
||||
searchText=""
|
||||
renderAdditionalView={this.renderAdditionalView.bind(this)}
|
||||
onPressRow={this.onPressRow.bind(this)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderAdditionalView(renderRow, renderTextInput): React.Component {
|
||||
if (this.props.isInDrawer) {
|
||||
var homePage = renderRow({
|
||||
title: 'UIExplorer',
|
||||
description: 'List of examples',
|
||||
}, -1);
|
||||
return (
|
||||
<View>
|
||||
{homePage}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
return renderTextInput(styles.searchTextInput);
|
||||
}
|
||||
|
||||
onPressRow(example: any) {
|
||||
var Component = UIExplorerListBase.makeRenderable(example);
|
||||
this.props.onSelectExample({
|
||||
title: Component.title,
|
||||
component: Component,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
searchTextInput: {
|
||||
padding: 2,
|
||||
var ComponentExamples: Array<UIExplorerExample> = [
|
||||
{
|
||||
key: 'ImageExample',
|
||||
module: require('./ImageExample'),
|
||||
},
|
||||
{
|
||||
key: 'ListViewExample',
|
||||
module: require('./ListViewExample'),
|
||||
},
|
||||
{
|
||||
key: 'PickerAndroidExample',
|
||||
module: require('./PickerAndroidExample'),
|
||||
},
|
||||
{
|
||||
key: 'ProgressBarAndroidExample',
|
||||
module: require('./ProgressBarAndroidExample'),
|
||||
},
|
||||
{
|
||||
key: 'RefreshControlExample',
|
||||
module: require('./RefreshControlExample'),
|
||||
},
|
||||
{
|
||||
key: 'ScrollViewSimpleExample',
|
||||
module: require('./ScrollViewSimpleExample'),
|
||||
},
|
||||
{
|
||||
key: 'StatusBarExample',
|
||||
module: require('./StatusBarExample'),
|
||||
},
|
||||
{
|
||||
key: 'SwitchExample',
|
||||
module: require('./SwitchExample'),
|
||||
},
|
||||
{
|
||||
key: 'TextExample',
|
||||
module: require('./TextExample'),
|
||||
},
|
||||
{
|
||||
key: 'TextInputExample',
|
||||
module: require('./TextInputExample'),
|
||||
},
|
||||
{
|
||||
key: 'ToolbarAndroidExample',
|
||||
module: require('./ToolbarAndroidExample'),
|
||||
},
|
||||
{
|
||||
key: 'TouchableExample',
|
||||
module: require('./TouchableExample'),
|
||||
},
|
||||
{
|
||||
key: 'ViewExample',
|
||||
module: require('./ViewExample'),
|
||||
},
|
||||
{
|
||||
key: 'ViewPagerAndroidExample',
|
||||
module: require('./ViewPagerAndroidExample'),
|
||||
},
|
||||
{
|
||||
key: 'WebViewExample',
|
||||
module: require('./WebViewExample'),
|
||||
},
|
||||
];
|
||||
|
||||
const APIExamples = [
|
||||
{
|
||||
key: 'AccessibilityAndroidExample',
|
||||
module: require('./AccessibilityAndroidExample'),
|
||||
},
|
||||
{
|
||||
key: 'AlertExample',
|
||||
module: require('./AlertExample').AlertExample,
|
||||
},
|
||||
{
|
||||
key: 'AppStateExample',
|
||||
module: require('./AppStateExample'),
|
||||
},
|
||||
{
|
||||
key: 'BorderExample',
|
||||
module: require('./BorderExample'),
|
||||
},
|
||||
{
|
||||
key: 'CameraRollExample',
|
||||
module: require('./CameraRollExample'),
|
||||
},
|
||||
{
|
||||
key: 'ClipboardExample',
|
||||
module: require('./ClipboardExample'),
|
||||
},
|
||||
{
|
||||
key: 'DatePickerAndroidExample',
|
||||
module: require('./DatePickerAndroidExample'),
|
||||
},
|
||||
{
|
||||
key: 'GeolocationExample',
|
||||
module: require('./GeolocationExample'),
|
||||
},
|
||||
{
|
||||
key: 'ImageEditingExample',
|
||||
module: require('./ImageEditingExample'),
|
||||
},
|
||||
{
|
||||
key: 'IntentAndroidExample',
|
||||
module: require('./IntentAndroidExample'),
|
||||
},
|
||||
{
|
||||
key: 'LayoutEventsExample',
|
||||
module: require('./LayoutEventsExample'),
|
||||
},
|
||||
{
|
||||
key: 'LayoutExample',
|
||||
module: require('./LayoutExample'),
|
||||
},
|
||||
{
|
||||
key: 'NavigationExperimentalExample',
|
||||
module: require('./NavigationExperimental/NavigationExperimentalExample'),
|
||||
},
|
||||
{
|
||||
key: 'NetInfoExample',
|
||||
module: require('./NetInfoExample'),
|
||||
},
|
||||
{
|
||||
key: 'PanResponderExample',
|
||||
module: require('./PanResponderExample'),
|
||||
},
|
||||
{
|
||||
key: 'PointerEventsExample',
|
||||
module: require('./PointerEventsExample'),
|
||||
},
|
||||
{
|
||||
key: 'TimePickerAndroidExample',
|
||||
module: require('./TimePickerAndroidExample'),
|
||||
},
|
||||
{
|
||||
key: 'TimerExample',
|
||||
module: require('./TimerExample'),
|
||||
},
|
||||
{
|
||||
key: 'ToastAndroidExample',
|
||||
module: require('./ToastAndroidExample'),
|
||||
},
|
||||
{
|
||||
key: 'XHRExample',
|
||||
module: require('./XHRExample'),
|
||||
},
|
||||
];
|
||||
|
||||
const Modules = {};
|
||||
|
||||
APIExamples.concat(ComponentExamples).forEach(Example => {
|
||||
Modules[Example.key] = Example.module;
|
||||
});
|
||||
|
||||
const UIExplorerList = {
|
||||
APIExamples,
|
||||
ComponentExamples,
|
||||
Modules,
|
||||
};
|
||||
|
||||
module.exports = UIExplorerList;
|
||||
|
|
|
@ -15,151 +15,243 @@
|
|||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
AppRegistry,
|
||||
Settings,
|
||||
SnapshotViewIOS,
|
||||
StyleSheet,
|
||||
} = React;
|
||||
|
||||
import type { NavigationContext } from 'NavigationContext';
|
||||
|
||||
var UIExplorerListBase = require('./UIExplorerListBase');
|
||||
|
||||
var COMPONENTS = [
|
||||
require('./ActivityIndicatorIOSExample'),
|
||||
require('./DatePickerIOSExample'),
|
||||
require('./ImageExample'),
|
||||
require('./LayoutEventsExample'),
|
||||
require('./ListViewExample'),
|
||||
require('./ListViewGridLayoutExample'),
|
||||
require('./ListViewPagingExample'),
|
||||
require('./MapViewExample'),
|
||||
require('./ModalExample'),
|
||||
require('./Navigator/NavigatorExample'),
|
||||
require('./NavigatorIOSColorsExample'),
|
||||
require('./NavigatorIOSExample'),
|
||||
require('./PickerIOSExample'),
|
||||
require('./ProgressViewIOSExample'),
|
||||
require('./RefreshControlExample'),
|
||||
require('./ScrollViewExample'),
|
||||
require('./SegmentedControlIOSExample'),
|
||||
require('./SliderIOSExample'),
|
||||
require('./StatusBarExample'),
|
||||
require('./SwitchExample'),
|
||||
require('./TabBarIOSExample'),
|
||||
require('./TextExample.ios'),
|
||||
require('./TextInputExample.ios'),
|
||||
require('./TouchableExample'),
|
||||
require('./TransparentHitTestExample'),
|
||||
require('./ViewExample'),
|
||||
require('./WebViewExample'),
|
||||
];
|
||||
|
||||
var APIS = [
|
||||
require('./AccessibilityIOSExample'),
|
||||
require('./ActionSheetIOSExample'),
|
||||
require('./AdSupportIOSExample'),
|
||||
require('./AlertIOSExample'),
|
||||
require('./AnimatedExample'),
|
||||
require('./AnimatedGratuitousApp/AnExApp'),
|
||||
require('./AppStateIOSExample'),
|
||||
require('./AppStateExample'),
|
||||
require('./AsyncStorageExample'),
|
||||
require('./BorderExample'),
|
||||
require('./BoxShadowExample'),
|
||||
require('./CameraRollExample'),
|
||||
require('./ClipboardExample'),
|
||||
require('./GeolocationExample'),
|
||||
require('./ImageEditingExample'),
|
||||
require('./LayoutExample'),
|
||||
require('./NavigationExperimental/NavigationExperimentalExample'),
|
||||
require('./NetInfoExample'),
|
||||
require('./PanResponderExample'),
|
||||
require('./PointerEventsExample'),
|
||||
require('./PushNotificationIOSExample'),
|
||||
require('./RCTRootViewIOSExample'),
|
||||
require('./StatusBarIOSExample'),
|
||||
require('./TimerExample'),
|
||||
require('./TransformExample'),
|
||||
require('./VibrationIOSExample'),
|
||||
require('./XHRExample.ios'),
|
||||
];
|
||||
|
||||
type Props = {
|
||||
navigator: {
|
||||
navigationContext: NavigationContext,
|
||||
push: (route: {title: string, component: ReactClass<any,any,any>}) => void,
|
||||
},
|
||||
onExternalExampleRequested: Function,
|
||||
export type UIExplorerExample = {
|
||||
key: string;
|
||||
module: Object;
|
||||
};
|
||||
|
||||
class UIExplorerList extends React.Component {
|
||||
props: Props;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<UIExplorerListBase
|
||||
components={COMPONENTS}
|
||||
apis={APIS}
|
||||
searchText={Settings.get('searchText')}
|
||||
renderAdditionalView={this.renderAdditionalView.bind(this)}
|
||||
search={this.search.bind(this)}
|
||||
onPressRow={this.onPressRow.bind(this)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderAdditionalView(renderRow: Function, renderTextInput: Function): React.Component {
|
||||
return renderTextInput(styles.searchTextInput);
|
||||
}
|
||||
|
||||
search(text: mixed) {
|
||||
Settings.set({searchText: text});
|
||||
}
|
||||
|
||||
_openExample(example: any) {
|
||||
if (example.external) {
|
||||
this.props.onExternalExampleRequested(example);
|
||||
return;
|
||||
}
|
||||
|
||||
var Component = UIExplorerListBase.makeRenderable(example);
|
||||
this.props.navigator.push({
|
||||
title: Component.title,
|
||||
component: Component,
|
||||
});
|
||||
}
|
||||
|
||||
onPressRow(example: any) {
|
||||
this._openExample(example);
|
||||
}
|
||||
|
||||
// Register suitable examples for snapshot tests
|
||||
static registerComponents() {
|
||||
COMPONENTS.concat(APIS).forEach((Example) => {
|
||||
if (Example.displayName) {
|
||||
var Snapshotter = React.createClass({
|
||||
render: function() {
|
||||
var Renderable = UIExplorerListBase.makeRenderable(Example);
|
||||
return (
|
||||
<SnapshotViewIOS>
|
||||
<Renderable />
|
||||
</SnapshotViewIOS>
|
||||
);
|
||||
},
|
||||
});
|
||||
AppRegistry.registerComponent(Example.displayName, () => Snapshotter);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
searchTextInput: {
|
||||
height: 30,
|
||||
var ComponentExamples: Array<UIExplorerExample> = [
|
||||
{
|
||||
key: 'ActivityIndicatorIOSExample',
|
||||
module: require('./ActivityIndicatorIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'DatePickerIOSExample',
|
||||
module: require('./DatePickerIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'ImageExample',
|
||||
module: require('./ImageExample'),
|
||||
},
|
||||
{
|
||||
key: 'LayoutEventsExample',
|
||||
module: require('./LayoutEventsExample'),
|
||||
},
|
||||
{
|
||||
key: 'ListViewExample',
|
||||
module: require('./ListViewExample'),
|
||||
},
|
||||
{
|
||||
key: 'ListViewGridLayoutExample',
|
||||
module: require('./ListViewGridLayoutExample'),
|
||||
},
|
||||
{
|
||||
key: 'ListViewPagingExample',
|
||||
module: require('./ListViewPagingExample'),
|
||||
},
|
||||
{
|
||||
key: 'MapViewExample',
|
||||
module: require('./MapViewExample'),
|
||||
},
|
||||
{
|
||||
key: 'ModalExample',
|
||||
module: require('./ModalExample'),
|
||||
},
|
||||
{
|
||||
key: 'NavigatorExample',
|
||||
module: require('./Navigator/NavigatorExample'),
|
||||
},
|
||||
{
|
||||
key: 'NavigatorIOSColorsExample',
|
||||
module: require('./NavigatorIOSColorsExample'),
|
||||
},
|
||||
{
|
||||
key: 'NavigatorIOSExample',
|
||||
module: require('./NavigatorIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'PickerIOSExample',
|
||||
module: require('./PickerIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'ProgressViewIOSExample',
|
||||
module: require('./ProgressViewIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'RefreshControlExample',
|
||||
module: require('./RefreshControlExample'),
|
||||
},
|
||||
{
|
||||
key: 'ScrollViewExample',
|
||||
module: require('./ScrollViewExample'),
|
||||
},
|
||||
{
|
||||
key: 'SegmentedControlIOSExample',
|
||||
module: require('./SegmentedControlIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'SliderIOSExample',
|
||||
module: require('./SliderIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'StatusBarExample',
|
||||
module: require('./StatusBarExample'),
|
||||
},
|
||||
{
|
||||
key: 'SwitchExample',
|
||||
module: require('./SwitchExample'),
|
||||
},
|
||||
{
|
||||
key: 'TabBarIOSExample',
|
||||
module: require('./TabBarIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'TextExample',
|
||||
module: require('./TextExample.ios'),
|
||||
},
|
||||
{
|
||||
key: 'TextInputExample',
|
||||
module: require('./TextInputExample.ios'),
|
||||
},
|
||||
{
|
||||
key: 'TouchableExample',
|
||||
module: require('./TouchableExample'),
|
||||
},
|
||||
{
|
||||
key: 'TransparentHitTestExample',
|
||||
module: require('./TransparentHitTestExample'),
|
||||
},
|
||||
{
|
||||
key: 'ViewExample',
|
||||
module: require('./ViewExample'),
|
||||
},
|
||||
{
|
||||
key: 'WebViewExample',
|
||||
module: require('./WebViewExample'),
|
||||
},
|
||||
];
|
||||
|
||||
var APIExamples: Array<UIExplorerExample> = [
|
||||
{
|
||||
key: 'AccessibilityIOSExample',
|
||||
module: require('./AccessibilityIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'ActionSheetIOSExample',
|
||||
module: require('./ActionSheetIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'AdSupportIOSExample',
|
||||
module: require('./AdSupportIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'AlertIOSExample',
|
||||
module: require('./AlertIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'AnimatedExample',
|
||||
module: require('./AnimatedExample'),
|
||||
},
|
||||
{
|
||||
key: 'AnExApp',
|
||||
module: require('./AnimatedGratuitousApp/AnExApp'),
|
||||
},
|
||||
{
|
||||
key: 'AppStateIOSExample',
|
||||
module: require('./AppStateIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'AppStateExample',
|
||||
module: require('./AppStateExample'),
|
||||
},
|
||||
{
|
||||
key: 'AsyncStorageExample',
|
||||
module: require('./AsyncStorageExample'),
|
||||
},
|
||||
{
|
||||
key: 'BorderExample',
|
||||
module: require('./BorderExample'),
|
||||
},
|
||||
{
|
||||
key: 'BoxShadowExample',
|
||||
module: require('./BoxShadowExample'),
|
||||
},
|
||||
{
|
||||
key: 'CameraRollExample',
|
||||
module: require('./CameraRollExample'),
|
||||
},
|
||||
{
|
||||
key: 'ClipboardExample',
|
||||
module: require('./ClipboardExample'),
|
||||
},
|
||||
{
|
||||
key: 'GeolocationExample',
|
||||
module: require('./GeolocationExample'),
|
||||
},
|
||||
{
|
||||
key: 'ImageEditingExample',
|
||||
module: require('./ImageEditingExample'),
|
||||
},
|
||||
{
|
||||
key: 'LayoutExample',
|
||||
module: require('./LayoutExample'),
|
||||
},
|
||||
{
|
||||
key: 'NavigationExperimentalExample',
|
||||
module: require('./NavigationExperimental/NavigationExperimentalExample'),
|
||||
},
|
||||
{
|
||||
key: 'NetInfoExample',
|
||||
module: require('./NetInfoExample'),
|
||||
},
|
||||
{
|
||||
key: 'PanResponderExample',
|
||||
module: require('./PanResponderExample'),
|
||||
},
|
||||
{
|
||||
key: 'PointerEventsExample',
|
||||
module: require('./PointerEventsExample'),
|
||||
},
|
||||
{
|
||||
key: 'PushNotificationIOSExample',
|
||||
module: require('./PushNotificationIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'RCTRootViewIOSExample',
|
||||
module: require('./RCTRootViewIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'StatusBarIOSExample',
|
||||
module: require('./StatusBarIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'TimerExample',
|
||||
module: require('./TimerExample'),
|
||||
},
|
||||
{
|
||||
key: 'TransformExample',
|
||||
module: require('./TransformExample'),
|
||||
},
|
||||
{
|
||||
key: 'VibrationIOSExample',
|
||||
module: require('./VibrationIOSExample'),
|
||||
},
|
||||
{
|
||||
key: 'XHRExample',
|
||||
module: require('./XHRExample.ios'),
|
||||
},
|
||||
];
|
||||
|
||||
const Modules = {};
|
||||
|
||||
APIExamples.concat(ComponentExamples).forEach(Example => {
|
||||
Modules[Example.key] = Example.module;
|
||||
});
|
||||
|
||||
const UIExplorerList = {
|
||||
APIExamples,
|
||||
ComponentExamples,
|
||||
Modules,
|
||||
};
|
||||
|
||||
module.exports = UIExplorerList;
|
||||
|
|
|
@ -1,190 +0,0 @@
|
|||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
ListView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
} = React;
|
||||
var createExamplePage = require('./createExamplePage');
|
||||
|
||||
var ds = new ListView.DataSource({
|
||||
rowHasChanged: (r1, r2) => r1 !== r2,
|
||||
sectionHeaderHasChanged: (h1, h2) => h1 !== h2,
|
||||
});
|
||||
|
||||
class UIExplorerListBase extends React.Component {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = {
|
||||
dataSource: ds.cloneWithRowsAndSections({
|
||||
components: [],
|
||||
apis: [],
|
||||
}),
|
||||
searchText: this.props.searchText || '',
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
this.search(this.state.searchText);
|
||||
}
|
||||
|
||||
render() {
|
||||
var topView = this.props.renderAdditionalView &&
|
||||
this.props.renderAdditionalView(this.renderRow.bind(this), this.renderTextInput.bind(this));
|
||||
|
||||
return (
|
||||
<View style={styles.listContainer}>
|
||||
{topView}
|
||||
<ListView
|
||||
style={styles.list}
|
||||
dataSource={this.state.dataSource}
|
||||
renderRow={this.renderRow.bind(this)}
|
||||
renderSectionHeader={this._renderSectionHeader}
|
||||
keyboardShouldPersistTaps={true}
|
||||
automaticallyAdjustContentInsets={false}
|
||||
keyboardDismissMode="on-drag"
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
renderTextInput(searchTextInputStyle: any) {
|
||||
return (
|
||||
<View style={styles.searchRow}>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
clearButtonMode="always"
|
||||
onChangeText={this.search.bind(this)}
|
||||
placeholder="Search..."
|
||||
style={[styles.searchTextInput, searchTextInputStyle]}
|
||||
testID="explorer_search"
|
||||
value={this.state.searchText}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_renderSectionHeader(data: any, section: string) {
|
||||
return (
|
||||
<Text style={styles.sectionHeader}>
|
||||
{section.toUpperCase()}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
renderRow(example: any, i: number) {
|
||||
return (
|
||||
<View key={i}>
|
||||
<TouchableHighlight onPress={() => this.onPressRow(example)}>
|
||||
<View style={styles.row}>
|
||||
<Text style={styles.rowTitleText}>
|
||||
{example.title}
|
||||
</Text>
|
||||
<Text style={styles.rowDetailText}>
|
||||
{example.description}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
<View style={styles.separator} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
search(text: mixed): void {
|
||||
this.props.search && this.props.search(text);
|
||||
|
||||
var regex = new RegExp(String(text), 'i');
|
||||
var filter = (component) => regex.test(component.title);
|
||||
|
||||
this.setState({
|
||||
dataSource: ds.cloneWithRowsAndSections({
|
||||
components: this.props.components.filter(filter),
|
||||
apis: this.props.apis.filter(filter),
|
||||
}),
|
||||
searchText: text,
|
||||
});
|
||||
}
|
||||
|
||||
onPressRow(example: any): void {
|
||||
this.props.onPressRow && this.props.onPressRow(example);
|
||||
}
|
||||
|
||||
static makeRenderable(example: any): ReactClass<any, any, any> {
|
||||
return example.examples ?
|
||||
createExamplePage(null, example) :
|
||||
example;
|
||||
}
|
||||
}
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
listContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
list: {
|
||||
backgroundColor: '#eeeeee',
|
||||
},
|
||||
sectionHeader: {
|
||||
padding: 5,
|
||||
fontWeight: '500',
|
||||
fontSize: 11,
|
||||
},
|
||||
group: {
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
row: {
|
||||
backgroundColor: 'white',
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 8,
|
||||
},
|
||||
separator: {
|
||||
height: StyleSheet.hairlineWidth,
|
||||
backgroundColor: '#bbbbbb',
|
||||
marginLeft: 15,
|
||||
},
|
||||
rowTitleText: {
|
||||
fontSize: 17,
|
||||
fontWeight: '500',
|
||||
},
|
||||
rowDetailText: {
|
||||
fontSize: 15,
|
||||
color: '#888888',
|
||||
lineHeight: 20,
|
||||
},
|
||||
searchRow: {
|
||||
backgroundColor: '#eeeeee',
|
||||
paddingTop: 75,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
paddingBottom: 10,
|
||||
},
|
||||
searchTextInput: {
|
||||
backgroundColor: 'white',
|
||||
borderColor: '#cccccc',
|
||||
borderRadius: 3,
|
||||
borderWidth: 1,
|
||||
paddingLeft: 8,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = UIExplorerListBase;
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const React = require('react-native');
|
||||
// $FlowFixMe : This is a platform-forked component, and flow seems to only run on iOS?
|
||||
const UIExplorerList = require('./UIExplorerList');
|
||||
const {
|
||||
NavigationExperimental,
|
||||
} = React;
|
||||
const {
|
||||
Reducer: NavigationReducer,
|
||||
} = NavigationExperimental;
|
||||
const StackReducer = NavigationReducer.StackReducer;
|
||||
|
||||
import type {NavigationState} from 'NavigationStateUtils';
|
||||
|
||||
import type {UIExplorerAction} from './UIExplorerActions';
|
||||
|
||||
export type UIExplorerNavigationState = {
|
||||
externalExample: ?string;
|
||||
stack: NavigationState;
|
||||
};
|
||||
|
||||
const UIExplorerStackReducer = StackReducer({
|
||||
key: 'UIExplorerMainStack',
|
||||
initialStates: [
|
||||
{key: 'AppList'},
|
||||
],
|
||||
initialIndex: 0,
|
||||
matchAction: action => action.openExample && !!UIExplorerList.Modules[action.openExample],
|
||||
actionStateMap: action => ({ key: action.openExample, }),
|
||||
});
|
||||
|
||||
function UIExplorerNavigationReducer(lastState: ?UIExplorerNavigationState, action: any): UIExplorerNavigationState {
|
||||
if (!lastState) {
|
||||
return {
|
||||
externalExample: null,
|
||||
stack: UIExplorerStackReducer(null, action),
|
||||
};
|
||||
}
|
||||
if (action.type === 'UIExplorerListWithFilterAction') {
|
||||
return {
|
||||
externalExample: null,
|
||||
stack: {
|
||||
key: 'UIExplorerMainStack',
|
||||
index: 0,
|
||||
children: [
|
||||
{
|
||||
key: 'AppList',
|
||||
filter: action.filter,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
if (action.type === 'BackAction' && lastState.externalExample) {
|
||||
return {
|
||||
...lastState,
|
||||
externalExample: null,
|
||||
};
|
||||
}
|
||||
if (action.type === 'UIExplorerExampleAction') {
|
||||
const ExampleModule = UIExplorerList.Modules[action.openExample];
|
||||
if (ExampleModule && ExampleModule.external) {
|
||||
return {
|
||||
...lastState,
|
||||
externalExample: action.openExample,
|
||||
};
|
||||
}
|
||||
}
|
||||
const newStack = UIExplorerStackReducer(lastState.stack, action);
|
||||
if (newStack !== lastState.stack) {
|
||||
return {
|
||||
externalExample: null,
|
||||
stack: UIExplorerStackReducer(null, action),
|
||||
}
|
||||
}
|
||||
return lastState;
|
||||
}
|
||||
|
||||
module.exports = UIExplorerNavigationReducer;
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const UIExplorerList = require('./UIExplorerList.ios');
|
||||
|
||||
import type {NavigationState} from 'NavigationStateUtils';
|
||||
|
||||
function StateTitleMap(state: NavigationState): string {
|
||||
if (UIExplorerList.Modules[state.key]) {
|
||||
return UIExplorerList.Modules[state.key].title
|
||||
}
|
||||
if (state.key === 'AppList') {
|
||||
return 'UIExplorer';
|
||||
}
|
||||
return 'Unknown';
|
||||
}
|
||||
|
||||
module.exports = StateTitleMap;
|
|
@ -17,6 +17,7 @@ const BackAndroid = require('BackAndroid');
|
|||
const Platform = require('Platform');
|
||||
|
||||
import type {
|
||||
NavigationAction,
|
||||
NavigationState,
|
||||
NavigationReducer
|
||||
} from 'NavigationStateUtils';
|
||||
|
@ -38,6 +39,7 @@ type Props = {
|
|||
renderNavigation: NavigationRenderer;
|
||||
reducer: NavigationReducer;
|
||||
persistenceKey: ?string;
|
||||
initialAction: NavigationAction;
|
||||
};
|
||||
|
||||
class NavigationRootContainer extends React.Component {
|
||||
|
@ -47,7 +49,7 @@ class NavigationRootContainer extends React.Component {
|
|||
this.handleNavigation = this.handleNavigation.bind(this);
|
||||
let navState = null;
|
||||
if (!this.props.persistenceKey) {
|
||||
navState = this.props.reducer(null, null);
|
||||
navState = this.props.reducer(null, props.initialAction);
|
||||
}
|
||||
this.state = { navState };
|
||||
}
|
||||
|
@ -56,7 +58,7 @@ class NavigationRootContainer extends React.Component {
|
|||
AsyncStorage.getItem(this.props.persistenceKey, (err, storedString) => {
|
||||
if (err || !storedString) {
|
||||
this.setState({
|
||||
navState: this.props.reducer(null, null),
|
||||
navState: this.props.reducer(null, this.props.initialAction),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -97,6 +99,12 @@ NavigationRootContainer.childContextTypes = {
|
|||
onNavigate: React.PropTypes.func,
|
||||
};
|
||||
|
||||
NavigationRootContainer.defaultProps = {
|
||||
initialAction: {
|
||||
type: 'NavigationRootContainerInitialAction',
|
||||
},
|
||||
};
|
||||
|
||||
NavigationRootContainer.getBackAction = getBackAction;
|
||||
|
||||
module.exports = NavigationRootContainer;
|
||||
|
|
|
@ -30,11 +30,6 @@ export type NavigationAction = {
|
|||
export type NavigationReducer = (
|
||||
state: ?NavigationState,
|
||||
action: ?NavigationAction
|
||||
) => ?NavigationState;
|
||||
|
||||
export type NavigationReducerWithDefault = (
|
||||
state: ?NavigationState,
|
||||
action: ?any
|
||||
) => NavigationState;
|
||||
|
||||
function getParent(state: NavigationState): ?NavigationParentState {
|
||||
|
|
|
@ -22,16 +22,16 @@ import type {
|
|||
NavigationReducer
|
||||
} from 'NavigationStateUtils';
|
||||
|
||||
function NavigationFindReducer(reducers: Array<NavigationReducer>): NavigationReducer {
|
||||
return function(lastState: ?NavigationState, action: ?any): ?NavigationState {
|
||||
function NavigationFindReducer(reducers: Array<NavigationReducer>, defaultState: NavigationState): NavigationReducer {
|
||||
return function(lastState: ?NavigationState, action: ?any): NavigationState {
|
||||
for (let i = 0; i < reducers.length; i++) {
|
||||
let reducer = reducers[i];
|
||||
let newState = reducer(lastState, action);
|
||||
if (newState !== lastState) {
|
||||
return newState;
|
||||
return newState || defaultState;
|
||||
}
|
||||
}
|
||||
return lastState;
|
||||
return lastState || defaultState;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -16,14 +16,12 @@ const NavigationStateUtils = require('NavigationStateUtils');
|
|||
|
||||
import type {
|
||||
NavigationReducer,
|
||||
NavigationReducerWithDefault,
|
||||
NavigationState,
|
||||
NavigationParentState
|
||||
} from 'NavigationStateUtils';
|
||||
|
||||
const ActionTypes = {
|
||||
JUMP_TO: 'react-native/NavigationExperimental/tabs-jumpTo',
|
||||
ON_TAB_ACTION: 'react-native/NavigationExperimental/tabs-onTabAction',
|
||||
};
|
||||
|
||||
const DEFAULT_KEY = 'TABS_STATE_DEFAULT_KEY';
|
||||
|
@ -39,37 +37,21 @@ function NavigationTabsJumpToAction(index: number): JumpToAction {
|
|||
};
|
||||
}
|
||||
|
||||
export type OnTabAction = {
|
||||
type: string,
|
||||
index: number,
|
||||
action: any,
|
||||
};
|
||||
function NavigationTabsOnTabAction(index: number, action: any): OnTabAction {
|
||||
return {
|
||||
type: ActionTypes.ON_TAB_ACTION,
|
||||
index,
|
||||
action,
|
||||
};
|
||||
}
|
||||
|
||||
type TabsReducerConfig = {
|
||||
key: string;
|
||||
initialIndex: ?number;
|
||||
tabReducers: Array<NavigationReducerWithDefault>;
|
||||
initialIndex: number;
|
||||
tabReducers: Array<NavigationReducer>;
|
||||
};
|
||||
|
||||
function NavigationTabsReducer({key, initialIndex, tabReducers}: TabsReducerConfig): NavigationReducer {
|
||||
if (initialIndex == null) {
|
||||
initialIndex = 0;
|
||||
}
|
||||
if (key == null) {
|
||||
key = DEFAULT_KEY;
|
||||
}
|
||||
return function(lastNavState: ?NavigationState, action: ?any): ?NavigationState {
|
||||
return function(lastNavState: ?NavigationState, action: ?any): NavigationState {
|
||||
if (!lastNavState) {
|
||||
lastNavState = {
|
||||
children: tabReducers.map(reducer => reducer(null, null)),
|
||||
index: initialIndex,
|
||||
index: initialIndex || 0,
|
||||
key,
|
||||
};
|
||||
}
|
||||
|
@ -86,37 +68,17 @@ function NavigationTabsReducer({key, initialIndex, tabReducers}: TabsReducerConf
|
|||
action.index,
|
||||
);
|
||||
}
|
||||
if (action.type === ActionTypes.ON_TAB_ACTION) {
|
||||
const onTabAction: OnTabAction = action;
|
||||
const lastTabRoute = lastParentNavState.children[onTabAction.index];
|
||||
const tabReducer = tabReducers[onTabAction.index];
|
||||
if (tabReducer) {
|
||||
const newTabRoute = tabReducer(lastTabRoute, action.action);
|
||||
if (newTabRoute && newTabRoute !== lastTabRoute) {
|
||||
let navState = NavigationStateUtils.replaceAtIndex(
|
||||
lastParentNavState,
|
||||
onTabAction.index,
|
||||
newTabRoute
|
||||
);
|
||||
navState = NavigationStateUtils.jumpToIndex(
|
||||
navState,
|
||||
onTabAction.index
|
||||
);
|
||||
return navState;
|
||||
}
|
||||
}
|
||||
}
|
||||
const subReducers = tabReducers.map((tabReducer, tabIndex) => {
|
||||
return function reduceTab(lastNavState: ?NavigationState, tabAction: ?any): ?NavigationState {
|
||||
if (!tabReducer || !lastNavState) {
|
||||
return lastNavState;
|
||||
return function(navState: ?NavigationState, tabAction: any): NavigationState {
|
||||
if (!navState) {
|
||||
return lastParentNavState;
|
||||
}
|
||||
const lastParentNavState = NavigationStateUtils.getParent(lastNavState);
|
||||
const lastSubTabState = lastParentNavState && lastParentNavState.children[tabIndex];
|
||||
const nextSubTabState = tabReducer(lastSubTabState, tabAction);
|
||||
if (nextSubTabState && lastSubTabState !== nextSubTabState) {
|
||||
const tabs = lastParentNavState && lastParentNavState.children || [];
|
||||
tabs[tabIndex] = nextSubTabState;
|
||||
const parentState = NavigationStateUtils.getParent(navState);
|
||||
const tabState = parentState && parentState.children[tabIndex];
|
||||
const nextTabState = tabReducer(tabState, tabAction);
|
||||
if (nextTabState && tabState !== nextTabState) {
|
||||
const tabs = parentState && parentState.children || [];
|
||||
tabs[tabIndex] = nextTabState;
|
||||
return {
|
||||
...lastParentNavState,
|
||||
tabs,
|
||||
|
@ -128,8 +90,8 @@ function NavigationTabsReducer({key, initialIndex, tabReducers}: TabsReducerConf
|
|||
});
|
||||
let selectedTabReducer = subReducers.splice(lastParentNavState.index, 1)[0];
|
||||
subReducers.unshift(selectedTabReducer);
|
||||
subReducers.push((lastParentNavState: ?NavigationState, action: ?any) => {
|
||||
if (lastParentNavState && action && action.type === 'BackAction') {
|
||||
subReducers.push(function(navState: ?NavigationState, action: any): NavigationState {
|
||||
if (navState && action.type === 'BackAction') {
|
||||
return NavigationStateUtils.jumpToIndex(
|
||||
lastParentNavState,
|
||||
0
|
||||
|
@ -137,12 +99,11 @@ function NavigationTabsReducer({key, initialIndex, tabReducers}: TabsReducerConf
|
|||
}
|
||||
return lastParentNavState;
|
||||
});
|
||||
const findReducer = NavigationFindReducer(subReducers);
|
||||
const findReducer = NavigationFindReducer(subReducers, lastParentNavState);
|
||||
return findReducer(lastParentNavState, action);
|
||||
};
|
||||
}
|
||||
|
||||
NavigationTabsReducer.JumpToAction = NavigationTabsJumpToAction;
|
||||
NavigationTabsReducer.OnTabAction = NavigationTabsOnTabAction;
|
||||
|
||||
module.exports = NavigationTabsReducer;
|
||||
|
|
Loading…
Reference in New Issue