master 40ead26ff616 cached
13 files
33.8 KB
8.7k tokens
32 symbols
1 requests
Download .txt
Repository: SuperDami/react-native-custom-navigation
Branch: master
Commit: 40ead26ff616
Files: 13
Total size: 33.8 KB

Directory structure:
gitextract_lhqzowum/

├── .gitignore
├── .npmignore
├── README.md
├── components/
│   ├── NavBarContainer.js
│   ├── NavBarContent.js
│   └── StaticNavBarContent.js
├── example/
│   ├── demo1.js
│   ├── demo2.js
│   ├── index.ios.js
│   ├── navbar.js
│   └── package.json
├── index.js
└── package.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
config.js

pids
logs
results
public

npm-debug.log
.DS_Store

node_modules
ACCOUNTS
Pods

.env

================================================
FILE: .npmignore
================================================
.*.swp
._*
.DS_Store
.git
.hg
.lock-wscript
.svn
.wafpickle-*
CVS
npm-debug.log
node_modules
example/node_modules

================================================
FILE: README.md
================================================
react-native-custom-navigation
===================
The goal is making a easy navigation router for react-native, you could plug-in different navigation-bar in each view stack, and update navigation-bar background style at any time. The router would provide your navigation-bar a smooth transition animation when push, pop or swipe-back gesture is activating.

