mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-02-11 22:32:38 +08:00
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:
committed by
facebook-github-bot-6
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',
|
||||
},
|
||||
|
||||
51
Examples/UIExplorer/UIExplorerActions.js
Normal file
51
Examples/UIExplorer/UIExplorerActions.js
Normal file
@@ -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;
|
||||
|
||||
218
Examples/UIExplorer/UIExplorerExampleList.js
Normal file
218
Examples/UIExplorer/UIExplorerExampleList.js
Normal file
@@ -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;
|
||||
95
Examples/UIExplorer/UIExplorerNavigationReducer.js
Normal file
95
Examples/UIExplorer/UIExplorerNavigationReducer.js
Normal file
@@ -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;
|
||||
32
Examples/UIExplorer/UIExplorerStateTitleMap.js
Normal file
32
Examples/UIExplorer/UIExplorerStateTitleMap.js
Normal file
@@ -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;
|
||||
Reference in New Issue
Block a user