├── .gitignore ├── README.md ├── components ├── button.js ├── container.js ├── icon.js └── navbar.js ├── index.js ├── package.json ├── styles.js └── utils.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NavbarNative 2 | A **fully customizable** Navbar component for React-Native. 3 | #### It works for both iOS and Android! 4 | 5 | ![navbar-native-intro](https://cloud.githubusercontent.com/assets/1061849/18530527/3bdab2b6-7ad2-11e6-95e4-1774e625080d.png) 6 | 7 | ![navbar-native-intro-android](https://cloud.githubusercontent.com/assets/1061849/18553248/0970cbd8-7b60-11e6-8b72-ec91f4d98671.png) 8 | 9 | ### Content 10 | - [Installation](#installation) 11 | - [Exported components](#exported-components) 12 | - [Getting started](#getting-started) 13 | - [Images as title](#image-as-title) 14 | - [Transparent navbar](#transparent-navbar) 15 | - [Container API](#container-api) 16 | - [Navbar API](#navbar-api) 17 | - [Demo](#demo) 18 | 19 | ### Installation 20 | ```bash 21 | npm i navbar-native --save 22 | ``` 23 | 24 | ### Pay attention 25 | This package depends on the beautiful [Vector Icons for React Native](https://github.com/oblador/react-native-vector-icons). 26 | 27 | After installing NavbarNative, in order to have **icons working**, please follow instructions about [HOW TO INSTALL AND LINK VECTOR ICONS](https://github.com/oblador/react-native-vector-icons) in your project. 28 | 29 | ### Exported components 30 | This package exports two main components: 31 | 32 | - **Container** - a container component to use as the first component in a __render()__ method. It accepts the "Navbar" component and the rest of the page content. 33 | - **Navbar** - the components which generates the bar on top. 34 | 35 | ### Helper components 36 | 37 | - **Icon** - a Vector Icons for React Native wrapper 38 | 39 | ### Getting started 40 | Basically, the Navbar component accepts a **title** prop and **left** and/or **right** objects (or array of objects) which describe each button that the navbar has to render in the specific position. 41 | 42 | #### Using icons 43 | In order to use the correct set of icons, please use **ios-** prefix in _icon_ prop name for iOS and **md-** prefix for Android. 44 | 45 | The following chunk of code shows a typical **iOS** NavbarNative usage: 46 | 47 | ```js 48 | import React, { Component } from 'react'; 49 | import { View } from 'react-native'; 50 | 51 | import { Container, Navbar } from 'navbar-native'; 52 | 53 | class ReactNativeProject extends Component { 54 | render() { 55 | return ( 56 | 57 | {alert('Go back!')} 63 | }} 64 | right={[{ 65 | icon: "ios-search", 66 | onPress: () => {alert('Search!')} 67 | },{ 68 | icon: "ios-menu", 69 | onPress: () => {alert('Toggle menu!')} 70 | }]} 71 | /> 72 | ... other stuff ... 73 | 74 | ); 75 | } 76 | } 77 | ``` 78 | 79 | ### Image as a title 80 | 81 | ![image_list](https://cloud.githubusercontent.com/assets/1061849/18619404/6b15bb58-7dfb-11e6-917d-9c3ca6547f4f.png) 82 | 83 | You can also use a **remote** or **local** image instead of the text title: 84 | 85 | ```js 86 | class ReactNativeEmpty extends Component { 87 | render() { 88 | return ( 89 | 90 | {alert('Go back!')} 107 | }} 108 | right={[{ 109 | icon: "ios-search", 110 | onPress: () => {alert('Search!')} 111 | },{ 112 | icon: "ios-menu", 113 | onPress: () => {alert('Toggle menu!')} 114 | }]} 115 | /> 116 | 117 | ); 118 | } 119 | } 120 | ``` 121 | 122 | ### Image as background 123 | 124 | ![image-background](https://cloud.githubusercontent.com/assets/1061849/18619959/0e4003b2-7e09-11e6-9ec5-d88a43b0ed2c.png) 125 | 126 | Images can be used in **background** also: 127 | 128 | ```js 129 | class ReactNativeEmpty extends Component { 130 | render() { 131 | return ( 132 | 133 | {alert('Go back!')}, 152 | style:{color: 'white'} 153 | }} 154 | right={[{ 155 | icon: "ios-search", 156 | iconColor: "white", 157 | onPress: () => {alert('Search!')} 158 | },{ 159 | icon: "ios-menu", 160 | iconColor: "white", 161 | onPress: () => {alert('Toggle menu!')} 162 | }]} 163 | /> 164 | 165 | ); 166 | } 167 | } 168 | ``` 169 | 170 | ### Transparent Navbar 171 | 172 | Do you need a **transparent** navbar and a full-page content beneath it? No problem! We've got you covered... 173 | 174 | Just set `bgColor="transparent"` and `theme="dark"` and you can achieve something like this: 175 | 176 | ![transparent_navbar](https://cloud.githubusercontent.com/assets/1061849/18752282/39d75436-80e2-11e6-86a5-92c848446a6d.png) 177 | 178 | ### Using badges 179 | 180 | ![ios-badge](https://cloud.githubusercontent.com/assets/1061849/20268744/bd13b304-aa80-11e6-8628-73c49b6a9755.png) 181 | 182 | ```js 183 | export default class ReactNativeEmpty extends Component { 184 | render() { 185 | 186 | const left = { 187 | role: 'menu', 188 | badge: { 189 | value: 4, 190 | bgColor: '#ffcc00', 191 | textColor: 'black' 192 | } 193 | }; 194 | 195 | return ( 196 | 197 | 198 | 199 | ); 200 | } 201 | } 202 | ``` 203 | 204 | ### Container API 205 | - **bgColor** - (String def. '#ffffff') - Background color for the Container, the one you see overscrolling 206 | - **data** - (Array of strings or Array of Objects opt.) - data source for ListView 207 | - **row** - (Function opt.) - A function that renders the single row element in ListView (accepts 'rowData', 'sectionID') 208 | - **style** - (Object opt.) - Custom styles for the container 209 | - **loading** - (Object opt.) - Prop to use in order to trigger the included loading screen [SPINNER INSTALLATION INSTRUCTIONS](https://github.com/maxs15/react-native-spinkit) 210 | - **spinner** - (String def. 'ThreeBounce') - Type of spinner animation from [HERE](https://github.com/maxs15/react-native-spinkit) 211 | - **spinnerColor** - (String def. '#ffffff') - Color of the spinner 212 | - **spinnerSize** - (Number def. 50) - Size of the spinner 213 | - **bgColor** - (String def. 'rgba(0,0,0,.8)') - Color to apply in the background 214 | - **message** - (String opt.) - Loading text message to display 215 | - **messageColor** - (String def. '#ffffff') - Color of the loading text message 216 | - **styleContainer** - (Object opt.) - Additional style for the loading screen 217 | - **styleText** - (Object opt.) - Additional style for the loading text 218 | - **type** - ('scroll' or 'list' def. 'scroll') - How to render Container children content 219 | - **height** - (Number def. screen height) - Set the height of the container 220 | 221 | ### Navbar API 222 | - **theme** - ('light' or 'dark' - def. 'light' iOS / 'dark' Android) - Base theme for the NavigationBar 223 | - **title** - (String or Component opt.) - The title element. Component needs to be styled accordingly. 224 | - **titleColor** - (String opt.) - The title string color 225 | - **bgColor** - (String def. light: ios #f2f2f2 android #f5f5f5 dark: ios #2b2b2b android #212121 ) - NavigationBar's background color 226 | - **image** - (Object opt.) - Local/remote image instead of the title 227 | - **source** - (require(String) for local or String for remote uri) - Local/remote image location 228 | - **type** - ('local' or 'remote' def. 'local') - Origin of the image 229 | - **resizeMode** - ('cover', 'contain', 'stretch', 'repeat', 'center' def. 'cover' local - 'contain' remote) 230 | - **style** - (Object opt.) - Additional styles for image title 231 | - **imageBackground** - (Object opt.) - Local/remote image in navbar background 232 | - **source** - (String) - Local/remote image location 233 | - **type** - ('local' or 'remote' def. 'local') - Origin of the image 234 | - **resizeMode** - ('cover', 'contain', 'stretch', 'repeat', 'center' def. 'cover') 235 | - **style** - (Object opt.) - Additional styles for image background 236 | - **statusBar** - (Object opt.): 237 | - **style** - ('light-content' or 'default') - Style of StatusBar 238 | - **hidden** - (Boolean) - Show or not StatusBar 239 | - **bgColor** - (String) - StatusBar background color 240 | - **animation** - (Boolean def. true) - Animation between StatusBar transitions 241 | - **transition** - ('fade' or 'slide' def. 'fade') - Type of StatusBar transition animation when hiding it 242 | - **left / right** - (Object or Array of Objects or React component / return function): 243 | - **icon** - (String opt.) - Vector Icon's icon name 244 | - **iconFamily** - (String def. Ionicons) - Vector Icon's icon library 245 | - **iconPos** - ('left' or 'right' def. left/right position) - Icon's position towards the label 246 | - **iconSize** - (Number def. 30 ios - 28 android) - Icon's size 247 | - **iconColor** - (String def. light: ios #387afe android #707070 dark: ios #ffffff android #ffffff ) - Icon's color 248 | - **label** - (String opt.) - Button's label 249 | - **badge** - (Number, String or Object opt.) 250 | - **value** - (Number or String) - The value in the badge 251 | - **bgColor** - (String opt.) - Badge background color 252 | - **textColor** - (String opt.) - Badge text color 253 | - **position** - ('left' or 'right' def. 'right') - Badge position in the button 254 | - **onPress** - (Function) - onPress function handler 255 | - **disabled** - (Boolean def. false) - It renders a button in a disabled status 256 | - **role** - (String opt. - 'back' | 'close' | 'login' | 'menu') - Button's pre-defined aspect 257 | - **style** - (Object opt.) - Button's override styles 258 | - **style** - (Object) - Custom styles for the navbar 259 | - **user** - (Object, Bool) - Authenticated user 260 | - **elevation** - (Number) - (Android-only) Elevation of the toolbar 261 | 262 | ### Icon API 263 | - **family** - (String def. 'Ionicons') - Font family for icons 264 | - **name** - (String) - Name of the icon to show 265 | - **color** - (String def. iOS '#387afe' android '#707070') - Color of the icon 266 | 267 | ### Demo 268 | 269 | [MeteorNative](https://github.com/redbaron76/MeteorNative) is a full featured **boilerplate** which brings together **React-Native** and **Meteor js**. 270 | 271 | In this project I implement **navbar-native** in many ways and you can see in action specific usages of this package. 272 | 273 | ![react-native-intro](https://cloud.githubusercontent.com/assets/1061849/18746036/5db45830-80c5-11e6-8222-1813798c8cd4.gif) 274 | -------------------------------------------------------------------------------- /components/button.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import {Text, TouchableOpacity, View} from 'react-native'; 4 | import Navbar from './navbar'; 5 | import styles, { theme } from '../styles'; 6 | 7 | const MARGIN = 4; 8 | 9 | export default class Button extends Component { 10 | 11 | constructor(props) { 12 | super(props); 13 | 14 | this.hasIcon = false; 15 | this.hasLabel = false; 16 | } 17 | 18 | renderButtonElements() { 19 | if (Array.isArray(this.props.children)) { 20 | const buttonElements = React.Children.map(this.props.children, (child) => { 21 | if (child) { 22 | switch (true) { 23 | case (child && typeof child === 'object'): 24 | return 25 | {React.cloneElement(child, { 26 | style: [ 27 | this._setIconLabelMargins(this.props), 28 | this.props.iconStyle 29 | ] 30 | })} 31 | ; 32 | case (child && typeof child == 'string'): 33 | return 39 | {child} 40 | ; 41 | } 42 | } 43 | }); 44 | return ( 45 | 46 | {buttonElements} 47 | 48 | ); 49 | } 50 | } 51 | 52 | renderBadge() { 53 | if ( 54 | (typeof this.props.badge === 'string' && !!this.props.badge) || 55 | (typeof this.props.badge === 'number' && !!this.props.badge) || 56 | (typeof this.props.badge === 'object' && !!this.props.badge.value) 57 | ) { 58 | 59 | let value = this.props.badge; 60 | let badgeBgColor = theme[this.props.theme].badgeBgColor; 61 | let badgeTextColor = theme[this.props.theme].badgeTextColor; 62 | 63 | let position = {}; 64 | position[Navbar.RIGHT] = -7; 65 | 66 | if (typeof this.props.badge === 'object') { 67 | value = this.props.badge.value; 68 | if (this.props.badge.bgColor) badgeBgColor = this.props.badge.bgColor; 69 | if (this.props.badge.textColor) badgeTextColor = this.props.badge.textColor; 70 | if (this.props.badge.position == Navbar.LEFT) { 71 | delete(position[Navbar.RIGHT]); 72 | position[Navbar.LEFT] = -7; 73 | } 74 | } 75 | 76 | return ( 77 | 82 | 86 | {value} 87 | 88 | 89 | ); 90 | } 91 | } 92 | 93 | render() { 94 | this._computeIconLabel(); 95 | if (!this.hasIcon && !this.hasLabel) return null; 96 | const disabled = this.props.disabled ? styles.navBarButtonDisabled : {}; 97 | const buttonElements = this.renderButtonElements(); 98 | return ( 99 | 103 | {buttonElements} 104 | {this.renderBadge()} 105 | 106 | ); 107 | } 108 | 109 | _computeIconLabel() { 110 | if (Array.isArray(this.props.children)) { 111 | const child = this.props.children; 112 | if (child[0] || child[2]) this.hasIcon = true; 113 | if (child[1]) this.hasLabel = true; 114 | } 115 | } 116 | 117 | _setButtonMargins() { 118 | 119 | switch (true) { 120 | case (this.props.btnLeft): 121 | switch (true) { 122 | case (this.hasIcon && !this.hasLabel): 123 | return { 124 | marginLeft: MARGIN, 125 | marginRight: MARGIN * 3, 126 | }; 127 | default: 128 | return { 129 | marginRight: MARGIN * 2 130 | }; 131 | } 132 | case (this.props.btnRight): 133 | switch (true) { 134 | case (this.hasIcon && !this.hasLabel): 135 | return { 136 | marginLeft: MARGIN * 3, 137 | marginRight: MARGIN, 138 | }; 139 | default: 140 | return { 141 | marginLeft: MARGIN * 2 142 | }; 143 | } 144 | } 145 | } 146 | 147 | _setIconLabelMargins(props) { 148 | 149 | switch (true) { 150 | case (this.props.btnLeft): 151 | switch (true) { 152 | case (props && props.iconPos && props.iconPos == 'right'): 153 | return { 154 | marginRight: MARGIN 155 | }; 156 | case (!this.hasIcon && this.hasLabel): 157 | return { 158 | marginLeft: 0 159 | }; 160 | case (this.hasIcon && !this.hasLabel): 161 | return { 162 | marginLeft: MARGIN * 2 163 | }; 164 | case (this.hasIcon && this.hasLabel): 165 | return { 166 | marginLeft: MARGIN 167 | }; 168 | } 169 | case (this.props.btnRight): 170 | switch (true) { 171 | case (props && props.iconPos && props.iconPos == 'left'): 172 | return { 173 | marginLeft: MARGIN 174 | }; 175 | case (!this.hasIcon && this.hasLabel): 176 | return { 177 | marginRight: 0 178 | }; 179 | case (this.hasIcon && !this.hasLabel): 180 | return { 181 | marginRight: MARGIN * 2 182 | }; 183 | case (this.hasIcon && this.hasLabel): 184 | return { 185 | marginRight: MARGIN 186 | }; 187 | } 188 | default: 189 | return { 190 | marginLeft: 0, 191 | marginRight: 0, 192 | } 193 | } 194 | } 195 | 196 | static propTypes = { 197 | style: PropTypes.oneOfType([ 198 | PropTypes.object, 199 | PropTypes.array, 200 | ]), 201 | iconStyle: PropTypes.oneOfType([ 202 | PropTypes.object, 203 | PropTypes.array, 204 | ]), 205 | btnLeft: PropTypes.bool, 206 | btnRight: PropTypes.bool, 207 | onPress: PropTypes.func, 208 | disabled: PropTypes.bool, 209 | theme: PropTypes.string, 210 | customStyle: PropTypes.object, 211 | badge: PropTypes.oneOfType([ 212 | PropTypes.object, 213 | PropTypes.number, 214 | PropTypes.string 215 | ]), 216 | }; 217 | }; 218 | -------------------------------------------------------------------------------- /components/container.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { ListView, ScrollView, View, Text, Dimensions } from 'react-native'; 4 | import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; 5 | import Spinner from 'react-native-spinkit'; 6 | import Navbar from './navbar'; 7 | import styles from '../styles'; 8 | import { color, size } from '../utils'; 9 | 10 | const SCROLL = 'scroll'; 11 | const LIST = 'list'; 12 | const PLAIN = 'plain'; 13 | 14 | export default class Container extends Component { 15 | 16 | constructor(props) { 17 | super(props); 18 | 19 | const { height } = Dimensions.get('window'); 20 | this.windowHeight = height; 21 | this.navbarHeight = height - (size.navBarHeight + size.statusBarHeight); 22 | this.hasStatusbar = true; 23 | this.hasNavbar = false; 24 | } 25 | 26 | renderLoadingMessage() { 27 | if (this.props.loading && this.props.loading.message) { 28 | return ( 29 | 34 | {this.props.loading.message} 35 | 36 | ); 37 | } 38 | return null; 39 | } 40 | 41 | renderLoading() { 42 | if (this.props.loading) { 43 | return ( 44 | 50 | 51 | 56 | {this.renderLoadingMessage()} 57 | 58 | 59 | ); 60 | }else{ 61 | return 62 | } 63 | } 64 | 65 | renderNavbar() { 66 | this.navbarTransparent = false; 67 | const navbar = React.Children.map(this.props.children, (child) => { 68 | if (child && child.type == Navbar) { 69 | this.hasNavbar = true; 70 | if (child.props.bgColor == 'transparent') { 71 | this.navbarTransparent = true; 72 | this.hasNavbar = false; 73 | } 74 | if (child.props.statusBar && child.props.statusBar.hidden) { 75 | this.hasStatusbar = false; 76 | } 77 | return child; 78 | } 79 | }); 80 | return (navbar) ? navbar : null; 81 | } 82 | 83 | _getDataSource() { 84 | if (this.props.type == LIST && this.props.data) { 85 | const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); 86 | return ds.cloneWithRows(this.props.data); 87 | } 88 | } 89 | 90 | defaultListRow(rowData, sectionID) { 91 | return ( 92 | 93 | {rowData} 94 | 95 | ); 96 | } 97 | 98 | renderContentType(children) { 99 | 100 | let height = (this.hasNavbar) ? this.navbarHeight : this.windowHeight; 101 | 102 | if (!this.hasStatusbar) { 103 | height = height + size.statusBarHeight; 104 | } 105 | 106 | if (this.props.height) { 107 | height = this.props.height; 108 | } 109 | 110 | switch (true) { 111 | case (this.props.type == LIST && !!this.props.data): 112 | return ( 113 | 119 | {children} 120 | 121 | ); 122 | case (this.props.type == PLAIN): 123 | return ( 124 | 127 | {children} 128 | 129 | ); 130 | case (this.props.type == SCROLL): 131 | default: 132 | return ( 133 | 140 | {children} 141 | 142 | ); 143 | } 144 | } 145 | 146 | renderContent() { 147 | const children = React.Children.map(this.props.children, (child) => { 148 | if (child && child.type !== Navbar) { 149 | return child; 150 | } 151 | }); 152 | 153 | const contentStyle = (this.navbarTransparent) ? 154 | Object.assign( 155 | {}, 156 | styles.contentContainer, 157 | styles.contentAbsolute) 158 | : Object.assign( 159 | {}, 160 | styles.contentContainer 161 | ); 162 | 163 | let contentHeight = {}; 164 | if (this.props.height) { 165 | contentHeight = {height: this.props.height}; 166 | } 167 | 168 | return ( 169 | 170 | {this.renderContentType(children)} 171 | 172 | ); 173 | } 174 | 175 | render() { 176 | return ( 177 | 178 | {this.renderLoading()} 179 | {this.renderNavbar()} 180 | {this.renderContent()} 181 | 182 | ); 183 | } 184 | 185 | static SCROLL = SCROLL; 186 | static LIST = LIST; 187 | static PLAIN = PLAIN; 188 | 189 | static loadingShape = { 190 | spinner: PropTypes.string, 191 | spinnerColor: PropTypes.string, 192 | spinnerSize: PropTypes.string, 193 | bgColor: PropTypes.string, 194 | message: PropTypes.string, 195 | messageColor: PropTypes.string, 196 | styleContainer: PropTypes.object, 197 | styleText: PropTypes.object, 198 | coverNavbar:PropTypes.bool, 199 | }; 200 | 201 | static arrayOfObjects = PropTypes.arrayOf(PropTypes.object); 202 | static arrayOfStrings = PropTypes.arrayOf(PropTypes.string); 203 | } 204 | 205 | Container.propTypes = { 206 | data: PropTypes.oneOfType([ 207 | Container.arrayOfStrings, 208 | Container.arrayOfObjects, 209 | ]), 210 | row: PropTypes.func, 211 | contentRef:PropTypes.func, 212 | style: PropTypes.object, 213 | loading: PropTypes.oneOfType([ 214 | PropTypes.bool, 215 | PropTypes.shape(Container.loadingShape), 216 | ]), 217 | type: PropTypes.oneOf([SCROLL, LIST,PLAIN]), 218 | bgColor: PropTypes.string, 219 | height: PropTypes.number, 220 | }; 221 | -------------------------------------------------------------------------------- /components/icon.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import Ionicons from 'react-native-vector-icons/Ionicons'; 5 | import Entypo from 'react-native-vector-icons/Entypo'; 6 | import FontAwesome from 'react-native-vector-icons/FontAwesome'; 7 | import Foundation from 'react-native-vector-icons/Foundation'; 8 | import MaterialIcons from 'react-native-vector-icons/MaterialIcons'; 9 | import Octicons from 'react-native-vector-icons/Octicons'; 10 | import Zocial from 'react-native-vector-icons/Zocial'; 11 | 12 | import styles, { theme } from '../styles'; 13 | import { size } from '../utils'; 14 | 15 | export default class Icon extends Component { 16 | 17 | constructor(props) { 18 | super(props); 19 | 20 | this.theme = (this.props.theme) ? this.props.theme : 'light'; 21 | } 22 | 23 | componentWillMount() { 24 | switch(this.props.family) { 25 | case 'Ionicons': 26 | this.Icon = Ionicons; 27 | break; 28 | case 'Entypo': 29 | this.Icon = Entypo; 30 | break; 31 | case 'FontAwesome': 32 | this.Icon = FontAwesome; 33 | break; 34 | case 'Foundation': 35 | this.Icon = Foundation; 36 | break; 37 | case 'MaterialIcons': 38 | this.Icon = MaterialIcons; 39 | break; 40 | case 'Octicons': 41 | this.Icon = Octicons; 42 | break; 43 | case 'Zocial': 44 | this.Icon = Zocial; 45 | break; 46 | default: 47 | this.Icon = Ionicons; 48 | } 49 | } 50 | 51 | render() { 52 | const color = {color: this.props.color ? this.props.color : theme[this.theme].buttonColor}; 53 | return( 54 | 59 | ); 60 | } 61 | 62 | static propTypes = { 63 | family: PropTypes.string, 64 | name: PropTypes.string, 65 | color: PropTypes.string, 66 | theme: PropTypes.string, 67 | }; 68 | 69 | static defaultProps = { 70 | size: size.iconSize 71 | }; 72 | } 73 | -------------------------------------------------------------------------------- /components/navbar.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { Image, Text, View, Platform, StatusBar } from 'react-native'; 4 | 5 | import Icon from './icon'; 6 | import Button from './button'; 7 | import styles, { theme, size } from '../styles'; 8 | import { isIOS, iOS, iconName, fixIconName } from '../utils'; 9 | 10 | const BACK = 'back'; 11 | const CLOSE = 'close'; 12 | const LOGIN = 'login'; 13 | const MENU = 'menu'; 14 | 15 | const FADE = 'fade'; 16 | const SLIDE = 'slide'; 17 | const NONE = 'none'; 18 | 19 | const DARK = 'dark'; 20 | const LIGHT = 'light'; 21 | 22 | const LEFT = 'left'; 23 | const RIGHT = 'right'; 24 | 25 | export default class Navbar extends Component { 26 | 27 | constructor(props) { 28 | super(props); 29 | 30 | this.hasLeftBtn = !!props.left; 31 | this.hasRightBtn = !!props.right; 32 | this.hasBothBtn = this.hasLeftBtn && this.hasRightBtn; 33 | this.iconPrefix = isIOS() ? 'ios' : 'md'; 34 | this.theme = !!props.theme ? props.theme : isIOS() ? LIGHT : DARK; 35 | } 36 | 37 | _managePress(props) { 38 | switch (true) { 39 | case (props.disabled): 40 | return null; 41 | case (props.role == LOGIN): 42 | switch (true) { 43 | case (!!this.props.user): 44 | return props.onPress; 45 | default: 46 | return props.onPress; 47 | } 48 | case (props.role == MENU): 49 | return props.onPress; 50 | case (props.role == BACK): 51 | return props.onPress; 52 | case (props.role == CLOSE): 53 | return props.onPress; 54 | default: 55 | return props.onPress; 56 | } 57 | } 58 | 59 | _manageJustifyContentContainer() { 60 | switch (true) { 61 | case (this.hasBothBtn): 62 | return { justifyContent : 'space-between' }; 63 | case (this.hasLeftBtn): 64 | return { justifyContent : 'flex-start' }; 65 | case (this.hasRightBtn): 66 | return { justifyContent : 'flex-end' }; 67 | } 68 | } 69 | 70 | renderStatusBar() { 71 | 72 | const customStatusBarBgColor = this.props.statusBar.bgColor ? 73 | { backgroundColor: this.props.statusBar.bgColor } : null; 74 | 75 | switch (true) { 76 | case (!!this.props.statusBar.hidden): 77 | return