Inspired by [react-native-router](https://github.com/t4t5/react-native-router)

Case 1:
Different view stack using different navgation bar

![Example](https://www.dropbox.com/s/3jqguw37buhagu4/demo.gif?dl=1)


Case 2:
Using singleton navigation bar for all views

![Example](https://www.dropbox.com/s/ik6i3x6m2bgirh5/demo2.gif?dl=1)



Install
-------

In your React Native project directory and run:

```npm install react-native-custom-navigation --save```



Demo
-------

In node_modules/react-native-custom-navigation/example directory and run:

```npm install```

In ```index.ios.js```, 2 demos are ready for you.


```javascript
var React = require('react-native');
var Demo1 = require('./demo1');
var Demo2 = require('./demo2');

var {
  AppRegistry,
} = React;

AppRegistry.registerComponent('ReactTest', () => Demo1);
```

Update
-------
0.2.1:
- Not specifying react-native as dependency in package.json
- Demo using react-native 0.11

0.2.0:
- You can pass initial props to your navbar component by
setting **`navbarPassProps`** when pushing a route object.
- You can update current navbar props in current view module by calling **`this.props.updateNavbarProps`**.
- Access the passing props in your navbar module by **`this.props.xxx`**,
- Handle the passing props in **`componentWillMound`** or **`componentWillReceiveProps`** to render navbar UI.
- The usage of these features can be found in the example that had been updated.


Basic Usage
-------

```javascript
var Router = require('react-native-custom-navigation');
```

Your route object should contain component object for the page to render.
I would like setting a back-button component for each view stack, also you can pass this and manage the back-button by your navigation-bar.

```javascript

var BackButton = React.createClass({
  render() {
    return (
      <Text style={{
          alignSelf: 'center',
          textAlign: 'center',
          fontSize: 16,
          color: '#fff',
        }}>Back</Text>)
  }
});

var route = {
  component: FirstView,
  backButton:
  title: 'Root',
  titleStyle: {
    color: '#ddd',
    fontSize: 22
  }
}

var RootController = React.createClass({
  render() {
    return (
      <Router
        backButtonComponent={BackButton}
        initialRoute=route/>);
  }
});

AppRegistry.registerComponent('ReactTest', () => RootController);
```

Here we go.
Now we got a scrollView here, we can have fade-in navbar-background when we scrolling down.

```javascript
var FirstView = React.createClass({
	render() {
		return (
      <ScrollView
        scrollEventThrottle={16}
        onScroll={this._handleScroll}>
        <TouchableHighlight
          onPress={this._push}>
          <View style={styles.buttonView}>
            <Text style={styles.buttonText}>Push with custom navbar</Text>
          </View>
        </TouchableHighlight>
      </ScrollView>
		)
	},

  _handleScroll(e) {
    var alpha = (e.nativeEvent.contentInset.top + e.nativeEvent.contentOffset.y) / 200;
    if (alpha < 0) alpha = 0;
    if (alpha > 1) alpha = 1;

    var style = {backgroundColor: 'rgba(102, 106, 136, ' + alpha +')'};
    this.props.route.updateNavbarStyle(style);
  }

  _push() {
    var navbarContent = (
          <CustomNavbar
            style={{backgroundColor: color}}/>);

    this.props.route.push({
      component: FirstView,
      title: 'title would never show',
      navbarComponent: navbarContent
    });
  },
});
```

You can then navigate further to a new component by calling
```javascript
this.props.route.push()
```

You can set "navbarComponent" as navigation-bar in next route object.
If you want still have the fade-in effect, make sure the background color of your "navbarComponent" is transparent.


Configurations
--------------
The **`<Router />`** object used to initialize the navigation can take the following props:
- `initialRoute` (required)
- `backButtonComponent`
- `navbarComponent`: Set the component as the singleton navbar for all views.
- `navbarPassProps`: Send initial props to your singleton navbar, access it by `this.props.xxx`

The **`this.props.route.push()`** callback prop takes one parameter (a JavaScript object) which can have the following keys:
- `title`
- `titleStyle`
- `component` (required) The next view component
- `navbarComponent`: Set the component as the navbar in this route
- `passProps`: Send object data to your view component. access the data by `this.props.xxx`
- `navbarPassProps`: Send initial data to your navbar, access it by `this.props.xxx`

The **`navbarComponent` and `component`** access route parameter or function by ***`this.props.route`*** which have the following keys:
- `index`
- `previousIndex`(for singleton navbar only)
- `progress`(for singleton navbar only): current transition animation progress (0 - 1)
- ~~`updateNavbarStyle`(view component only)~~
- `push`
- `pop`
- `popToTop`

~~The **`this.props.route.updateNavbarStyle()`** callback prop takes style object which update the style of navbar background~~

**`this.props.route.updateNavbarStyle`** this function had been abandoned, replace with **`this.props.updateBarBackgroundStyle()`** .


Todos
-------

- Less and clear code
- Make transition animation looks naturally when using singleton navbar and stack navbar at same time.

Questions?
---------
feel free to [follow me on Twitter](https://twitter.com/eatdami)

================================================
FILE: components/NavBarContainer.js
================================================
'use strict';

var React = require('react-native');

var NavBarContent = require('./NavBarContent').NavBarContent;
var NavbarBackground = require('./NavBarContent').NavbarBackground;
var StaticNavBarContent = require('./StaticNavBarContent');

var {
  StyleSheet,
  View
} = React;

var NavBarContainer = React.createClass({

  getInitialState: function() {
    return {};
  },

  componentWillReceiveProps: function(newProps) {
    if (!this.props.currentRoute || (this.props.currentRoute.index === null)) {
      newProps.currentRoute.index = 0;
    }

    if (newProps.currentRoute === this.props.currentRoute) {
      return;
    }

    this.setState({
      previousRoute: this.props.currentRoute,
      currentRoute: newProps.currentRoute
    });
  },

  _goBack: function() {
    this.props.onBack(this.props.navigator);
  },

  _goForward: function(route) {
    this.props.onForward(route, this.props.navigator);
  },

  _goFirst: function() {
    this.props.onFirst(this.props.navigator);
  },

  _onAnimationChange: function(progress, fromIndex, toIndex) {
    this.setState({
      progress: progress
    });
  },

  onAnimationStart: function(fromIndex, toIndex) {
    var routeStack = this.props.navState.routeStack;
    var fromRoute = routeStack.length > fromIndex ? routeStack[fromIndex] : null;
    var toRoute = routeStack.length > toIndex ? routeStack[toIndex] : null;
    this.state = {
      previousRoute: fromRoute,
      currentRoute: toRoute,
    };
  },

  onAnimationEnd: function() {

  },

  updateProgress: function(progress, fromIndex, toIndex) {
    this._onAnimationChange(progress, fromIndex, toIndex);
  },

  // We render both the current and the previous navbar (for animation)
  render: function() {

    var currentProps = {
      progress:this.state.progress,
      route:this.state.currentRoute,
    };

    var previousProps = {
      progress:this.state.progress,
      route:this.state.previousRoute,
      willDisappear:true
    };

    var navigatorProps = {
      goForward: this._goForward,
      goBack: this._goBack,
      goFirst: this._goFirst
    };

    var previousContent, currentContent;
    var previousBackground, currentBackground;
    if (this.state.previousRoute) {
      previousBackground = (
        <NavbarBackground
          {...previousProps}
          style={styles.background}/>);

      currentBackground = (
        <NavbarBackground
          {...currentProps}
          style={styles.background}/>);

      currentContent = (
        <NavBarContent
          {...currentProps}
          {...navigatorProps}
          direction={this.state.currentRoute.index - this.state.previousRoute.index}
          backButtonComponent={this.props.backButtonComponent}/>);

      previousContent = (
        <NavBarContent
          {...previousProps}
          {...navigatorProps}
          direction={this.state.currentRoute.index - this.state.previousRoute.index}
          backButtonComponent={this.props.backButtonComponent}/>);

    } else if (this.state.currentRoute){
      currentBackground = (
        <NavbarBackground
          {...currentProps}
          style={styles.background}/>);

      currentContent = (
        <NavBarContent
          {...currentProps}
          {...navigatorProps}
          direction={0}
          backButtonComponent={this.props.backButtonComponent}/>);
    }

    var staticContent;
    if (this.props.navbarComponent) {
      staticContent = (
        <StaticNavBarContent
          previousRoute={this.state.previousRoute}
          currentRoute={this.state.currentRoute}
          progress={this.state.progress}
          navbarComponent={this.props.navbarComponent}
          navbarPassProps={this.props.navbarPassProps}
          {...navigatorProps}/>
        )
    }

    // Using createFragment to prevent 'Each child in an array should have a unique "key" prop.'
    // warning message
    var navbarContents = React.addons.createFragment({
      "staticContent": staticContent,
      "previousCountent" : previousContent,
      "currentContent":currentContent
    });

    return (
      <View style={[styles.navbarContainer, this.props.style]}>
        {previousBackground}
        {currentBackground}
        {navbarContents}
      </View>
    )
  }
});


var styles = StyleSheet.create({
  navbar: {
    position: 'absolute',
    top: 0,
    left: 0,
    height: 64,
    justifyContent: 'center',
    flexDirection: 'row',
  },

  background: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    height: 64,
  },

  navbarContainer: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    height: 64,
    backgroundColor: 'rgba(0,0,0,0)'
  }
});


module.exports = NavBarContainer;


================================================
FILE: components/NavBarContent.js
================================================
'use strict';

var React = require('react-native');
var TimerMixin = require('react-timer-mixin');

var {
  StyleSheet,
  Text,
  View,
  TouchableHighlight,
  Dimensions,
} = React;

var NavbarBackground = React.createClass({
  mixins: [TimerMixin],

  getInitialState: function() {
    return {};
  },

  _initState: function(fadeIn) {
    var state = {};
    state.opacityStart = fadeIn ? 0 : 1;
    state.opacityEnd = fadeIn ? 1 : 0;
    state.progress = 0;
    this.state = state;
  },

  componentWillMount: function() {
    this.props.route.updateBarBackgroundStyle = this._updateBarBackgroundStyle;
    this._initState(false);
  },

  componentWillReceiveProps: function(newProps) {
    if (newProps.route !== this.props.route) {
      this._initState(!this.props.willDisappear);
      if (!this.props.willDisappear) {
        newProps.route.updateBarBackgroundStyle = this._updateBarBackgroundStyle;
      }
    }

    this.state.progress = newProps.progress;
  },

  _updateBarBackgroundStyle: function(style) {
    this.props.route.barBackgroundStyle = style;
    this.setTimeout(this.forceUpdate, 0);
  },

  render() {
    var opacity = (this.state.opacityEnd - this.state.opacityStart) * this.state.progress + this.state.opacityStart;
    var transitionStyle = {
      opacity: opacity,
    };

    return (
      <View style={[this.props.style, transitionStyle, this.props.route.barBackgroundStyle]} />
    );
  }
});

var screen = Dimensions.get('window');
var NavBarContent = React.createClass({
  mixins: [TimerMixin],

  getInitialState: function() {
    return {};
  },

  _initState: function(direction, fadeIn) {
    var state = {};
    state.opacityStart = fadeIn ? 0 : 1;
    state.opacityEnd = fadeIn ? 1 : 0;

    if (direction > 0) {
      state.leftStart = fadeIn ? screen.width : 0;
      state.leftEnd = fadeIn ? 0 : -screen.width;
    } else if (direction < 0) {
      state.leftStart = fadeIn ? -screen.width : 0;
      state.leftEnd = fadeIn ? 0: screen.width;
    } else {
      //todo replace
    }
    this.state = state;
  },

  componentWillMount: function() {
    this._initState(1, false);
    this.props.route.updateNavbarProps = this._updateNavbarProps;
  },

  componentWillReceiveProps: function(newProps) {
    if (this.props.route !== newProps.route) {
      this._initState(newProps.direction, !this.props.willDisappear);
      if (!newProps.willDisappear) {
        newProps.route.updateNavbarProps = this._updateNavbarProps;
      }
    }
  },

  _updateNavbarProps: function(props) {
    this.props.route.navbarProps = props;
    this.setTimeout(this.forceUpdate, 0);
  },

  render() {
    var left = (this.state.leftEnd - this.state.leftStart) * this.props.progress + this.state.leftStart;
    var opacity = (this.state.opacityEnd - this.state.opacityStart) * this.props.progress + this.state.opacityStart;

    var transitionStyle = {
      position: 'absolute',
      opacity: opacity,
      left: left
    };

    var mainContent;
    if (this.props.route.navbarComponent) {
      var navbarProps = this.props.route.navbarProps ? this.props.route.navbarProps : this.props.route.navbarPassProps
      var NavbarComponent = this.props.route.navbarComponent;
      mainContent = (
        <NavbarComponent
          route={{
            index: this.props.route.index,
            push: this.props.goForward,
            pop: this.props.goBack,
            popToTop: this.props.goFirst
          }}
          {...navbarProps}/>
        );
    } else {
      var leftCorner;
      var leftCornerContent;
      var BackButton = this.props.backButtonComponent

      if (this.props.route.index > 0 && BackButton) {
        leftCornerContent = (
          <TouchableHighlight onPress={this.props.goBack} underlayColor="transparent">
            <View style={styles.backView}>
              <BackButton />
            </View>
          </TouchableHighlight>);
      }

      leftCorner = (
        <View
          key='nav-back'
          style={[styles.corner, styles.alignLeft]}>
          {leftCornerContent}
        </View>
      );

      mainContent = [leftCorner];
        if (this.props.route.title) {
          mainContent.push(
            <Text
              key='nav-title'
              style={[styles.title, this.props.route.titleStyle]}
              numberOfLines={1}>{this.props.route.title}</Text>
        );
      }
    }

    return (
      <View style={[styles.navbar, transitionStyle]}>
        {mainContent}
      </View>
    );
  }
});


var styles = StyleSheet.create({
  navbar: {
    position: 'absolute',
    top: 0,
    left: 0,
    height: 64,
    justifyContent: 'center',
    flexDirection: 'row',
  },

  corner: {
    flex: 1,
    left:0,
    top: 18,
    position: 'absolute',
    justifyContent: 'center',
  },

  alignLeft: {
    alignItems: 'flex-start'
  },

  title: {
    position: 'absolute',
    width: screen.width - 100,
    top: 28,
    left: 50,
    fontSize: 18,
    color: '#fff',
    textAlign: 'center',
  },

  backView: {
    width: 44,
    height: 44,
    justifyContent: 'center',
  }
});


module.exports = {
  NavBarContent: NavBarContent,
  NavbarBackground: NavbarBackground,
};


================================================
FILE: components/StaticNavBarContent.js
================================================
'use strict';

var React = require('react-native');
var TimerMixin = require('react-timer-mixin');

var {
  StyleSheet,
  Text,
  View,
  TouchableHighlight
} = React;

var StaticNavBarContent = React.createClass({
  mixins: [TimerMixin],

  getInitialState() {
    return {
      navbarProps: this.props.navbarPassProps
    };
  },

  componentWillMount() {
    this.props.currentRoute &&
      (this.props.currentRoute.updateStaticNavbarProps = this._updateNavbarProps)
  },

  componentWillReceiveProps(newProps) {
    if (this.props.currentRoute !== newProps.currentRoute) {
      newProps.currentRoute.updateStaticNavbarProps = this._updateNavbarProps;
    };
  },

  render() {
    var previousIndex = this.props.previousRoute ? this.props.previousRoute.index : null;
    var index = this.props.currentRoute ? this.props.currentRoute.index : null;

    return (
      <View style={styles.navbar}>
        <this.props.navbarComponent
          route={{
            progress: this.props.progress,
            previousIndex: previousIndex,
            index: index,
            push: this.props.goForward,
            pop: this.props.goBack,
            popToTop: this.props.goFirst
          }}
          {...this.state.navbarProps}/>
      </View>
      );
  },

  _updateNavbarProps(props) {
    this.setTimeout(
      () => {
        this.setState({
          navbarProps: props
        });
      },
      0
    );
  }
});

var styles = StyleSheet.create({
  navbar: {
    position: 'absolute',
    top: 0,
    left: 0,
    height: 64,
    justifyContent: 'center',
    flexDirection: 'row',
  },
});

module.exports = StaticNavBarContent;

================================================
FILE: example/demo1.js
================================================
var React = require('react-native');
var {
	Image,
	View,
  ScrollView,
	StyleSheet,
  Text,
  TouchableHighlight
} = React;

var Router = require('react-native-custom-navigation');

var navbarColors = [
  '#acc7bf',
  '#5e5f67',
  '#c37070',
  '#eae160',
  '#bf7aa3',
  '#b7d967'
];

var NavbarContent = require('./navbar');
var screen = require('Dimensions').get('window');

var BackButton = React.createClass({
  render() {
    return (
        <Text style={{
            alignSelf: 'center',
            textAlign: 'center',
            fontSize: 16,
            color: '#fff',
          }}>Back</Text>)
  }
});

var RootController = React.createClass({
  render() {
    return (
      <Router
        backButtonComponent={BackButton}
        initialRoute={{
          component: DemoView,
          title: 'Root',
          titleStyle: {
            color: '#ddd',
            fontSize: 22
          },
        }}/>);
  }
});

var NavbarWrapper = React.createClass({
  getInitialState() {
    return {};
  },

  componentWillMount() {
    this.setState({
      style: this.props.style
    });
  },

  componentWillReceiveProps(newProps) {
    if (newProps.style !== this.props.style) {
      this.setState({
        style: newProps.style
      });
    }
  },

  render() {
    return (
      <NavbarContent
        goFoward = {this._push}
        goBack = {this.props.route.pop}
        style={this.state.style}/>);
  },

  _push() {
    var colorIndex = this.props.route.index % navbarColors.length;
    var color = navbarColors[colorIndex];

    this.props.route.push({
      component: DemoView,
      navbarComponent: NavbarWrapper,
      navbarPassProps: {
        style: {
          backgroundColor: color
        }
      }
    });
  },
});

var DemoView = React.createClass({
	render() {
    var imageUri = 'https://divnil.com/wallpaper/iphone5/img/app/c/l/clear-your-desktop-wallpaper-for-640x1136-iphone-5-311-46_33a8356f2205d7c0be8727720a21a207_raw.jpg';

		return (
      <View style={styles.container}>
        <ScrollView
          scrollEventThrottle={16}
          onScroll={this._handleScroll}>
          <Image
            style={styles.image}
            source={{uri: imageUri}}>
            <TouchableHighlight
              style={[styles.button, {marginTop: 120}]}
              onPress={this._pushToNext}>
              <View style={styles.buttonView}>
                <Text style={styles.buttonText}>Push</Text>
              </View>
            </TouchableHighlight>
            <TouchableHighlight
              style={styles.button}
              onPress={this._pushToNextCustomNavbar}>
              <View style={styles.buttonView}>
                <Text style={styles.buttonText}>Push with custom navbar</Text>
              </View>
            </TouchableHighlight>
            <TouchableHighlight
              style={styles.button}
              onPress={this._back}>
              <View style={styles.buttonView}>
                <Text style={styles.buttonText}>Back</Text>
              </View>
            </TouchableHighlight>
            <TouchableHighlight
              style={styles.button}
              onPress={this._popToTop}>
              <View style={styles.buttonView}>
                <Text style={styles.buttonText}>Pop to top</Text>
              </View>
            </TouchableHighlight>
            <TouchableHighlight
              style={styles.button}
              onPress={this._changeColor}>
              <View style={styles.buttonView}>
                <Text style={styles.buttonText}>*custom bar become gray</Text>
              </View>
            </TouchableHighlight>
          </Image>
        </ScrollView>
      </View>
		)
	},

  _back() {
    this.props.route.pop();
  },

  _pushToNext() {
    var nextIndex = ++this.props.route.index;

    this.props.route.push({
      component: DemoView,
      title: nextIndex,
      titleStyle: {
        fontSize: 22,
        color: '#eee'
      }
    });
  },

  _pushToNextCustomNavbar() {
    var colorIndex = this.props.route.index % navbarColors.length;
    var color = navbarColors[colorIndex];

    this.props.route.push({
      component: DemoView,
      navbarComponent: NavbarWrapper,
      navbarPassProps: {
        style: {
          backgroundColor: color
        }
      }
    });
  },

  _popToTop() {
    this.props.route.popToTop();
  },

  _changeColor() {
    this.props.updateNavbarProps({
      style: {
        backgroundColor: '#666'
      }
    });
  },

  _handleScroll(e) {
    var alpha = (e.nativeEvent.contentInset.top + e.nativeEvent.contentOffset.y) / 200;
    if (alpha < 0) alpha = 0;
    if (alpha > 1) alpha = 1;

    var style = {backgroundColor: 'rgba(102, 106, 136, ' + alpha +')'};
    this.props.updateBarBackgroundStyle(style);
  }
});

var styles = StyleSheet.create({
  container: {
    width: screen.width,
    height: screen.height,
  },

  buttonView: {
    justifyContent: 'center',
    padding: 4,
    width: 180,
    height: 60,
    backgroundColor: 'rgba(0,0,0,0.5)',
    borderRadius: 4
  },

  button: {
    marginBottom: 40
  },

  buttonText: {
    fontSize: 20,
    textAlign: 'center',
    color: '#fff',
    backgroundColor: 'rgba(0,0,0,0)'
  },

	image: {
    alignItems: 'center',
		width: screen.width,
		height: screen.height * 1.5,
	},
});

module.exports = RootController;

================================================
FILE: example/demo2.js
================================================
var React = require('react-native');
var {
  Image,
  View,
  ScrollView,
  StyleSheet,
  Text,
  TouchableHighlight
} = React;

var Router = require('react-native-custom-navigation');

var navbarColors = [
  '#acc7bf',
  '#5e5f67',
  '#c37070',
  '#eae160',
  '#bf7aa3',
  '#b7d967'
];

var NavbarContent = require('./navbar');
var screen = require('Dimensions').get('window');
var axisWidth = screen.width - 120;

var NavbarWrapper = React.createClass({
  getInitialState() {
    return {
      backgroundColor: this.props.backgroundColor,
      progress: 0
    };
  },

  componentWillReceiveProps(newProps) {
    if (newProps.route !== this.props.route) {
      var route = newProps.route;
      var progress;
      var n = Math.abs(route.previousIndex - route.index) * route.progress;
      if (route.index > route.previousIndex) {
        progress = (route.previousIndex + n) * 0.2;
      } else {
        progress = (route.previousIndex - n) * 0.2;
      }

      this.setState({
        progress : progress
      });
    }

    if (newProps.backgroundColor !== this.props.backgroundColor) {
      this.setState({
        backgroundColor: newProps.backgroundColor
      })
    }
  },

  _push() {
    if (this.props.route.index > 4) {
      return;
    }

    this.props.route.push({
      component: DemoView,
    });
  },

  render() {
    var width = this.state.progress * axisWidth;
    return (
      <View>
        <NavbarContent
          goFoward = {this._push}
          goBack = {this.props.route.pop}
          style={{backgroundColor: '#5e5f67'}} />
        <View style={styles.activity}>
          <View style={styles.axisView}>
            <View style={[styles.progress, {width: width, backgroundColor: this.state.backgroundColor}]}/>
          </View>
        </View>
      </View>
      );
  }
});

var RootController = React.createClass({
  render() {
    return (
      <Router
        navbarComponent={NavbarWrapper}
        navbarPassProps={{
          backgroundColor: '#b7d967'
        }}
        initialRoute={{
          component: DemoView,
        }}/>);
  }
});

var DemoView = React.createClass({
  render() {
    var imageUri = 'https://divnil.com/wallpaper/iphone5/img/app/c/l/clear-your-desktop-wallpaper-for-640x1136-iphone-5-311-46_33a8356f2205d7c0be8727720a21a207_raw.jpg';

    return (
      <View style={styles.container}>
        <Image
          style={styles.image}
          source={{uri: imageUri}}>
          <TouchableHighlight
            style={styles.button}
            onPress={this._pushToNext}>
            <View style={styles.buttonView}>
              <Text style={styles.buttonText}>Push</Text>
            </View>
          </TouchableHighlight>
          <TouchableHighlight
            style={styles.button}
            onPress={this._back}>
            <View style={styles.buttonView}>
              <Text style={styles.buttonText}>Back</Text>
            </View>
          </TouchableHighlight>
          <TouchableHighlight
            style={styles.button}
            onPress={this._popToTop}>
            <View style={styles.buttonView}>
              <Text style={styles.buttonText}>Pop to top </Text>
            </View>
          </TouchableHighlight>
          <TouchableHighlight
            style={styles.button}
            onPress={this._changeColor}>
            <View style={styles.buttonView}>
              <Text style={styles.buttonText}>{'*change progress red'}</Text>
            </View>
          </TouchableHighlight>
        </Image>
      </View>
    )
  },

  _back() {
    this.props.route.pop();
  },

  _pushToNext() {
    if (this.props.route.index > 4) {
      return;
    }

    this.props.route.push({
      component: DemoView,
    });
  },

  _popToTop() {
    this.props.route.popToTop();
  },

  _changeColor() {
    this.props.updateNavbarProps({backgroundColor: 'rgba(255,0,0,1)'});
  }
});

var styles = StyleSheet.create({
  container: {
    width: screen.width,
    height: screen.height,
  },

  buttonView: {
    justifyContent: 'center',
    padding: 4,
    width: 180,
    height: 60,
    backgroundColor: 'rgba(0,0,0,0.5)',
    borderRadius: 4
  },

  button: {
    marginBottom: 40
  },

  buttonText: {
    fontSize: 20,
    textAlign: 'center',
    color: '#fff',
    backgroundColor: 'rgba(0,0,0,0)'
  },

  image: {
    alignItems: 'center',
    width: screen.width,
    height: screen.height,
    justifyContent: 'center'
  },

  activity: {
    position: 'absolute',
    height: 64,
    width: axisWidth,
    top: 0,
    left: (screen.width - axisWidth) / 2
  },

  navbar: {
    width:screen.width,
    height: 64,
    backgroundColor: '#5e5f67',
    justifyContent: 'center'
  },

  axisView: {
    marginTop: 40,
    width: axisWidth,
    height: 8,
    borderRadius: 4,
    backgroundColor : '#fff',
    alignSelf: 'center',
    justifyContent: 'center'
  },

  progress: {
    alignSelf: 'flex-start',
    height: 6,
    borderRadius: 3,
  }
});

module.exports = RootController;

================================================
FILE: example/index.ios.js
================================================
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';

var React = require('react-native');
var Demo1 = require('./demo1');
var Demo2 = require('./demo2');

var {
  AppRegistry,
} = React;

AppRegistry.registerComponent('ReactTest', () => Demo1);

================================================
FILE: example/navbar.js
================================================
'use strict';

var React = require('react-native');

var {
  View,
  Text,
  StyleSheet,
  TouchableHighlight,
} = React;

var screen = require('Dimensions').get('window');
var NavbarContent = React.createClass({
  render() {
    return (
      <View style={[styles.container, this.props.style]}>
        <View style={[styles.corner, styles.leftCorner]}>
          <TouchableHighlight onPress={this.props.goBack} underlayColor="transparent">
            <View style={styles.backView}>
              <Text style={styles.buttonText}>{'<'}</Text>
            </View>
          </TouchableHighlight>
        </View>

        <View style={[styles.corner, styles.rightCorner]}>
          <TouchableHighlight onPress={this.props.goFoward} underlayColor="transparent">
            <View style={styles.backView}>
              <Text style={styles.buttonText}>{'>'}</Text>
            </View>
          </TouchableHighlight>
        </View>

        <Text style={styles.titleText}>{this.props.title}</Text>
      </View>
    )
  },
});

var styles = StyleSheet.create({
  container: {
    width: screen.width,
    height: 64,
    justifyContent: 'center',
  },

  titleText: {
    fontSize: 22,
    color: '#fff',
    textAlign: 'center',
    alignSelf: 'center',
  },

  buttonText: {
    fontSize: 32,
    color: '#111',
    textAlign: 'center',
  },

  corner: {
    top: 20,
    flex: 1,
    position: 'absolute',
    justifyContent: 'center',
  },

  leftCorner: {
    left:0,
  },

  rightCorner: {
    right:0,
  },

  backView: {
    width: 44,
    height: 44,
    justifyContent: 'center',
  }
});

module.exports = NavbarContent;

================================================
FILE: example/package.json
================================================
{
  "name": "sample-react-native-custom-navigation",
  "version": "0.2.1",
  "private": true,
  "scripts": {
    "start": "node_modules/react-native/packager/packager.sh"
  },
  "dependencies": {
    "react-native" : "^0.11.0",
    "react-native-custom-navigation" : "file:../"
  }
}


================================================
FILE: index.js
================================================
'use strict';

var React = require('react-native');

var NavBarContainer = require('./components/NavBarContainer');

var {
  StyleSheet,
  Navigator,
  StatusBarIOS,
  View,
} = React;

var self;
var Router = React.createClass({

  getInitialState: function() {
    self = this;
    return {
      route: null,
      dragStartX: null,
      didSwitchView: null,
    };
  },

  /*
   * This changes the title in the navigation bar
   * It should preferrably be called for "onWillFocus" instad >
   * > but a recent update to React Native seems to break the animation
   */
  onDidFocus: function(route) {
    this.setState({ route: route });
  },

  onBack: function(navigator) {
    if (this.state.route.index > 0) {
      navigator.pop();
    }
  },

  onForward: function(route, navigator) {
    route.index = this.state.route.index + 1 || 1;
    navigator.push(route);
  },

  onFirst: function(navigator) {
    navigator.popToTop();
  },

  renderScene: function(route, navigator) {
    var goForward = function(route) {
      route.index = this.state.route.index + 1 || 1;
      navigator.push(route);
    }.bind(this);

    var goBackwards = function() {
      this.onBack(navigator);
    }.bind(this);

    var goToFirstRoute = function() {
      navigator.popToTop();
    };

    var didStartDrag = function(evt) {
      var x = evt.nativeEvent.pageX;
      if (x < 28) {
        this.setState({
          dragStartX: x,
          didSwitchView: false
        });
        return true;
      }
    }.bind(this);

    // Recognize swipe back gesture for navigation
    var didMoveFinger = function(evt) {
      var draggedAway = ((evt.nativeEvent.pageX - this.state.dragStartX) > 30);
      if (!this.state.didSwitchView && draggedAway) {
        this.onBack(navigator);
        this.setState({ didSwitchView: true });
      }
    }.bind(this);

    // Set to false to prevent iOS from hijacking the responder
    var preventDefault = function(evt) {
      return true;
    };

    var updateNavbarProps = function(props) {
      route.updateNavbarProps && route.updateNavbarProps(props);
      route.updateStaticNavbarProps && route.updateStaticNavbarProps(props);
    }

    var Content = route.component;
    return (
      <View
        style={[styles.container]}
        onStartShouldSetResponder={didStartDrag}
        onResponderMove={didMoveFinger}
        onResponderTerminationRequest={preventDefault}>
        <Content
          route={{
            index:route.index,
            push:goForward,
            pop:goBackwards,
            popToTop:goToFirstRoute,
          }}
          updateBarBackgroundStyle={
            (style)=>{
              route.updateBarBackgroundStyle &&
                route.updateBarBackgroundStyle(style)
            }
          }
          updateNavbarProps={updateNavbarProps}
          {...route.passProps}/>
      </View>
    )

  },

  render: function() {

    // Status bar color
    if (this.props.statusBarColor === "black") {
      StatusBarIOS.setStyle(0);
    } else {
      StatusBarIOS.setStyle(1);
    }

    var navigationBar =
      <NavBarContainer
        navbarComponent={this.props.navbarComponent}
        navbarPassProps={this.props.navbarPassProps}
        currentRoute={this.state.route}
        backButtonComponent={this.props.backButtonComponent}
        onForward={this.onForward}
        onBack={this.onBack}
        onFirst={this.onFirst}/>

    var initialRoute = this.props.initialRoute;
    initialRoute.index = 0;
    return (
      <Navigator
        initialRoute={initialRoute}
        navigationBar={navigationBar}
        renderScene={this.renderScene}
        onDidFocus={this.onDidFocus}/>)
  },
});


var styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});


module.exports = Router;

================================================
FILE: package.json
================================================
{
  "name": "react-native-custom-navigation",
  "version": "0.2.2",
  "description": "A navigation that allow to custom the appearance of navigation bar in your app",
  "main": "index.js",
  "repository": {
    "type": "git",
    "url": "https://github.com/superdami/react-native-custom-navigation.git"
  },
  "keywords": [
    "react",
    "react component",
    "react native",
    "react navigation",
    "ios",
    "navigation",
    "navbar",
    "router"
  ],
  "author": "Chen Zhejun <devsuperdami@gmail.com>",
  "license": "MIT",
  "homepage": "https://github.com/superdami/react-native-custom-navigation",
  "dependencies": {
    "react-timer-mixin" : "*"
  }
}
Download .txt
gitextract_lhqzowum/

├── .gitignore
├── .npmignore
├── README.md
├── components/
│   ├── NavBarContainer.js
│   ├── NavBarContent.js
│   └── StaticNavBarContent.js
├── example/
│   ├── demo1.js
│   ├── demo2.js
│   ├── index.ios.js
│   ├── navbar.js
│   └── package.json
├── index.js
└── package.json
Download .txt
SYMBOL INDEX (32 symbols across 5 files)

FILE: components/NavBarContent.js
  method render (line 50) | render() {
  method render (line 106) | render() {

FILE: components/StaticNavBarContent.js
  method getInitialState (line 16) | getInitialState() {
  method componentWillMount (line 22) | componentWillMount() {
  method componentWillReceiveProps (line 27) | componentWillReceiveProps(newProps) {
  method render (line 33) | render() {
  method _updateNavbarProps (line 53) | _updateNavbarProps(props) {

FILE: example/demo1.js
  method render (line 26) | render() {
  method render (line 38) | render() {
  method getInitialState (line 54) | getInitialState() {
  method componentWillMount (line 58) | componentWillMount() {
  method componentWillReceiveProps (line 64) | componentWillReceiveProps(newProps) {
  method render (line 72) | render() {
  method _push (line 80) | _push() {
  method render (line 97) | render() {
  method _back (line 149) | _back() {
  method _pushToNext (line 153) | _pushToNext() {
  method _pushToNextCustomNavbar (line 166) | _pushToNextCustomNavbar() {
  method _popToTop (line 181) | _popToTop() {
  method _changeColor (line 185) | _changeColor() {
  method _handleScroll (line 193) | _handleScroll(e) {

FILE: example/demo2.js
  method getInitialState (line 27) | getInitialState() {
  method componentWillReceiveProps (line 34) | componentWillReceiveProps(newProps) {
  method _push (line 57) | _push() {
  method render (line 67) | render() {
  method render (line 86) | render() {
  method render (line 100) | render() {
  method _back (line 141) | _back() {
  method _pushToNext (line 145) | _pushToNext() {
  method _popToTop (line 155) | _popToTop() {
  method _changeColor (line 159) | _changeColor() {

FILE: example/navbar.js
  method render (line 14) | render() {
Condensed preview — 13 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (37K chars).
[
  {
    "path": ".gitignore",
    "chars": 144,
    "preview": "lib-cov\n*.seed\n*.log\n*.csv\n*.dat\n*.out\n*.pid\n*.gz\nconfig.js\n\npids\nlogs\nresults\npublic\n\nnpm-debug.log\n.DS_Store\n\nnode_mod"
  },
  {
    "path": ".npmignore",
    "chars": 113,
    "preview": ".*.swp\n._*\n.DS_Store\n.git\n.hg\n.lock-wscript\n.svn\n.wafpickle-*\nCVS\nnpm-debug.log\nnode_modules\nexample/node_modules"
  },
  {
    "path": "README.md",
    "chars": 5734,
    "preview": "react-native-custom-navigation\n===================\nThe goal is making a easy navigation router for react-native, you cou"
  },
  {
    "path": "components/NavBarContainer.js",
    "chars": 4731,
    "preview": "'use strict';\n\nvar React = require('react-native');\n\nvar NavBarContent = require('./NavBarContent').NavBarContent;\nvar N"
  },
  {
    "path": "components/NavBarContent.js",
    "chars": 5184,
    "preview": "'use strict';\n\nvar React = require('react-native');\nvar TimerMixin = require('react-timer-mixin');\n\nvar {\n  StyleSheet,\n"
  },
  {
    "path": "components/StaticNavBarContent.js",
    "chars": 1646,
    "preview": "'use strict';\n\nvar React = require('react-native');\nvar TimerMixin = require('react-timer-mixin');\n\nvar {\n  StyleSheet,\n"
  },
  {
    "path": "example/demo1.js",
    "chars": 5352,
    "preview": "var React = require('react-native');\nvar {\n\tImage,\n\tView,\n  ScrollView,\n\tStyleSheet,\n  Text,\n  TouchableHighlight\n} = Re"
  },
  {
    "path": "example/demo2.js",
    "chars": 5002,
    "preview": "var React = require('react-native');\nvar {\n  Image,\n  View,\n  ScrollView,\n  StyleSheet,\n  Text,\n  TouchableHighlight\n} ="
  },
  {
    "path": "example/index.ios.js",
    "chars": 285,
    "preview": "/**\n * Sample React Native App\n * https://github.com/facebook/react-native\n */\n'use strict';\n\nvar React = require('react"
  },
  {
    "path": "example/navbar.js",
    "chars": 1629,
    "preview": "'use strict';\n\nvar React = require('react-native');\n\nvar {\n  View,\n  Text,\n  StyleSheet,\n  TouchableHighlight,\n} = React"
  },
  {
    "path": "example/package.json",
    "chars": 284,
    "preview": "{\n  \"name\": \"sample-react-native-custom-navigation\",\n  \"version\": \"0.2.1\",\n  \"private\": true,\n  \"scripts\": {\n    \"start\""
  },
  {
    "path": "index.js",
    "chars": 3788,
    "preview": "'use strict';\n\nvar React = require('react-native');\n\nvar NavBarContainer = require('./components/NavBarContainer');\n\nvar"
  },
  {
    "path": "package.json",
    "chars": 670,
    "preview": "{\n  \"name\": \"react-native-custom-navigation\",\n  \"version\": \"0.2.2\",\n  \"description\": \"A navigation that allow to custom "
  }
]

About this extraction

This page contains the full source code of the SuperDami/react-native-custom-navigation GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 13 files (33.8 KB), approximately 8.7k tokens, and a symbol index with 32 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!