├── .nvmrc ├── .watchmanconfig ├── .env.template ├── assets ├── icon.png ├── icon.psd ├── logos │ ├── ada@2x.png │ ├── bcc@2x.png │ ├── bnb@2x.png │ ├── btc@2x.png │ ├── eos@2x.png │ ├── etc@2x.png │ ├── eth@2x.png │ ├── icx@2x.png │ ├── ltc@2x.png │ ├── neo@2x.png │ ├── ont@2x.png │ ├── qtum@2x.png │ ├── trx@2x.png │ ├── tusd@2x.png │ ├── vet@2x.png │ ├── xlm@2x.png │ ├── xrp@2x.png │ └── miota@2x.png ├── app-store │ ├── icon.png │ └── screenshots │ │ ├── 12.9-1.png │ │ ├── 12.9-2.png │ │ ├── 12.9-3.png │ │ ├── 5.5-1.png │ │ ├── 5.5-2.png │ │ ├── 5.5-3.png │ │ ├── 6.5-1.png │ │ ├── 6.5-2.png │ │ └── 6.5-3.png ├── icon-transparent.png ├── play-store │ ├── icon.png │ ├── feature-graphic.png │ └── screenshots │ │ ├── phone_1.png │ │ ├── phone_2.png │ │ └── phone_3.png └── github │ └── screenshot.png ├── helpers ├── index.js ├── priceFormat │ └── index.js ├── sectorIcons │ └── index.js └── cryptoLogos │ └── index.js ├── constants ├── index.js ├── textStrings │ └── index.js ├── colors │ └── index.js ├── ranges │ └── index.js └── actions │ └── index.js ├── .gitignore ├── store ├── actions │ ├── tabs │ │ └── index.js │ ├── symbol │ │ └── index.js │ ├── autoSuggest │ │ └── index.js │ ├── crypto │ │ └── index.js │ ├── symbols │ │ └── index.js │ ├── losers │ │ └── index.js │ ├── gainers │ │ └── index.js │ ├── sectors │ │ └── index.js │ ├── mostActive │ │ └── index.js │ ├── index.js │ ├── favorites │ │ └── index.js │ └── stock │ │ └── index.js ├── reducers │ ├── symbol │ │ └── index.js │ ├── autoSuggest │ │ └── index.js │ ├── symbols │ │ └── index.js │ ├── sectors │ │ └── index.js │ ├── index.js │ ├── losers │ │ └── index.js │ ├── gainers │ │ └── index.js │ ├── mostActive │ │ └── index.js │ ├── crypto │ │ └── index.js │ ├── tabs │ │ └── index.js │ ├── stock │ │ └── index.js │ └── favorites │ │ └── index.js └── index.js ├── babel.config.js ├── native-base-theme ├── components │ ├── Picker.ios.js │ ├── Spinner.js │ ├── Switch.js │ ├── Tab.js │ ├── Icon.js │ ├── Body.js │ ├── Left.js │ ├── View.js │ ├── Label.js │ ├── H1.js │ ├── H2.js │ ├── H3.js │ ├── Picker.js │ ├── Right.js │ ├── Picker.android.js │ ├── Content.js │ ├── Text.js │ ├── Input.js │ ├── Container.js │ ├── Subtitle.js │ ├── Title.js │ ├── Fab.js │ ├── Textarea.js │ ├── Thumbnail.js │ ├── Radio.js │ ├── TabContainer.js │ ├── Toast.js │ ├── Card.js │ ├── SwipeRow.js │ ├── Badge.js │ ├── TabHeading.js │ ├── CheckBox.js │ ├── Separator.js │ ├── TabBar.js │ ├── Segment.js │ ├── Form.js │ ├── FooterTab.js │ ├── Footer.js │ ├── InputGroup.js │ ├── CardItem.js │ ├── index.js │ ├── Item.js │ ├── Button.js │ ├── Header.js │ └── ListItem.js └── variables │ ├── material.js │ ├── commonColor.js │ └── platform.js ├── .prettierrc ├── components ├── Losers │ └── index.js ├── Crypto │ └── index.js ├── Gainers │ └── index.js ├── MostActive │ └── index.js ├── Favorites │ └── index.js ├── ListHeader │ └── index.js ├── Stock │ ├── News │ │ └── index.js │ ├── index.js │ ├── Save │ │ └── index.js │ ├── Info │ │ └── index.js │ ├── Details │ │ └── index.js │ └── Chart │ │ └── index.js ├── Search │ └── index.js ├── Sectors │ └── index.js ├── AutoSuggest │ └── index.js ├── Tabs │ └── index.js └── List │ └── index.js ├── package.json ├── LICENSE.md ├── README.md ├── app.json └── App.js /.nvmrc: -------------------------------------------------------------------------------- 1 | 14 -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.env.template: -------------------------------------------------------------------------------- 1 | API_KEY=pk_... 2 | -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/icon.png -------------------------------------------------------------------------------- /assets/icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/icon.psd -------------------------------------------------------------------------------- /assets/logos/ada@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/ada@2x.png -------------------------------------------------------------------------------- /assets/logos/bcc@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/bcc@2x.png -------------------------------------------------------------------------------- /assets/logos/bnb@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/bnb@2x.png -------------------------------------------------------------------------------- /assets/logos/btc@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/btc@2x.png -------------------------------------------------------------------------------- /assets/logos/eos@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/eos@2x.png -------------------------------------------------------------------------------- /assets/logos/etc@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/etc@2x.png -------------------------------------------------------------------------------- /assets/logos/eth@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/eth@2x.png -------------------------------------------------------------------------------- /assets/logos/icx@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/icx@2x.png -------------------------------------------------------------------------------- /assets/logos/ltc@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/ltc@2x.png -------------------------------------------------------------------------------- /assets/logos/neo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/neo@2x.png -------------------------------------------------------------------------------- /assets/logos/ont@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/ont@2x.png -------------------------------------------------------------------------------- /assets/logos/qtum@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/qtum@2x.png -------------------------------------------------------------------------------- /assets/logos/trx@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/trx@2x.png -------------------------------------------------------------------------------- /assets/logos/tusd@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/tusd@2x.png -------------------------------------------------------------------------------- /assets/logos/vet@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/vet@2x.png -------------------------------------------------------------------------------- /assets/logos/xlm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/xlm@2x.png -------------------------------------------------------------------------------- /assets/logos/xrp@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/xrp@2x.png -------------------------------------------------------------------------------- /assets/app-store/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/app-store/icon.png -------------------------------------------------------------------------------- /assets/icon-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/icon-transparent.png -------------------------------------------------------------------------------- /assets/logos/miota@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/logos/miota@2x.png -------------------------------------------------------------------------------- /assets/play-store/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/play-store/icon.png -------------------------------------------------------------------------------- /assets/github/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/github/screenshot.png -------------------------------------------------------------------------------- /helpers/index.js: -------------------------------------------------------------------------------- 1 | export * from './cryptoLogos' 2 | export * from './priceFormat' 3 | export * from './sectorIcons' 4 | -------------------------------------------------------------------------------- /assets/play-store/feature-graphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/play-store/feature-graphic.png -------------------------------------------------------------------------------- /assets/app-store/screenshots/12.9-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/app-store/screenshots/12.9-1.png -------------------------------------------------------------------------------- /assets/app-store/screenshots/12.9-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/app-store/screenshots/12.9-2.png -------------------------------------------------------------------------------- /assets/app-store/screenshots/12.9-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/app-store/screenshots/12.9-3.png -------------------------------------------------------------------------------- /assets/app-store/screenshots/5.5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/app-store/screenshots/5.5-1.png -------------------------------------------------------------------------------- /assets/app-store/screenshots/5.5-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/app-store/screenshots/5.5-2.png -------------------------------------------------------------------------------- /assets/app-store/screenshots/5.5-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/app-store/screenshots/5.5-3.png -------------------------------------------------------------------------------- /assets/app-store/screenshots/6.5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/app-store/screenshots/6.5-1.png -------------------------------------------------------------------------------- /assets/app-store/screenshots/6.5-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/app-store/screenshots/6.5-2.png -------------------------------------------------------------------------------- /assets/app-store/screenshots/6.5-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/app-store/screenshots/6.5-3.png -------------------------------------------------------------------------------- /assets/play-store/screenshots/phone_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/play-store/screenshots/phone_1.png -------------------------------------------------------------------------------- /assets/play-store/screenshots/phone_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/play-store/screenshots/phone_2.png -------------------------------------------------------------------------------- /assets/play-store/screenshots/phone_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krestaino/markets-react/HEAD/assets/play-store/screenshots/phone_3.png -------------------------------------------------------------------------------- /constants/index.js: -------------------------------------------------------------------------------- 1 | export * from './actions' 2 | export * from './colors' 3 | export * from './ranges' 4 | export * from './textStrings' 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p12 6 | *.key 7 | *.mobileprovision 8 | .vscode 9 | .DS_Store 10 | .env 11 | -------------------------------------------------------------------------------- /store/actions/tabs/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | export const setTab = index => { 4 | return { 5 | type: Actions.SET_TAB, 6 | payload: index 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true) 3 | return { 4 | presets: [ 5 | 'babel-preset-expo', 6 | 'module:react-native-dotenv' 7 | ] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /store/actions/symbol/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | export const setSymbol = symbol => { 4 | return { 5 | type: Actions.SET_SYMBOL, 6 | payload: symbol 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /constants/textStrings/index.js: -------------------------------------------------------------------------------- 1 | export const TextStrings = { 2 | NO_FAVORITES: 'You don’t have any favorites.\nYou can add them from the Search tab.', 3 | NO_LIST_DATA: 'No data is currently available.' 4 | } 5 | -------------------------------------------------------------------------------- /native-base-theme/components/Picker.ios.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const pickerTheme = {}; 5 | 6 | return pickerTheme; 7 | }; 8 | -------------------------------------------------------------------------------- /store/actions/autoSuggest/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | export const showAutoSuggest = symbol => { 4 | return { 5 | type: Actions.SHOW_AUTOSUGGEST, 6 | payload: symbol 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /native-base-theme/components/Spinner.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const spinnerTheme = { 5 | height: 80 6 | }; 7 | 8 | return spinnerTheme; 9 | }; 10 | -------------------------------------------------------------------------------- /native-base-theme/components/Switch.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const switchTheme = { 5 | marginVertical: -5, 6 | }; 7 | 8 | return switchTheme; 9 | }; 10 | -------------------------------------------------------------------------------- /native-base-theme/components/Tab.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const tabTheme = { 5 | flex: 1, 6 | backgroundColor: "#FFF" 7 | }; 8 | 9 | return tabTheme; 10 | }; 11 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "tabWidth": 2, 4 | "semi": false, 5 | "useTabs": false, 6 | "jsxBracketSameLine": false, 7 | "arrowParens": "avoid", 8 | "singleQuote": true, 9 | "bracketSpacing": true, 10 | "trailingComma": "none" 11 | } 12 | -------------------------------------------------------------------------------- /native-base-theme/components/Icon.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const iconTheme = { 5 | fontSize: variables.iconFontSize, 6 | color: "#000" 7 | }; 8 | 9 | return iconTheme; 10 | }; 11 | -------------------------------------------------------------------------------- /native-base-theme/components/Body.js: -------------------------------------------------------------------------------- 1 | import variable from './../variables/platform'; 2 | 3 | export default (variables = variable) => { 4 | const bodyTheme = { 5 | flex: 1, 6 | alignItems: 'center', 7 | alignSelf: 'center', 8 | }; 9 | 10 | return bodyTheme; 11 | }; 12 | -------------------------------------------------------------------------------- /native-base-theme/components/Left.js: -------------------------------------------------------------------------------- 1 | import variable from './../variables/platform'; 2 | 3 | export default (variables = variable) => { 4 | const leftTheme = { 5 | flex: 1, 6 | alignSelf: 'center', 7 | alignItems: 'flex-start', 8 | }; 9 | 10 | return leftTheme; 11 | }; 12 | -------------------------------------------------------------------------------- /native-base-theme/components/View.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const viewTheme = { 5 | ".padder": { 6 | padding: variables.contentPadding 7 | } 8 | }; 9 | 10 | return viewTheme; 11 | }; 12 | -------------------------------------------------------------------------------- /store/actions/crypto/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | export const getCrypto = () => { 4 | return { 5 | type: Actions.GET_CRYPTO, 6 | payload: { 7 | request: { 8 | url: '/stock/market/crypto' 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /store/actions/symbols/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | export const getSymbols = () => { 4 | return { 5 | type: Actions.GET_SYMBOLS, 6 | payload: { 7 | request: { 8 | url: 'ref-data/symbols' 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /native-base-theme/components/Label.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const labelTheme = { 5 | ".focused": { 6 | width: 0 7 | }, 8 | fontSize: 17 9 | }; 10 | 11 | return labelTheme; 12 | }; 13 | -------------------------------------------------------------------------------- /store/actions/losers/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | export const getLosers = () => { 4 | return { 5 | type: Actions.GET_LOSERS, 6 | payload: { 7 | request: { 8 | url: '/stock/market/list/losers' 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /store/actions/gainers/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | export const getGainers = () => { 4 | return { 5 | type: Actions.GET_GAINERS, 6 | payload: { 7 | request: { 8 | url: '/stock/market/list/gainers' 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /store/actions/sectors/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | export const getSectors = () => { 4 | return { 5 | type: Actions.GET_SECTORS, 6 | payload: { 7 | request: { 8 | url: '/stock/market/sector-performance' 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /constants/colors/index.js: -------------------------------------------------------------------------------- 1 | export const Colors = { 2 | BLUE0: '#15191d', 3 | BLUE1: '#182129', 4 | BLUE2: '#232f3a', 5 | BLUE3: '#2f4356', 6 | BLUE4: '#2582e0', 7 | TEXT_NORMAL: '#bcc6d9', 8 | TEXT_DARK: '#6d788c', 9 | RED: '#d23f31', 10 | GREEN: '#0f9d58', 11 | PINK: '#b257c5' 12 | } 13 | -------------------------------------------------------------------------------- /store/actions/mostActive/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | export const getMostActive = () => { 4 | return { 5 | type: Actions.GET_MOST_ACTIVE, 6 | payload: { 7 | request: { 8 | url: '/stock/market/list/mostactive' 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /native-base-theme/components/H1.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const h1Theme = { 5 | color: variables.textColor, 6 | fontSize: variables.fontSizeH1, 7 | lineHeight: variables.lineHeightH1, 8 | }; 9 | 10 | return h1Theme; 11 | }; 12 | -------------------------------------------------------------------------------- /native-base-theme/components/H2.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const h2Theme = { 5 | color: variables.textColor, 6 | fontSize: variables.fontSizeH2, 7 | lineHeight: variables.lineHeightH2, 8 | }; 9 | 10 | return h2Theme; 11 | }; 12 | -------------------------------------------------------------------------------- /native-base-theme/components/H3.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const h3Theme = { 5 | color: variables.textColor, 6 | fontSize: variables.fontSizeH3, 7 | lineHeight: variables.lineHeightH3 8 | }; 9 | 10 | return h3Theme; 11 | }; 12 | -------------------------------------------------------------------------------- /store/reducers/symbol/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | const initialState = '' 4 | 5 | export const symbol = (state = initialState, action) => { 6 | switch (action.type) { 7 | case Actions.SET_SYMBOL: 8 | return action.payload 9 | default: 10 | return state 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /native-base-theme/components/Picker.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const pickerTheme = { 5 | ".note": { 6 | color: "#8F8E95" 7 | }, 8 | // width: 90, 9 | marginRight: -4, 10 | flexGrow: 1 11 | }; 12 | 13 | return pickerTheme; 14 | }; 15 | -------------------------------------------------------------------------------- /native-base-theme/components/Right.js: -------------------------------------------------------------------------------- 1 | import variable from './../variables/platform'; 2 | 3 | export default (variables = variable) => { 4 | const rightTheme = { 5 | 'NativeBase.Button': { 6 | alignSelf: null, 7 | }, 8 | flex: 1, 9 | alignSelf: 'center', 10 | alignItems: 'flex-end', 11 | }; 12 | 13 | return rightTheme; 14 | }; 15 | -------------------------------------------------------------------------------- /store/reducers/autoSuggest/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | const initialState = false 4 | 5 | export const autoSuggest = (state = initialState, action) => { 6 | switch (action.type) { 7 | case Actions.SHOW_AUTOSUGGEST: 8 | return action.payload 9 | default: 10 | return state 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /native-base-theme/components/Picker.android.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const pickerTheme = { 5 | ".note": { 6 | color: "#8F8E95" 7 | }, 8 | // width: 90, 9 | marginRight: -4, 10 | flexGrow: 1 11 | }; 12 | 13 | return pickerTheme; 14 | }; 15 | -------------------------------------------------------------------------------- /store/actions/index.js: -------------------------------------------------------------------------------- 1 | export * from './stock' 2 | export * from './symbols' 3 | export * from './symbol' 4 | export * from './tabs' 5 | export * from './favorites' 6 | export * from './autoSuggest' 7 | export * from './crypto' 8 | export * from './gainers' 9 | export * from './losers' 10 | export * from './mostActive' 11 | export * from './sectors' 12 | -------------------------------------------------------------------------------- /native-base-theme/components/Content.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const contentTheme = { 5 | flex: 1, 6 | backgroundColor: "transparent", 7 | "NativeBase.Segment": { 8 | borderWidth: 0, 9 | backgroundColor: "transparent" 10 | } 11 | }; 12 | 13 | return contentTheme; 14 | }; 15 | -------------------------------------------------------------------------------- /helpers/priceFormat/index.js: -------------------------------------------------------------------------------- 1 | import { Colors } from '../../constants' 2 | 3 | export const upOrDownSymbol = x => (x > 0 ? '▲' : '▼') 4 | export const formatPercentage = x => (x * 100).toFixed(2) 5 | export const positiveOrNegative = x => (x > 0 ? styles.positive : styles.negative) 6 | 7 | const styles = { 8 | positive: { 9 | color: Colors.GREEN 10 | }, 11 | negative: { 12 | color: Colors.RED 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /native-base-theme/components/Text.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const textTheme = { 5 | fontSize: variables.DefaultFontSize, 6 | fontFamily: variables.fontFamily, 7 | color: variables.textColor, 8 | ".note": { 9 | color: "#a7a7a7", 10 | fontSize: variables.noteFontSize 11 | } 12 | }; 13 | 14 | return textTheme; 15 | }; 16 | -------------------------------------------------------------------------------- /native-base-theme/components/Input.js: -------------------------------------------------------------------------------- 1 | import variable from './../variables/platform'; 2 | 3 | export default (variables = variable) => { 4 | const inputTheme = { 5 | '.multiline': { 6 | height: null, 7 | }, 8 | height: variables.inputHeightBase, 9 | color: variables.inputColor, 10 | paddingLeft: 5, 11 | paddingRight: 5, 12 | flex: 1, 13 | fontSize: variables.inputFontSize 14 | }; 15 | 16 | return inputTheme; 17 | }; 18 | -------------------------------------------------------------------------------- /native-base-theme/components/Container.js: -------------------------------------------------------------------------------- 1 | import { Platform, Dimensions } from "react-native"; 2 | 3 | import variable from "./../variables/platform"; 4 | 5 | const deviceHeight = Dimensions.get("window").height; 6 | export default (variables = variable) => { 7 | const theme = { 8 | flex: 1, 9 | height: Platform.OS === "ios" ? deviceHeight : deviceHeight - 20, 10 | backgroundColor: variables.containerBgColor 11 | }; 12 | 13 | return theme; 14 | }; 15 | -------------------------------------------------------------------------------- /native-base-theme/components/Subtitle.js: -------------------------------------------------------------------------------- 1 | import { Platform } from "react-native"; 2 | 3 | import variable from "./../variables/platform"; 4 | 5 | export default (variables = variable) => { 6 | const subtitleTheme = { 7 | fontSize: variables.subTitleFontSize, 8 | fontFamily: variables.titleFontfamily, 9 | color: variables.subtitleColor, 10 | textAlign: "center", 11 | paddingLeft: Platform.OS === "ios" ? 4 : 0, 12 | marginLeft: Platform.OS === "ios" ? undefined : -3 13 | }; 14 | 15 | return subtitleTheme; 16 | }; 17 | -------------------------------------------------------------------------------- /store/actions/favorites/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | export const clearFavorites = () => { 4 | return { 5 | type: Actions.CLEAR_FAVORITES 6 | } 7 | } 8 | 9 | export const getFavorites = symbols => { 10 | return { 11 | type: Actions.GET_FAVORITES, 12 | payload: { 13 | request: { 14 | url: `/stock/market/batch?symbols=${symbols.join()}&types=quote` 15 | } 16 | } 17 | } 18 | } 19 | 20 | export const toggleFavorite = stock => { 21 | return { 22 | type: Actions.TOGGLE_FAVORITE, 23 | payload: stock 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /native-base-theme/components/Title.js: -------------------------------------------------------------------------------- 1 | import { Platform } from "react-native"; 2 | 3 | import variable from "./../variables/platform"; 4 | 5 | export default (variables = variable) => { 6 | const titleTheme = { 7 | fontSize: variables.titleFontSize, 8 | fontFamily: variables.titleFontfamily, 9 | color: variables.titleFontColor, 10 | fontWeight: Platform.OS === "ios" ? "700" : undefined, 11 | textAlign: "center", 12 | paddingLeft: Platform.OS === "ios" ? 4 : 0, 13 | marginLeft: Platform.OS === "ios" ? undefined : -3, 14 | paddingTop: 1 15 | }; 16 | 17 | return titleTheme; 18 | }; 19 | -------------------------------------------------------------------------------- /store/reducers/symbols/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | const initialState = { data: [], loading: null, error: false } 4 | 5 | export const symbols = (state = initialState, action) => { 6 | switch (action.type) { 7 | case Actions.GET_SYMBOLS: 8 | return { ...state, loading: true } 9 | case Actions.GET_SYMBOLS_SUCCESS: 10 | return { ...state, loading: false, data: action.payload.data } 11 | case Actions.GET_SYMBOLS_FAIL: 12 | return { ...state, loading: false, error: 'Error while fetching symbols.' } 13 | default: 14 | return state 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /constants/ranges/index.js: -------------------------------------------------------------------------------- 1 | export const Ranges = { 2 | ONE_DAY: { 3 | query: '1d', 4 | interval: 6 5 | }, 6 | ONE_MONTH: { 7 | query: '1m', 8 | interval: 1 9 | }, 10 | THREE_MONTHS: { 11 | query: '3m', 12 | interval: 1 13 | }, 14 | SIX_MONTHS: { 15 | query: '6m', 16 | interval: 1 17 | }, 18 | YEAR_TO_DATE: { 19 | query: 'ytd', 20 | interval: 2 21 | }, 22 | ONE_YEAR: { 23 | query: '1y', 24 | interval: 2 25 | }, 26 | TWO_YEARS: { 27 | query: '2y', 28 | interval: 4 29 | }, 30 | FIVE_YEARS: { 31 | query: '5y', 32 | interval: 8 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /native-base-theme/components/Fab.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const platform = variables.platform; 5 | 6 | const fabTheme = { 7 | "NativeBase.Button": { 8 | alignItems: "center", 9 | padding: null, 10 | justifyContent: "center", 11 | "NativeBase.Icon": { 12 | alignSelf: "center", 13 | fontSize: 20, 14 | marginLeft: 0, 15 | marginRight: 0, 16 | }, 17 | "NativeBase.IconNB": { 18 | alignSelf: "center", 19 | fontSize: 20, 20 | marginLeft: 0, 21 | marginRight: 0, 22 | }, 23 | }, 24 | }; 25 | 26 | return fabTheme; 27 | }; 28 | -------------------------------------------------------------------------------- /native-base-theme/components/Textarea.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const textAreaTheme = { 5 | ".underline": { 6 | borderBottomWidth: variables.borderWidth, 7 | marginTop: 5, 8 | borderColor: variables.inputBorderColor 9 | }, 10 | ".bordered": { 11 | borderWidth: 1, 12 | marginTop: 5, 13 | borderColor: variables.inputBorderColor 14 | }, 15 | color: variables.textColor, 16 | paddingLeft: 10, 17 | paddingRight: 5, 18 | fontSize: 15, 19 | textAlignVertical: "top" 20 | }; 21 | 22 | return textAreaTheme; 23 | }; 24 | -------------------------------------------------------------------------------- /store/reducers/sectors/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | const initialState = { data: [], latestUpdate: null, loading: null, error: false } 4 | 5 | export const sectors = (state = initialState, action) => { 6 | switch (action.type) { 7 | case Actions.GET_SECTORS: 8 | return { ...state, latestUpdate: null, loading: true, error: false } 9 | case Actions.GET_SECTORS_SUCCESS: 10 | return { ...state, latestUpdate: new Date(), loading: false, data: action.payload.data } 11 | case Actions.GET_SECTORS_FAIL: 12 | return { ...state, latestUpdate: null, loading: false, error: 'No results found.' } 13 | default: 14 | return state 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /store/actions/stock/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | export const getStock = (symbol, range) => { 4 | return { 5 | type: Actions.GET_STOCK, 6 | payload: { 7 | range: range, 8 | request: { 9 | url: `/stock/${symbol}/batch?types=quote,news,chart&range=${range.query}&chartInterval=${range.interval}` 10 | } 11 | } 12 | } 13 | } 14 | 15 | export const getStockChart = (symbol, range) => { 16 | return { 17 | type: Actions.GET_STOCK_CHART, 18 | payload: { 19 | range: range, 20 | request: { 21 | url: `/stock/${symbol}/batch?types=quote,news,chart&range=${range.query}&chartInterval=${range.interval}` 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /store/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux' 2 | 3 | import { stock } from './stock' 4 | import { symbol } from './symbol' 5 | import { symbols } from './symbols' 6 | import { tabs } from './tabs' 7 | import { favorites } from './favorites' 8 | import { autoSuggest } from './autoSuggest' 9 | import { sectors } from './sectors' 10 | import { gainers } from './gainers' 11 | import { losers } from './losers' 12 | import { mostActive } from './mostActive' 13 | import { crypto } from './crypto' 14 | 15 | export default combineReducers({ 16 | stock, 17 | symbol, 18 | symbols, 19 | tabs, 20 | favorites, 21 | autoSuggest, 22 | sectors, 23 | gainers, 24 | losers, 25 | mostActive, 26 | crypto 27 | }) 28 | -------------------------------------------------------------------------------- /store/reducers/losers/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | const initialState = { data: [], latestUpdate: null, loading: null, error: false } 4 | 5 | export const losers = (state = initialState, action) => { 6 | switch (action.type) { 7 | case Actions.GET_LOSERS: 8 | return { ...state, latestUpdate: null, loading: true, error: false } 9 | case Actions.GET_LOSERS_SUCCESS: 10 | const data = Object.keys(action.payload.data).map(k => action.payload.data[k]) 11 | return { ...state, latestUpdate: new Date(), loading: false, data: data } 12 | case Actions.GET_LOSERS_FAIL: 13 | return { ...state, latestUpdate: null, loading: false, error: 'No results found.' } 14 | default: 15 | return state 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /store/reducers/gainers/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | const initialState = { data: [], latestUpdate: null, loading: null, error: false } 4 | 5 | export const gainers = (state = initialState, action) => { 6 | switch (action.type) { 7 | case Actions.GET_GAINERS: 8 | return { ...state, latestUpdate: null, loading: true, error: false } 9 | case Actions.GET_GAINERS_SUCCESS: 10 | const data = Object.keys(action.payload.data).map(k => action.payload.data[k]) 11 | return { ...state, latestUpdate: new Date(), loading: false, data: data } 12 | case Actions.GET_GAINERS_FAIL: 13 | return { ...state, latestUpdate: null, loading: false, error: 'No results found.' } 14 | default: 15 | return state 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /store/reducers/mostActive/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | const initialState = { data: [], latestUpdate: null, loading: null, error: false } 4 | 5 | export const mostActive = (state = initialState, action) => { 6 | switch (action.type) { 7 | case Actions.GET_MOST_ACTIVE: 8 | return { ...state, latestUpdate: null, loading: true, error: false } 9 | case Actions.GET_MOST_ACTIVE_SUCCESS: 10 | const data = Object.keys(action.payload.data).map(k => action.payload.data[k]) 11 | return { ...state, latestUpdate: new Date(), loading: false, data: data } 12 | case Actions.GET_MOST_ACTIVE_FAIL: 13 | return { ...state, latestUpdate: null, loading: false, error: 'No results found.' } 14 | default: 15 | return state 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /native-base-theme/components/Thumbnail.js: -------------------------------------------------------------------------------- 1 | import variable from './../variables/platform'; 2 | 3 | export default (variables = variable) => { 4 | const thumbnailTheme = { 5 | '.square': { 6 | borderRadius: 0, 7 | '.small': { 8 | width: 36, 9 | height: 36, 10 | borderRadius: 0, 11 | }, 12 | '.large': { 13 | width: 80, 14 | height: 80, 15 | borderRadius: 0, 16 | }, 17 | }, 18 | '.small': { 19 | width: 36, 20 | height: 36, 21 | borderRadius: 18, 22 | '.square': { 23 | borderRadius: 0, 24 | }, 25 | }, 26 | '.large': { 27 | width: 80, 28 | height: 80, 29 | borderRadius: 40, 30 | '.square': { 31 | borderRadius: 0, 32 | }, 33 | }, 34 | width: 56, 35 | height: 56, 36 | borderRadius: 28, 37 | }; 38 | 39 | return thumbnailTheme; 40 | }; 41 | -------------------------------------------------------------------------------- /store/reducers/crypto/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | const initialState = { data: [], latestUpdate: null, loading: null, error: false } 4 | 5 | export const crypto = (state = initialState, action) => { 6 | switch (action.type) { 7 | case Actions.GET_CRYPTO: 8 | return { ...state, latestUpdate: null, loading: true, error: false } 9 | case Actions.GET_CRYPTO_SUCCESS: 10 | const data = Object.keys(action.payload.data).map(k => action.payload.data[k]) 11 | data.sort((a, b) => a.symbol.localeCompare(b.symbol)) 12 | return { ...state, latestUpdate: new Date(), loading: false, data: data } 13 | case Actions.GET_CRYPTO_FAIL: 14 | return { ...state, latestUpdate: null, loading: false, error: 'No results found.' } 15 | default: 16 | return state 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /helpers/sectorIcons/index.js: -------------------------------------------------------------------------------- 1 | const icons = { 2 | Energy: { name: 'bolt', type: 'FontAwesome' }, 3 | CommunicationServices: { name: 'radio-tower', type: 'Octicons' }, 4 | ConsumerDiscretionary: { name: 'beach-access', type: 'MaterialIcons' }, 5 | Materials: { name: 'barrel', type: 'MaterialCommunityIcons' }, 6 | Technology: { name: 'computer', type: 'MaterialIcons' }, 7 | Industrials: { name: 'tools', type: 'Entypo' }, 8 | Financials: { name: 'attach-money', type: 'MaterialIcons' }, 9 | RealEstate: { name: 'home', type: 'MaterialIcons' }, 10 | HealthCare: { name: 'local-hospital', type: 'MaterialIcons' }, 11 | ConsumerStaples: { name: 'food', type: 'MaterialCommunityIcons' }, 12 | Utilities: { name: 'water-pump', type: 'MaterialCommunityIcons' } 13 | } 14 | 15 | export const sectorIcons = sector => icons[sector.replace(/ /g, '')] || false 16 | -------------------------------------------------------------------------------- /components/Losers/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { connect } from 'react-redux' 3 | import { getLosers } from '../../store/actions' 4 | 5 | import List from '../List' 6 | 7 | class Losers extends Component { 8 | onRefresh = () => this.props.getLosers() 9 | 10 | componentDidMount() { 11 | this.props.getLosers() 12 | } 13 | 14 | render() { 15 | const { data, latestUpdate, loading } = this.props.losers 16 | 17 | return ( 18 | 19 | ) 20 | } 21 | } 22 | 23 | const mapStateToProps = state => ({ 24 | losers: state.losers 25 | }) 26 | 27 | const mapDispatchToProps = { 28 | getLosers 29 | } 30 | 31 | export default connect( 32 | mapStateToProps, 33 | mapDispatchToProps 34 | )(Losers) 35 | -------------------------------------------------------------------------------- /store/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import axiosMiddleware from 'redux-axios-middleware' 3 | import storage from 'redux-persist/lib/storage' 4 | import { createStore, applyMiddleware } from 'redux' 5 | import { persistStore, persistReducer } from 'redux-persist' 6 | 7 | import reducers from './reducers' 8 | import { API_KEY } from 'react-native-dotenv' 9 | 10 | const persistConfig = { 11 | key: 'root', 12 | storage, 13 | whitelist: ['favorites'] 14 | } 15 | 16 | const client = axios.create({ 17 | baseURL: 'https://cloud.iexapis.com/v1', 18 | responseType: 'json', 19 | params: { 20 | token: API_KEY 21 | }, 22 | }) 23 | 24 | const persistedReducer = persistReducer(persistConfig, reducers) 25 | 26 | const store = createStore(persistedReducer, applyMiddleware(axiosMiddleware(client))) 27 | const persistor = persistStore(store) 28 | 29 | export default { store, persistor } 30 | -------------------------------------------------------------------------------- /native-base-theme/components/Radio.js: -------------------------------------------------------------------------------- 1 | import { Platform } from "react-native"; 2 | 3 | import variable from "./../variables/platform"; 4 | 5 | export default (variables = variable) => { 6 | const radioTheme = { 7 | ".selected": { 8 | "NativeBase.IconNB": { 9 | color: Platform.OS === "ios" 10 | ? variables.radioColor 11 | : variables.radioSelectedColorAndroid, 12 | lineHeight: Platform.OS === "ios" ? 25 : variables.radioBtnLineHeight, 13 | height: Platform.OS === "ios" ? 20 : undefined 14 | } 15 | }, 16 | "NativeBase.IconNB": { 17 | color: Platform.OS === "ios" ? "transparent" : undefined, 18 | lineHeight: Platform.OS === "ios" 19 | ? undefined 20 | : variables.radioBtnLineHeight, 21 | fontSize: Platform.OS === "ios" ? undefined : variables.radioBtnSize 22 | } 23 | }; 24 | 25 | return radioTheme; 26 | }; 27 | -------------------------------------------------------------------------------- /native-base-theme/components/TabContainer.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | import { Platform } from "react-native"; 3 | 4 | export default (variables = variable) => { 5 | const platformStyle = variables.platformStyle; 6 | const platform = variables.platform; 7 | 8 | const tabContainerTheme = { 9 | elevation: 3, 10 | height: 50, 11 | flexDirection: "row", 12 | shadowColor: platformStyle === "material" ? "#000" : undefined, 13 | shadowOffset: platformStyle === "material" 14 | ? { width: 0, height: 2 } 15 | : undefined, 16 | shadowOpacity: platformStyle === "material" ? 0.2 : undefined, 17 | shadowRadius: platformStyle === "material" ? 1.2 : undefined, 18 | justifyContent: "space-around", 19 | borderBottomWidth: Platform.OS === "ios" ? variables.borderWidth : 0, 20 | borderColor: variables.topTabBarBorderColor 21 | }; 22 | 23 | return tabContainerTheme; 24 | }; 25 | -------------------------------------------------------------------------------- /components/Crypto/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { connect } from 'react-redux' 3 | import { getCrypto } from '../../store/actions' 4 | 5 | import List from '../List' 6 | 7 | class Crypto extends Component { 8 | onRefresh = () => this.props.getCrypto() 9 | 10 | componentDidMount() { 11 | this.props.getCrypto() 12 | } 13 | 14 | render() { 15 | const { data, latestUpdate, loading } = this.props.crypto 16 | 17 | return ( 18 | 25 | ) 26 | } 27 | } 28 | 29 | const mapStateToProps = state => ({ 30 | crypto: state.crypto 31 | }) 32 | 33 | const mapDispatchToProps = { 34 | getCrypto 35 | } 36 | 37 | export default connect( 38 | mapStateToProps, 39 | mapDispatchToProps 40 | )(Crypto) 41 | -------------------------------------------------------------------------------- /components/Gainers/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { connect } from 'react-redux' 3 | import { getGainers } from '../../store/actions' 4 | 5 | import List from '../List' 6 | 7 | class Gainers extends Component { 8 | onRefresh = () => this.props.getGainers() 9 | 10 | componentDidMount() { 11 | this.props.getGainers() 12 | } 13 | 14 | render() { 15 | const { data, latestUpdate, loading } = this.props.gainers 16 | 17 | return ( 18 | 25 | ) 26 | } 27 | } 28 | 29 | const mapStateToProps = state => ({ 30 | gainers: state.gainers 31 | }) 32 | 33 | const mapDispatchToProps = { 34 | getGainers 35 | } 36 | 37 | export default connect( 38 | mapStateToProps, 39 | mapDispatchToProps 40 | )(Gainers) 41 | -------------------------------------------------------------------------------- /components/MostActive/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { connect } from 'react-redux' 3 | import { getMostActive } from '../../store/actions' 4 | 5 | import List from '../List' 6 | 7 | class MostActive extends Component { 8 | onRefresh = () => this.props.getMostActive() 9 | 10 | componentDidMount() { 11 | this.props.getMostActive() 12 | } 13 | 14 | render() { 15 | const { data, latestUpdate, loading } = this.props.mostActive 16 | 17 | return ( 18 | 25 | ) 26 | } 27 | } 28 | 29 | const mapStateToProps = state => ({ 30 | mostActive: state.mostActive 31 | }) 32 | 33 | const mapDispatchToProps = { 34 | getMostActive 35 | } 36 | 37 | export default connect( 38 | mapStateToProps, 39 | mapDispatchToProps 40 | )(MostActive) 41 | -------------------------------------------------------------------------------- /native-base-theme/components/Toast.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const platform = variables.platform; 5 | 6 | const toastTheme = { 7 | ".danger": { 8 | backgroundColor: variables.brandDanger 9 | }, 10 | ".warning": { 11 | backgroundColor: variables.brandWarning 12 | }, 13 | ".success": { 14 | backgroundColor: variables.brandSuccess 15 | }, 16 | backgroundColor: "rgba(0,0,0,0.8)", 17 | borderRadius: platform === "ios" ? 5 : 0, 18 | flexDirection: "row", 19 | justifyContent: "space-between", 20 | alignItems: "center", 21 | padding: 10, 22 | minHeight: 50, 23 | "NativeBase.Text": { 24 | color: "#fff", 25 | flex: 1 26 | }, 27 | "NativeBase.Button": { 28 | backgroundColor: "transparent", 29 | height: 30, 30 | elevation: 0, 31 | "NativeBase.Text": { 32 | fontSize: 14 33 | } 34 | } 35 | }; 36 | 37 | return toastTheme; 38 | }; 39 | -------------------------------------------------------------------------------- /native-base-theme/components/Card.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const cardTheme = { 5 | ".transparent": { 6 | shadowColor: null, 7 | shadowOffset: null, 8 | shadowOpacity: null, 9 | shadowRadius: null, 10 | elevation: null, 11 | backgroundColor: "transparent", 12 | borderWidth: 0 13 | }, 14 | ".noShadow": { 15 | shadowColor: null, 16 | shadowOffset: null, 17 | shadowOpacity: null, 18 | elevation: null 19 | }, 20 | marginVertical: 5, 21 | marginHorizontal: 2, 22 | borderWidth: variables.borderWidth, 23 | borderRadius: variables.cardBorderRadius, 24 | borderColor: variables.cardBorderColor, 25 | flexWrap: "nowrap", 26 | backgroundColor: variables.cardDefaultBg, 27 | shadowColor: "#000", 28 | shadowOffset: { width: 0, height: 2 }, 29 | shadowOpacity: 0.1, 30 | shadowRadius: 1.5, 31 | elevation: 3 32 | }; 33 | 34 | return cardTheme; 35 | }; 36 | -------------------------------------------------------------------------------- /store/reducers/tabs/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | const initialState = { 4 | index: 0, 5 | previousIndex: 0, 6 | routes: [ 7 | { key: 'favorites', title: 'Favorites', icon: 'md-heart' }, 8 | { key: 'search', title: 'Search', icon: 'md-search' }, 9 | // { key: 'sectors', title: 'Sectors', icon: 'md-business' }, 10 | { key: 'gainers', title: 'Gainers', icon: 'md-trending-up' }, 11 | { key: 'losers', title: 'Losers', icon: 'md-trending-down' }, 12 | { key: 'mostActive', title: 'Most Active', icon: 'md-flame' }, 13 | // { key: 'crypto', title: 'Crypto', icon: 'logo-bitcoin' } 14 | // { key: 'ipo', title: 'IPO', icon: "md-calendar" }, 15 | // { key: 'earnings', title: 'Earnings', icon: "logo-usd" } 16 | ] 17 | } 18 | 19 | export const tabs = (state = initialState, action) => { 20 | switch (action.type) { 21 | case Actions.SET_TAB: 22 | return { ...state, index: action.payload, previousIndex: state.index } 23 | default: 24 | return state 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /helpers/cryptoLogos/index.js: -------------------------------------------------------------------------------- 1 | const logos = { 2 | ADAUSDT: require('../../assets/logos/ada.png'), 3 | BCCUSDT: require('../../assets/logos/bcc.png'), 4 | BNBUSDT: require('../../assets/logos/bnb.png'), 5 | BTCUSDT: require('../../assets/logos/btc.png'), 6 | EOSUSDT: require('../../assets/logos/eos.png'), 7 | ETCUSDT: require('../../assets/logos/etc.png'), 8 | ETHUSDT: require('../../assets/logos/eth.png'), 9 | ICXUSDT: require('../../assets/logos/icx.png'), 10 | IOTAUSDT: require('../../assets/logos/ltc.png'), 11 | LTCUSDT: require('../../assets/logos/miota.png'), 12 | NEOUSDT: require('../../assets/logos/neo.png'), 13 | ONTUSDT: require('../../assets/logos/ont.png'), 14 | QTUMUSDT: require('../../assets/logos/qtum.png'), 15 | TRXUSDT: require('../../assets/logos/trx.png'), 16 | TUSDUSDT: require('../../assets/logos/tusd.png'), 17 | VENUSDT: require('../../assets/logos/vet.png'), 18 | XLMUSDT: require('../../assets/logos/xlm.png'), 19 | XRPUSDT: require('../../assets/logos/xrp.png') 20 | } 21 | 22 | export const cryptoLogos = symbol => logos[symbol] || false 23 | -------------------------------------------------------------------------------- /native-base-theme/components/SwipeRow.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const swipeRowTheme = { 5 | "NativeBase.ListItem": { 6 | ".list": { 7 | backgroundColor: "#FFF", 8 | }, 9 | marginLeft: 0, 10 | }, 11 | "NativeBase.Left": { 12 | flex: 0, 13 | alignSelf: null, 14 | alignItems: null, 15 | "NativeBase.Button": { 16 | flex: 1, 17 | alignItems: "center", 18 | justifyContent: "center", 19 | alignSelf: "stretch", 20 | borderRadius: 0, 21 | }, 22 | }, 23 | "NativeBase.Right": { 24 | flex: 0, 25 | alignSelf: null, 26 | alignItems: null, 27 | "NativeBase.Button": { 28 | flex: 1, 29 | alignItems: "center", 30 | justifyContent: "center", 31 | alignSelf: "stretch", 32 | borderRadius: 0, 33 | }, 34 | }, 35 | "NativeBase.Button": { 36 | flex: 1, 37 | height: null, 38 | alignItems: "center", 39 | justifyContent: "center", 40 | alignSelf: "stretch", 41 | borderRadius: 0, 42 | }, 43 | }; 44 | 45 | return swipeRowTheme; 46 | }; 47 | -------------------------------------------------------------------------------- /native-base-theme/components/Badge.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const badgeTheme = { 5 | ".primary": { 6 | backgroundColor: variables.btnPrimaryBg 7 | }, 8 | ".warning": { 9 | backgroundColor: variables.btnWarningBg 10 | }, 11 | ".info": { 12 | backgroundColor: variables.btnInfoBg 13 | }, 14 | ".success": { 15 | backgroundColor: variables.btnSuccessBg 16 | }, 17 | ".danger": { 18 | backgroundColor: variables.btnDangerBg 19 | }, 20 | "NativeBase.Text": { 21 | color: variables.badgeColor, 22 | fontSize: variables.fontSizeBase, 23 | lineHeight: variables.lineHeight - 1, 24 | textAlign: "center", 25 | paddingHorizontal: 3 26 | }, 27 | backgroundColor: variables.badgeBg, 28 | padding: variables.badgePadding, 29 | paddingHorizontal: 6, 30 | alignSelf: "flex-start", 31 | justifyContent: variables.platform === "ios" ? "center" : undefined, 32 | borderRadius: 13.5, 33 | height: 27 34 | }; 35 | return badgeTheme; 36 | }; 37 | -------------------------------------------------------------------------------- /native-base-theme/components/TabHeading.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const platform = variables.platform; 5 | 6 | const tabHeadingTheme = { 7 | flexDirection: "row", 8 | backgroundColor: variables.tabDefaultBg, 9 | flex: 1, 10 | alignItems: "center", 11 | justifyContent: "center", 12 | ".scrollable": { 13 | paddingHorizontal: 20, 14 | flex: platform === "android" ? 0 : 1, 15 | minWidth: platform === "android" ? undefined : 60 16 | }, 17 | "NativeBase.Text": { 18 | color: variables.topTabBarTextColor, 19 | marginHorizontal: 7 20 | }, 21 | "NativeBase.Icon": { 22 | color: variables.topTabBarTextColor, 23 | fontSize: platform === "ios" ? 26 : undefined 24 | }, 25 | ".active": { 26 | "NativeBase.Text": { 27 | color: variables.topTabBarActiveTextColor, 28 | fontWeight: "600" 29 | }, 30 | "NativeBase.Icon": { 31 | color: variables.topTabBarActiveTextColor 32 | } 33 | } 34 | }; 35 | 36 | return tabHeadingTheme; 37 | }; 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "markets-react", 3 | "version": "1.2.0", 4 | "main": "node_modules/expo/AppEntry.js", 5 | "private": true, 6 | "scripts": { 7 | "start": "expo start", 8 | "android": "expo start --android", 9 | "ios": "expo start --ios", 10 | "eject": "expo eject" 11 | }, 12 | "dependencies": { 13 | "axios": "^0.18.1", 14 | "date-fns": "^1.29.0", 15 | "expo": "^33.0.0", 16 | "expo-font": "~5.0.1", 17 | "lodash": "^4.17.15", 18 | "native-base": "^2.13.1", 19 | "react": "16.8.3", 20 | "react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz", 21 | "react-native-platform-touchable": "^1.1.1", 22 | "react-native-status-bar-height": "^2.1.0", 23 | "react-native-tab-view": "2.11.0", 24 | "react-native-vector-icons": "^5.0.0", 25 | "react-redux": "^5.1.0", 26 | "redux": "^4.0.1", 27 | "redux-axios-middleware": "^4.0.0", 28 | "redux-persist": "^5.10.0", 29 | "victory-native": "^30.6.0" 30 | }, 31 | "devDependencies": { 32 | "babel-preset-expo": "^5.0.0", 33 | "react-native-dotenv": "^0.2.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Kevin Restaino 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /store/reducers/stock/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | const initialState = { 4 | data: {}, 5 | chartLoading: false, 6 | loading: false, 7 | error: false, 8 | range: null 9 | } 10 | 11 | export const stock = (state = initialState, action) => { 12 | switch (action.type) { 13 | case Actions.GET_STOCK: 14 | return { ...state, chartLoading: true, loading: true, error: false, range: action.payload.range } 15 | case Actions.GET_STOCK_SUCCESS: 16 | return { ...state, chartLoading: false, loading: false, data: action.payload.data } 17 | case Actions.GET_STOCK_FAIL: 18 | return { ...state, chartLoading: false, loading: false, error: 'Stock symbol not found.' } 19 | case Actions.GET_STOCK_CHART: 20 | return { ...state, chartLoading: true, error: false, range: action.payload.range } 21 | case Actions.GET_STOCK_CHART_SUCCESS: 22 | return { ...state, chartLoading: false, data: action.payload.data } 23 | case Actions.GET_STOCK_CHART_FAIL: 24 | return { ...state, chartLoading: false, error: 'There was an unexpected error.' } 25 | default: 26 | return state 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /native-base-theme/components/CheckBox.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const checkBoxTheme = { 5 | ".checked": { 6 | "NativeBase.Icon": { 7 | color: variables.checkboxTickColor 8 | }, 9 | "NativeBase.IconNB": { 10 | color: variables.checkboxTickColor 11 | } 12 | }, 13 | "NativeBase.Icon": { 14 | color: "transparent", 15 | lineHeight: variables.CheckboxIconSize, 16 | marginTop: variables.CheckboxIconMarginTop, 17 | fontSize: variables.CheckboxFontSize 18 | }, 19 | "NativeBase.IconNB": { 20 | color: "transparent", 21 | lineHeight: variables.CheckboxIconSize, 22 | marginTop: variables.CheckboxIconMarginTop, 23 | fontSize: variables.CheckboxFontSize 24 | }, 25 | borderRadius: variables.CheckboxRadius, 26 | overflow: "hidden", 27 | width: variables.checkboxSize, 28 | height: variables.checkboxSize, 29 | borderWidth: variables.CheckboxBorderWidth, 30 | paddingLeft: variables.CheckboxPaddingLeft - 1, 31 | paddingBottom: variables.CheckboxPaddingBottom, 32 | left: 10 33 | }; 34 | 35 | return checkBoxTheme; 36 | }; 37 | -------------------------------------------------------------------------------- /store/reducers/favorites/index.js: -------------------------------------------------------------------------------- 1 | import { Actions } from '../../../constants' 2 | 3 | const initialState = { data: [], latestUpdate: null, loading: null, error: false, symbols: [] } 4 | 5 | export const favorites = (state = initialState, action) => { 6 | switch (action.type) { 7 | case Actions.TOGGLE_FAVORITE: 8 | const index = state.symbols.findIndex(symbol => symbol === action.payload) 9 | return index !== -1 10 | ? { ...state, symbols: [...state.symbols.slice(0, index), ...state.symbols.slice(index + 1)] } 11 | : { ...state, symbols: [...state.symbols, action.payload] } 12 | case Actions.GET_FAVORITES: 13 | return { ...state, latestUpdate: null, loading: true, error: false } 14 | case Actions.GET_FAVORITES_SUCCESS: 15 | const data = Object.keys(action.payload.data).map(k => action.payload.data[k].quote) 16 | data.sort((a, b) => a.symbol.localeCompare(b.symbol)) 17 | return { ...state, latestUpdate: new Date(), loading: false, data: data } 18 | case Actions.GET_FAVORITES_FAIL: 19 | return { ...state, latestUpdate: null, loading: false, error: 'No results found.' } 20 | case Actions.CLEAR_FAVORITES: 21 | return { ...state, data: [] } 22 | default: 23 | return state 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Markets React 2 | 3 | Ever want to check the stock market, but you just couldn't figure out how? Well look no further, this app has got you covered! Built with React Native, Expo, and NativeBase using data from EX API. 4 | 5 | ![alt tag](assets/github/screenshot.png) 6 | 7 | ## Getting Started 8 | 9 | First, head over to the [Expo installation guide](https://docs.expo.io/versions/latest/introduction/installation.html) to get your development environment set up. 10 | 11 | ``` bash 12 | # clone repo 13 | git clone git@github.com:krestaino/stock-check.git 14 | 15 | # install dependencies 16 | yarn install 17 | 18 | # start development server 19 | yarn start 20 | 21 | # build 22 | expo build:android 23 | # or 24 | expo build:ios 25 | ``` 26 | 27 | ## Store Links 28 | * [Google Play](https://play.google.com/store/apps/details?id=com.kmr.marketsreact) 29 | * [App Store](https://itunes.apple.com/us/app/markets-react/id1441913854) 30 | 31 | ## Built With 32 | * [React Native](https://facebook.github.io/react-native/docs/getting-started.html) 33 | * [Expo](https://docs.expo.io/versions/latest/) 34 | * [NativeBase](https://docs.nativebase.io/) 35 | * [IEX Cloud](https://iexcloud.io/docs/api/) 36 | 37 | ## License 38 | This project is licensed under the MIT License - see the LICENSE.md file for details 39 | -------------------------------------------------------------------------------- /native-base-theme/components/Separator.js: -------------------------------------------------------------------------------- 1 | import variable from './../variables/platform'; 2 | 3 | export default (variables = variable) => { 4 | const theme = { 5 | '.group': { 6 | height: 50, 7 | paddingVertical: variables.listItemPadding - 8, 8 | paddingTop: variables.listItemPadding + 12, 9 | '.bordered': { 10 | height: 50, 11 | paddingVertical: variables.listItemPadding - 8, 12 | paddingTop: variables.listItemPadding + 12, 13 | }, 14 | }, 15 | '.bordered': { 16 | '.noTopBorder': { 17 | borderTopWidth: 0, 18 | }, 19 | '.noBottomBorder': { 20 | borderBottomWidth: 0, 21 | }, 22 | height: 35, 23 | paddingTop: variables.listItemPadding + 2, 24 | paddingBottom: variables.listItemPadding, 25 | borderBottomWidth: variables.borderWidth, 26 | borderTopWidth: variables.borderWidth, 27 | borderColor: variables.listBorderColor, 28 | }, 29 | 'NativeBase.Text': { 30 | fontSize: variables.tabBarTextSize - 2, 31 | color: '#777', 32 | }, 33 | '.noTopBorder': { 34 | borderTopWidth: 0, 35 | }, 36 | '.noBottomBorder': { 37 | borderBottomWidth: 0, 38 | }, 39 | height: 38, 40 | backgroundColor: '#F0EFF5', 41 | flex: 1, 42 | justifyContent: 'center', 43 | paddingLeft: variables.listItemPadding + 5, 44 | }; 45 | 46 | return theme; 47 | }; 48 | -------------------------------------------------------------------------------- /constants/actions/index.js: -------------------------------------------------------------------------------- 1 | export const Actions = { 2 | GET_STOCK: 'GET_STOCK', 3 | GET_STOCK_SUCCESS: 'GET_STOCK_SUCCESS', 4 | GET_STOCK_FAIL: 'GET_STOCK_FAIL', 5 | GET_STOCK_CHART: 'GET_STOCK_CHART', 6 | GET_STOCK_CHART_SUCCESS: 'GET_STOCK_CHART_SUCCESS', 7 | GET_STOCK_CHART_FAIL: 'GET_STOCK_CHART_FAIL', 8 | GET_SYMBOLS: 'GET_SYMBOLS', 9 | GET_SYMBOLS_SUCCESS: 'GET_SYMBOLS_SUCCESS', 10 | GET_SYMBOLS_FAIL: 'GET_SYMBOLS_FAIL', 11 | SET_SYMBOL: 'SET_SYMBOL', 12 | SET_TAB: 'SET_TAB', 13 | TOGGLE_FAVORITE: 'TOGGLE_FAVORITE', 14 | GET_FAVORITES: 'GET_FAVORITES', 15 | GET_FAVORITES_SUCCESS: 'GET_FAVORITES_SUCCESS', 16 | GET_FAVORITES_FAIL: 'GET_FAVORITES_FAIL', 17 | CLEAR_FAVORITES: 'CLEAR_FAVORITES', 18 | SHOW_AUTOSUGGEST: 'SHOW_AUTOSUGGEST', 19 | GET_CRYPTO: 'GET_CRYPTO', 20 | GET_CRYPTO_SUCCESS: 'GET_CRYPTO_SUCCESS', 21 | GET_CRYPTO_FAIL: 'GET_CRYPTO_FAIL', 22 | GET_GAINERS: 'GET_GAINERS', 23 | GET_GAINERS_SUCCESS: 'GET_GAINERS_SUCCESS', 24 | GET_GAINERS_FAIL: 'GET_GAINERS_FAIL', 25 | GET_LOSERS: 'GET_LOSERS', 26 | GET_LOSERS_SUCCESS: 'GET_LOSERS_SUCCESS', 27 | GET_LOSERS_FAIL: 'GET_LOSERS_FAIL', 28 | GET_MOST_ACTIVE: 'GET_MOST_ACTIVE', 29 | GET_MOST_ACTIVE_SUCCESS: 'GET_MOST_ACTIVE_SUCCESS', 30 | GET_MOST_ACTIVE_FAIL: 'GET_MOST_ACTIVE_FAIL', 31 | GET_SECTORS: 'GET_SECTORS', 32 | GET_SECTORS_SUCCESS: 'GET_SECTORS_SUCCESS', 33 | GET_SECTORS_FAIL: 'GET_SECTORS_FAIL' 34 | } 35 | -------------------------------------------------------------------------------- /components/Favorites/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { connect } from 'react-redux' 3 | import { clearFavorites, getFavorites } from '../../store/actions' 4 | import { TextStrings } from '../../constants' 5 | 6 | import List from '../List' 7 | 8 | class Favorites extends Component { 9 | onRefresh = () => this.props.getFavorites(this.props.favorites.symbols) 10 | 11 | componentDidMount() { 12 | if (this.props.favorites.symbols.length) { 13 | this.props.getFavorites(this.props.favorites.symbols) 14 | } 15 | } 16 | 17 | componentDidUpdate(prevProps) { 18 | if (prevProps.favorites.symbols !== this.props.favorites.symbols) { 19 | this.props.favorites.symbols.length 20 | ? this.props.getFavorites(this.props.favorites.symbols) 21 | : this.props.clearFavorites() 22 | } 23 | } 24 | 25 | render() { 26 | const { data, latestUpdate, loading } = this.props.favorites 27 | 28 | return ( 29 | 37 | ) 38 | } 39 | } 40 | 41 | const mapStateToProps = state => ({ 42 | favorites: state.favorites 43 | }) 44 | 45 | const mapDispatchToProps = { 46 | clearFavorites, 47 | getFavorites 48 | } 49 | 50 | export default connect( 51 | mapStateToProps, 52 | mapDispatchToProps 53 | )(Favorites) 54 | -------------------------------------------------------------------------------- /native-base-theme/components/TabBar.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const tabBarTheme = { 5 | ".tabIcon": { 6 | height: undefined 7 | }, 8 | ".vertical": { 9 | height: 60 10 | }, 11 | "NativeBase.Button": { 12 | ".transparent": { 13 | "NativeBase.Text": { 14 | fontSize: variables.tabFontSize, 15 | color: variables.sTabBarActiveTextColor, 16 | fontWeight: "400" 17 | }, 18 | "NativeBase.IconNB": { 19 | color: variables.sTabBarActiveTextColor 20 | } 21 | }, 22 | "NativeBase.IconNB": { 23 | color: variables.sTabBarActiveTextColor 24 | }, 25 | "NativeBase.Text": { 26 | fontSize: variables.tabFontSize, 27 | color: variables.sTabBarActiveTextColor, 28 | fontWeight: "400" 29 | }, 30 | ".isTabActive": { 31 | "NativeBase.Text": { 32 | fontWeight: "900" 33 | } 34 | }, 35 | flex: 1, 36 | alignSelf: "stretch", 37 | alignItems: "center", 38 | justifyContent: "center", 39 | borderRadius: null, 40 | borderBottomColor: "transparent", 41 | backgroundColor: variables.tabBgColor 42 | }, 43 | height: 45, 44 | flexDirection: "row", 45 | justifyContent: "space-around", 46 | borderWidth: 1, 47 | borderTopWidth: 0, 48 | borderLeftWidth: 0, 49 | borderRightWidth: 0, 50 | borderBottomColor: "#ccc", 51 | backgroundColor: variables.tabBgColor 52 | }; 53 | 54 | return tabBarTheme; 55 | }; 56 | -------------------------------------------------------------------------------- /native-base-theme/components/Segment.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const platform = variables.platform; 5 | 6 | const segmentTheme = { 7 | height: 45, 8 | borderColor: variables.segmentBorderColorMain, 9 | flexDirection: "row", 10 | justifyContent: "center", 11 | backgroundColor: variables.segmentBackgroundColor, 12 | "NativeBase.Button": { 13 | alignSelf: "center", 14 | borderRadius: 0, 15 | paddingTop: 3, 16 | paddingBottom: 3, 17 | height: 30, 18 | backgroundColor: "transparent", 19 | borderWidth: 1, 20 | borderLeftWidth: 0, 21 | borderColor: variables.segmentBorderColor, 22 | elevation: 0, 23 | ".active": { 24 | backgroundColor: variables.segmentActiveBackgroundColor, 25 | "NativeBase.Text": { 26 | color: variables.segmentActiveTextColor 27 | }, 28 | "NativeBase.Icon": { 29 | color: variables.segmentActiveTextColor 30 | } 31 | }, 32 | ".first": { 33 | borderTopLeftRadius: platform === "ios" ? 5 : undefined, 34 | borderBottomLeftRadius: platform === "ios" ? 5 : undefined, 35 | borderLeftWidth: 1 36 | }, 37 | ".last": { 38 | borderTopRightRadius: platform === "ios" ? 5 : undefined, 39 | borderBottomRightRadius: platform === "ios" ? 5 : undefined 40 | }, 41 | "NativeBase.Text": { 42 | color: variables.segmentTextColor, 43 | fontSize: 14 44 | }, 45 | "NativeBase.Icon": { 46 | fontSize: 22, 47 | paddingTop: 0, 48 | color: variables.segmentTextColor 49 | } 50 | } 51 | }; 52 | 53 | return segmentTheme; 54 | }; 55 | -------------------------------------------------------------------------------- /components/ListHeader/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { StyleSheet } from 'react-native' 3 | import { Text, View } from 'native-base' 4 | import { distanceInWords } from 'date-fns' 5 | 6 | import { Colors } from '../../constants' 7 | 8 | class ListHeader extends Component { 9 | state = { 10 | latestUpdate: null 11 | } 12 | 13 | capitalize = string => string.charAt(0).toUpperCase() + string.slice(1) 14 | 15 | formatTime = () => (this.state.latestUpdate ? this.capitalize(this.state.latestUpdate) + ' ago' : 'Just now') 16 | 17 | timer() { 18 | return setInterval(() => { 19 | this.setState({ latestUpdate: distanceInWords(new Date(), this.props.latestUpdate) }) 20 | }, 15000) 21 | } 22 | 23 | componentDidMount() { 24 | this.timestamp = this.timer() 25 | } 26 | 27 | componentDidUpdate(prevProps) { 28 | if (prevProps.latestUpdate !== this.props.latestUpdate) { 29 | clearInterval(this.timestamp) 30 | this.timestamp = this.timer() 31 | this.setState({ latestUpdate: null }) 32 | } 33 | } 34 | 35 | render() { 36 | return ( 37 | 38 | {this.props.title} 39 | {this.props.latestUpdate && {this.formatTime()}} 40 | 41 | ) 42 | } 43 | } 44 | 45 | const styles = StyleSheet.create({ 46 | container: { 47 | borderBottomColor: Colors.BLUE2, 48 | borderBottomWidth: 1, 49 | paddingHorizontal: 16, 50 | flexDirection: 'row', 51 | justifyContent: 'space-between', 52 | height: 50 53 | }, 54 | text: { 55 | color: Colors.TEXT_DARK, 56 | fontSize: 13, 57 | fontWeight: '400', 58 | lineHeight: 50 59 | } 60 | }) 61 | 62 | export default ListHeader 63 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "Markets React", 4 | "description": "Ever want to check the stock market, but you just couldn't figure out how? Well look no further, this app has got you covered!", 5 | "slug": "markets-react", 6 | "privacy": "public", 7 | "sdkVersion": "33.0.0", 8 | "platforms": ["ios", "android"], 9 | "version": "1.2.0", 10 | "orientation": "portrait", 11 | "primaryColor": "#182129", 12 | "icon": "./assets/icon.png", 13 | "updates": { 14 | "fallbackToCacheTimeout": 0 15 | }, 16 | "assetBundlePatterns": [ 17 | "**/*" 18 | ], 19 | "ios": { 20 | "bundleIdentifier": "com.kmr.marketsreact", 21 | "buildNumber": "1.2.0", 22 | "supportsTablet": true, 23 | "splash": { 24 | "backgroundColor": "#182129", 25 | "resizeMode": "contain", 26 | "image": "./assets/icon-transparent.png", 27 | "tabletImage": "./assets/icon-transparent.png" 28 | } 29 | }, 30 | "android": { 31 | "package": "com.kmr.marketsreact", 32 | "permissions": [], 33 | "versionCode": 26, 34 | "adaptiveIcon": { 35 | "foregroundImage": "./assets/icon-transparent.png", 36 | "backgroundColor": "#182129" 37 | }, 38 | "playStoreUrl": "https://play.google.com/store/apps/details?id=com.kmr.marketsreact", 39 | "splash": { 40 | "backgroundColor": "#182129", 41 | "resizeMode": "contain", 42 | "ldpi": "./assets/icon-transparent.png", 43 | "mdpi": "./assets/icon-transparent.png", 44 | "hdpi": "./assets/icon-transparent.png", 45 | "xhdpi": "./assets/icon-transparent.png", 46 | "xxhdpi": "./assets/icon-transparent.png", 47 | "xxxhdpi": "./assets/icon-transparent.png" 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Platform, StatusBar, StyleSheet } from 'react-native' 3 | import { Container, Root, StyleProvider, View } from 'native-base' 4 | import * as Font from 'expo-font'; 5 | import { Provider } from 'react-redux' 6 | import { PersistGate } from 'redux-persist/integration/react' 7 | import { getStatusBarHeight } from 'react-native-status-bar-height' 8 | 9 | import getTheme from './native-base-theme/components' 10 | import platform from './native-base-theme/variables/platform' 11 | 12 | import { Colors } from './constants' 13 | import store from './store' 14 | 15 | import Tabs from './components/Tabs' 16 | 17 | export default class App extends Component { 18 | state = { loading: true } 19 | 20 | async componentWillMount() { 21 | await Font.loadAsync({ 22 | Roboto: require('native-base/Fonts/Roboto.ttf'), 23 | Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf') 24 | }) 25 | this.setState({ loading: false }) 26 | } 27 | 28 | render() { 29 | if (this.state.loading) { 30 | return 31 | } 32 | return ( 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ) 46 | } 47 | } 48 | 49 | const styles = StyleSheet.create({ 50 | container: { 51 | backgroundColor: Colors.BLUE1, 52 | flex: 1, 53 | paddingTop: Platform.OS === 'ios' ? getStatusBarHeight() : StatusBar.currentHeight 54 | } 55 | }) 56 | -------------------------------------------------------------------------------- /components/Stock/News/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Linking, StyleSheet } from 'react-native' 3 | import { Text, View } from 'native-base' 4 | import { connect } from 'react-redux' 5 | import { format } from 'date-fns' 6 | import Touchable from 'react-native-platform-touchable' 7 | 8 | import { Colors } from '../../../constants' 9 | 10 | class News extends Component { 11 | render() { 12 | const { news } = this.props.stock.data 13 | 14 | if (!news || news.length === 0) return null 15 | 16 | return ( 17 | 18 | News 19 | {news.map((article, index) => ( 20 | Linking.openURL(article.url)} 24 | > 25 | 26 | 27 | {article.source} – {format(article.datetime, 'MMM D, h:mm a')} 28 | 29 | 30 | {article.headline} 31 | 32 | 33 | 34 | ))} 35 | 36 | ) 37 | } 38 | } 39 | 40 | const styles = StyleSheet.create({ 41 | container: { 42 | flexDirection: 'column', 43 | marginBottom: 78 44 | }, 45 | title: { 46 | fontWeight: 'bold', 47 | fontSize: 20, 48 | paddingHorizontal: 16 49 | }, 50 | item: { 51 | flexDirection: 'column', 52 | flex: 1, 53 | flexWrap: 'wrap', 54 | paddingHorizontal: 16, 55 | paddingVertical: 12 56 | }, 57 | preHeadline: { 58 | color: Colors.TEXT_DARK, 59 | fontSize: 13 60 | }, 61 | headline: { 62 | fontWeight: 'bold', 63 | marginTop: 4 64 | }, 65 | summary: { 66 | marginTop: 8 67 | } 68 | }) 69 | 70 | const mapStateToProps = state => ({ 71 | stock: state.stock 72 | }) 73 | 74 | export default connect(mapStateToProps)(News) 75 | -------------------------------------------------------------------------------- /native-base-theme/components/Form.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const platform = variables.platform; 5 | 6 | const theme = { 7 | "NativeBase.Item": { 8 | ".fixedLabel": { 9 | "NativeBase.Label": { 10 | paddingLeft: null 11 | }, 12 | marginLeft: 15 13 | }, 14 | ".inlineLabel": { 15 | "NativeBase.Label": { 16 | paddingLeft: null 17 | }, 18 | marginLeft: 15 19 | }, 20 | ".placeholderLabel": { 21 | "NativeBase.Input": {} 22 | }, 23 | ".stackedLabel": { 24 | "NativeBase.Label": { 25 | top: 5, 26 | paddingLeft: null 27 | }, 28 | "NativeBase.Input": { 29 | paddingLeft: null, 30 | marginLeft: null 31 | }, 32 | "NativeBase.Icon": { 33 | marginTop: 36 34 | }, 35 | marginLeft: 15 36 | }, 37 | ".floatingLabel": { 38 | "NativeBase.Input": { 39 | paddingLeft: null, 40 | top: 10, 41 | marginLeft: null 42 | }, 43 | "NativeBase.Label": { 44 | left: 0, 45 | top: 6 46 | }, 47 | "NativeBase.Icon": { 48 | top: 6 49 | }, 50 | marginTop: 15, 51 | marginLeft: 15 52 | }, 53 | ".regular": { 54 | "NativeBase.Label": { 55 | left: 0 56 | }, 57 | marginLeft: 0 58 | }, 59 | ".rounded": { 60 | "NativeBase.Label": { 61 | left: 0 62 | }, 63 | marginLeft: 0 64 | }, 65 | ".underline": { 66 | "NativeBase.Label": { 67 | left: 0, 68 | top: 0, 69 | position: "relative" 70 | }, 71 | "NativeBase.Input": { 72 | left: -15 73 | }, 74 | marginLeft: 15 75 | }, 76 | ".last": { 77 | marginLeft: 0, 78 | paddingLeft: 15 79 | }, 80 | "NativeBase.Label": { 81 | paddingRight: 5 82 | }, 83 | marginLeft: 15 84 | } 85 | }; 86 | 87 | return theme; 88 | }; 89 | -------------------------------------------------------------------------------- /native-base-theme/components/FooterTab.js: -------------------------------------------------------------------------------- 1 | import { Platform } from "react-native"; 2 | 3 | import variable from "./../variables/platform"; 4 | 5 | export default (variables = variable) => { 6 | const platform = variables.platform; 7 | 8 | const footerTabTheme = { 9 | "NativeBase.Button": { 10 | ".active": { 11 | "NativeBase.Text": { 12 | color: variables.tabBarActiveTextColor, 13 | fontSize: variables.tabBarTextSize, 14 | lineHeight: 16 15 | }, 16 | "NativeBase.Icon": { 17 | color: variables.tabBarActiveTextColor 18 | }, 19 | "NativeBase.IconNB": { 20 | color: variables.tabBarActiveTextColor 21 | }, 22 | backgroundColor: variables.tabActiveBgColor 23 | }, 24 | flexDirection: null, 25 | backgroundColor: "transparent", 26 | borderColor: null, 27 | elevation: 0, 28 | shadowColor: null, 29 | shadowOffset: null, 30 | shadowRadius: null, 31 | shadowOpacity: null, 32 | alignSelf: "center", 33 | flex: 1, 34 | height: variables.footerHeight, 35 | justifyContent: "center", 36 | ".badge": { 37 | "NativeBase.Badge": { 38 | "NativeBase.Text": { 39 | fontSize: 11, 40 | fontWeight: platform === "ios" ? "600" : undefined, 41 | lineHeight: 14 42 | }, 43 | top: -3, 44 | alignSelf: "center", 45 | left: 10, 46 | zIndex: 99, 47 | height: 18, 48 | padding: 1.7, 49 | paddingHorizontal: 3 50 | }, 51 | "NativeBase.Icon": { 52 | marginTop: -18 53 | } 54 | }, 55 | "NativeBase.Icon": { 56 | color: variables.tabBarTextColor 57 | }, 58 | "NativeBase.IconNB": { 59 | color: variables.tabBarTextColor 60 | }, 61 | "NativeBase.Text": { 62 | color: variables.tabBarTextColor, 63 | fontSize: variables.tabBarTextSize, 64 | lineHeight: 16 65 | } 66 | }, 67 | backgroundColor: Platform.OS === "android" 68 | ? variables.footerDefaultBg 69 | : undefined, 70 | flexDirection: "row", 71 | justifyContent: "space-between", 72 | flex: 1, 73 | alignSelf: "stretch" 74 | }; 75 | 76 | return footerTabTheme; 77 | }; 78 | -------------------------------------------------------------------------------- /components/Stock/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { RefreshControl, StyleSheet } from 'react-native' 3 | import { Content, Text, View } from 'native-base' 4 | import { connect } from 'react-redux' 5 | 6 | import { Colors } from '../../constants' 7 | import { getStock } from '../../store/actions' 8 | 9 | import Search from '../Search' 10 | import AutoSuggest from '../AutoSuggest' 11 | import Info from './Info' 12 | import Chart from './Chart' 13 | import Details from './Details' 14 | import News from './News' 15 | import Save from './Save' 16 | 17 | class Stock extends Component { 18 | onRefresh = () => { 19 | if (this.props.stock.data.quote) { 20 | this.props.getStock(this.props.stock.data.quote.symbol, this.props.stock.range) 21 | } 22 | } 23 | 24 | render() { 25 | const { error, loading } = this.props.stock 26 | const isError = error && !loading 27 | 28 | return ( 29 | 30 | 31 | 32 | {isError ? ( 33 | {error} 34 | ) : ( 35 | 36 | 44 | } 45 | > 46 | 47 | 48 |
49 | 50 | 51 | 52 | 53 | )} 54 | 55 | ) 56 | } 57 | } 58 | 59 | const styles = StyleSheet.create({ 60 | container: { 61 | flex: 1, 62 | flexDirection: 'column' 63 | }, 64 | noResults: { 65 | color: Colors.TEXT_DARK, 66 | fontSize: 13, 67 | padding: 20, 68 | textAlign: 'center' 69 | } 70 | }) 71 | 72 | const mapStateToProps = state => ({ 73 | stock: state.stock, 74 | symbol: state.symbol 75 | }) 76 | 77 | const mapDispatchToProps = { 78 | getStock 79 | } 80 | 81 | export default connect( 82 | mapStateToProps, 83 | mapDispatchToProps 84 | )(Stock) 85 | -------------------------------------------------------------------------------- /components/Stock/Save/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Platform, StyleSheet } from 'react-native' 3 | import { Icon, Fab, Toast, View } from 'native-base' 4 | import { connect } from 'react-redux' 5 | 6 | import { Colors } from '../../../constants' 7 | import { toggleFavorite } from '../../../store/actions' 8 | 9 | class Save extends Component { 10 | isFavorite = symbol => this.props.favorites.symbols.filter(favorite => favorite === symbol).length 11 | 12 | onPress = quote => { 13 | this.props.toggleFavorite(quote.symbol) 14 | this.toast(quote.symbol) 15 | } 16 | 17 | toast = symbol => { 18 | const text = this.isFavorite(symbol) ? 'removed from' : 'added to' 19 | 20 | Toast.show({ 21 | text: `${symbol} ${text} favorites.`, 22 | textStyle: styles.text, 23 | position: 'top', 24 | style: styles.toast 25 | }) 26 | } 27 | 28 | render() { 29 | const { quote } = this.props.stock.data 30 | 31 | if (!quote) return null 32 | 33 | return ( 34 | 35 | {!this.props.autoSuggest && ( 36 | this.onPress(quote)} 40 | > 41 | 42 | 43 | )} 44 | 45 | ) 46 | } 47 | } 48 | 49 | const styles = StyleSheet.create({ 50 | favorite: { 51 | backgroundColor: Colors.BLUE4 52 | }, 53 | notFavorite: { 54 | backgroundColor: Colors.BLUE3 55 | }, 56 | icon: { 57 | color: '#fff' 58 | }, 59 | toast: { 60 | backgroundColor: Colors.BLUE0, 61 | borderRadius: 6, 62 | fontSize: 13, 63 | marginLeft: 16, 64 | marginRight: 16, 65 | marginTop: Platform.OS === 'ios' ? -25 : 6, 66 | minHeight: 0, 67 | paddingHorizontal: 6 68 | }, 69 | text: { 70 | color: Colors.TEXT_NORMAL, 71 | fontSize: 13, 72 | textAlign: 'center' 73 | } 74 | }) 75 | 76 | const mapStateToProps = state => ({ 77 | autoSuggest: state.autoSuggest, 78 | favorites: state.favorites, 79 | stock: state.stock, 80 | symbol: state.symbol 81 | }) 82 | 83 | const mapDispatchToProps = { 84 | toggleFavorite 85 | } 86 | 87 | export default connect( 88 | mapStateToProps, 89 | mapDispatchToProps 90 | )(Save) 91 | -------------------------------------------------------------------------------- /components/Stock/Info/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Image, StyleSheet } from 'react-native' 3 | import { Text, View } from 'native-base' 4 | import { connect } from 'react-redux' 5 | import { format } from 'date-fns' 6 | 7 | import { Colors } from '../../../constants' 8 | import { upOrDownSymbol, formatPercentage, positiveOrNegative } from '../../../helpers' 9 | 10 | class Info extends Component { 11 | render() { 12 | const { quote } = this.props.stock.data 13 | 14 | if (!quote) return null 15 | const logo = `https://storage.googleapis.com/iex/api/logos/${quote.symbol}.png` 16 | 17 | return ( 18 | 19 | 20 | 21 | {quote.companyName} 22 | 23 | {quote.primaryExchange}: {quote.symbol} 24 | 25 | 26 | 27 | 28 | 29 | {quote.latestPrice} 30 | USD 31 | 32 | {quote.change} 33 | 34 | ({formatPercentage(quote.changePercent)} 35 | %) {upOrDownSymbol(quote.changePercent)} 36 | 37 | 38 | 39 | {format(quote.latestUpdate, 'MMM D, h:mm A')} 40 | 41 | ) 42 | } 43 | } 44 | 45 | const styles = StyleSheet.create({ 46 | container: { 47 | padding: 16 48 | }, 49 | row: { 50 | flexDirection: 'row', 51 | justifyContent: 'space-between' 52 | }, 53 | image: { 54 | borderRadius: 3, 55 | height: 48, 56 | resizeMode: 'contain', 57 | width: 48 58 | }, 59 | companyName: { 60 | flexWrap: 'wrap', 61 | fontSize: 20, 62 | fontWeight: 'bold', 63 | maxWidth: '90%' 64 | }, 65 | primaryExchange: { 66 | color: Colors.TEXT_DARK, 67 | marginBottom: 6 68 | }, 69 | latestPrice: { 70 | fontWeight: 'bold', 71 | fontSize: 24 72 | }, 73 | latestUpdate: { 74 | color: Colors.TEXT_DARK, 75 | fontSize: 12 76 | } 77 | }) 78 | 79 | const mapStateToProps = state => ({ 80 | stock: state.stock 81 | }) 82 | 83 | export default connect(mapStateToProps)(Info) 84 | -------------------------------------------------------------------------------- /components/Search/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { StyleSheet, TouchableOpacity } from 'react-native' 3 | import { Icon, Item, Input, View } from 'native-base' 4 | import { connect } from 'react-redux' 5 | 6 | import { Colors, Ranges } from '../../constants' 7 | import { getStock, setSymbol, showAutoSuggest } from '../../store/actions' 8 | 9 | class Search extends Component { 10 | state = { hideAutoSuggest: false } 11 | 12 | onChangeText = symbol => { 13 | this.props.setSymbol(symbol) 14 | this.props.showAutoSuggest(true) 15 | } 16 | 17 | onSubmitEditing = () => { 18 | if (this.props.symbol) { 19 | this.props.getStock(this.props.symbol, Ranges.ONE_MONTH) 20 | this.props.showAutoSuggest(false) 21 | } 22 | } 23 | 24 | componentDidUpdate = () => { 25 | if (this.props.stock.error) { 26 | this.input._root.focus() 27 | } 28 | if (!this.props.symbol) { 29 | this.props.showAutoSuggest(false) 30 | } 31 | } 32 | 33 | render = () => ( 34 | 35 | 36 | 37 | this.onChangeText(symbol)} 43 | onSubmitEditing={this.onSubmitEditing} 44 | placeholder="Search by stock symbol" 45 | ref={ref => (this.input = ref)} 46 | returnKeyType="search" 47 | selectionColor={Colors.TEXT_NORMAL} 48 | spellCheck={false} 49 | style={[styles.input, { color: '#ffffff' }]} 50 | value={this.props.symbol} 51 | /> 52 | {this.props.symbol ? ( 53 | this.onChangeText('')}> 54 | 55 | 56 | ) : null} 57 | 58 | 59 | ) 60 | } 61 | 62 | const styles = StyleSheet.create({ 63 | item: { 64 | borderBottomWidth: 1, 65 | height: 50, 66 | paddingLeft: 20, 67 | paddingRight: 10, 68 | marginLeft: 0 69 | }, 70 | icon: { 71 | color: Colors.TEXT_NORMAL 72 | }, 73 | input: { 74 | color: Colors.TEXT_DARK, 75 | fontSize: 13, 76 | fontWeight: '400' 77 | } 78 | }) 79 | 80 | const mapStateToProps = state => ({ 81 | stock: state.stock, 82 | symbol: state.symbol 83 | }) 84 | 85 | const mapDispatchToProps = { 86 | getStock, 87 | setSymbol, 88 | showAutoSuggest 89 | } 90 | 91 | export default connect( 92 | mapStateToProps, 93 | mapDispatchToProps 94 | )(Search) 95 | -------------------------------------------------------------------------------- /components/Sectors/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { RefreshControl, StyleSheet } from 'react-native' 3 | import { Content, Icon, Text, View } from 'native-base' 4 | import { connect } from 'react-redux' 5 | 6 | import { Colors } from '../../constants' 7 | import { getSectors } from '../../store/actions' 8 | import { formatPercentage, positiveOrNegative, sectorIcons, upOrDownSymbol } from '../../helpers' 9 | 10 | import ListHeader from '../ListHeader' 11 | 12 | class Sectors extends Component { 13 | onRefresh = () => this.props.getSectors() 14 | 15 | componentDidMount() { 16 | this.props.getSectors() 17 | } 18 | 19 | render() { 20 | const { data, latestUpdate, loading } = this.props.sectors 21 | 22 | return ( 23 | 24 | 25 | 33 | } 34 | > 35 | 36 | {data.map((sector, index) => { 37 | const icon = sectorIcons(sector.name) 38 | 39 | return ( 40 | 41 | 42 | 43 | {formatPercentage(sector.performance)}%{upOrDownSymbol(sector.performance)} 44 | 45 | {sector.name} 46 | 47 | ) 48 | })} 49 | 50 | 51 | 52 | ) 53 | } 54 | } 55 | 56 | const styles = StyleSheet.create({ 57 | container: { 58 | width: '100%', 59 | flexDirection: 'row', 60 | flexWrap: 'wrap', 61 | padding: 16 62 | }, 63 | sector: { 64 | alignItems: 'center', 65 | flexDirection: 'column', 66 | paddingHorizontal: 4, 67 | paddingVertical: 16, 68 | width: '33.33%' 69 | }, 70 | performance: { 71 | fontSize: 13, 72 | marginTop: 8 73 | }, 74 | name: { 75 | fontSize: 13, 76 | marginTop: 4, 77 | maxWidth: 110, 78 | textAlign: 'center' 79 | } 80 | }) 81 | 82 | const mapStateToProps = state => ({ 83 | sectors: state.sectors 84 | }) 85 | 86 | const mapDispatchToProps = { 87 | getSectors 88 | } 89 | 90 | export default connect( 91 | mapStateToProps, 92 | mapDispatchToProps 93 | )(Sectors) 94 | -------------------------------------------------------------------------------- /components/Stock/Details/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { StyleSheet } from 'react-native' 3 | import { Text, View } from 'native-base' 4 | import { connect } from 'react-redux' 5 | 6 | import { Colors } from '../../../constants' 7 | 8 | class Details extends Component { 9 | formatMarketCap = x => (x < 1000000000 ? (x / 1000000).toFixed(2) + 'M' : (x / 1000000000).toFixed(2) + 'B') 10 | 11 | render() { 12 | const { quote } = this.props.stock.data 13 | 14 | if (!quote) return null 15 | 16 | return ( 17 | 18 | 19 | 20 | Open 21 | {quote.open} 22 | 23 | 24 | High 25 | {quote.high} 26 | 27 | 28 | Low 29 | {quote.low} 30 | 31 | 32 | Mkt cap 33 | {this.formatMarketCap(quote.marketCap)} 34 | 35 | 36 | P/E ratio 37 | {quote.peRatio} 38 | 39 | 40 | 41 | 42 | Prev close 43 | {quote.previousClose} 44 | 45 | 46 | 52-wk high 47 | {quote.week52High} 48 | 49 | 50 | 52-wk low 51 | {quote.week52Low} 52 | 53 | 54 | 55 | ) 56 | } 57 | } 58 | 59 | const styles = StyleSheet.create({ 60 | container: { 61 | flexDirection: 'row', 62 | justifyContent: 'space-between', 63 | padding: 16 64 | }, 65 | column: { 66 | width: '50%' 67 | }, 68 | columnFirst: { 69 | paddingRight: 8 70 | }, 71 | columnSecond: { 72 | paddingLeft: 8 73 | }, 74 | row: { 75 | flexDirection: 'row', 76 | justifyContent: 'space-between', 77 | marginTop: 8 78 | }, 79 | label: { 80 | fontSize: 14 81 | }, 82 | value: { 83 | color: Colors.TEXT_DARK, 84 | fontSize: 14 85 | } 86 | }) 87 | 88 | const mapStateToProps = state => ({ 89 | stock: state.stock 90 | }) 91 | 92 | export default connect(mapStateToProps)(Details) 93 | -------------------------------------------------------------------------------- /native-base-theme/components/Footer.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const platformStyle = variables.platformStyle; 5 | const platform = variables.platform; 6 | 7 | const iconCommon = { 8 | "NativeBase.Icon": { 9 | color: variables.tabBarActiveTextColor 10 | } 11 | }; 12 | const iconNBCommon = { 13 | "NativeBase.IconNB": { 14 | color: variables.tabBarActiveTextColor 15 | } 16 | }; 17 | const textCommon = { 18 | "NativeBase.Text": { 19 | color: variables.tabBarActiveTextColor 20 | } 21 | }; 22 | const footerTheme = { 23 | "NativeBase.Left": { 24 | "NativeBase.Button": { 25 | ".transparent": { 26 | backgroundColor: "transparent", 27 | borderColor: null, 28 | elevation: 0, 29 | shadowColor: null, 30 | shadowOffset: null, 31 | shadowRadius: null, 32 | shadowOpacity: null, 33 | ...iconCommon, 34 | ...iconNBCommon, 35 | ...textCommon 36 | }, 37 | alignSelf: null, 38 | ...iconCommon, 39 | ...iconNBCommon, 40 | // ...textCommon 41 | }, 42 | flex: 1, 43 | alignSelf: "center", 44 | alignItems: "flex-start" 45 | }, 46 | "NativeBase.Body": { 47 | flex: 1, 48 | alignItems: "center", 49 | alignSelf: "center", 50 | flexDirection: "row", 51 | "NativeBase.Button": { 52 | alignSelf: "center", 53 | ".transparent": { 54 | backgroundColor: "transparent", 55 | borderColor: null, 56 | elevation: 0, 57 | shadowColor: null, 58 | shadowOffset: null, 59 | shadowRadius: null, 60 | shadowOpacity: null, 61 | ...iconCommon, 62 | ...iconNBCommon, 63 | ...textCommon 64 | }, 65 | ".full": { 66 | height: variables.footerHeight, 67 | paddingBottom: variables.footerPaddingBottom, 68 | flex: 1 69 | }, 70 | ...iconCommon, 71 | ...iconNBCommon, 72 | // ...textCommon 73 | } 74 | }, 75 | "NativeBase.Right": { 76 | "NativeBase.Button": { 77 | ".transparent": { 78 | backgroundColor: "transparent", 79 | borderColor: null, 80 | elevation: 0, 81 | shadowColor: null, 82 | shadowOffset: null, 83 | shadowRadius: null, 84 | shadowOpacity: null, 85 | ...iconCommon, 86 | ...iconNBCommon, 87 | ...textCommon 88 | }, 89 | alignSelf: null, 90 | ...iconCommon, 91 | ...iconNBCommon, 92 | // ...textCommon 93 | }, 94 | flex: 1, 95 | alignSelf: "center", 96 | alignItems: "flex-end" 97 | }, 98 | backgroundColor: variables.footerDefaultBg, 99 | flexDirection: "row", 100 | justifyContent: "center", 101 | borderTopWidth: 102 | platform === "ios" && platformStyle !== "material" 103 | ? variables.borderWidth 104 | : undefined, 105 | borderColor: 106 | platform === "ios" && platformStyle !== "material" 107 | ? "#cbcbcb" 108 | : undefined, 109 | height: variables.footerHeight, 110 | paddingBottom: variables.footerPaddingBottom, 111 | elevation: 3, 112 | left: 0, 113 | right: 0 114 | }; 115 | return footerTheme; 116 | }; 117 | -------------------------------------------------------------------------------- /components/AutoSuggest/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { BackHandler, Dimensions, FlatList, Keyboard, Platform, StatusBar, StyleSheet } from 'react-native' 3 | import { Spinner, Text, View } from 'native-base' 4 | import { connect } from 'react-redux' 5 | import { getStatusBarHeight } from 'react-native-status-bar-height' 6 | import Touchable from 'react-native-platform-touchable' 7 | 8 | import { Colors, Ranges } from '../../constants' 9 | import { getStock, getSymbols, setSymbol, showAutoSuggest } from '../../store/actions' 10 | 11 | class AutoSuggest extends Component { 12 | state = { 13 | filteredSearch: [] 14 | } 15 | 16 | listHeight = () => { 17 | const statusBar = Platform.OS === 'ios' ? getStatusBarHeight() : StatusBar.currentHeight 18 | const windowHeight = Dimensions.get('window').height 19 | const tabAndSearchHeight = 105 + 10 20 | return windowHeight - statusBar - tabAndSearchHeight 21 | } 22 | 23 | onBackPress = () => (this.props.autoSuggest ? this.props.showAutoSuggest(false) : false) 24 | 25 | onPress = symbol => { 26 | this.props.getStock(symbol, Ranges.ONE_MONTH) 27 | this.props.setSymbol(symbol) 28 | this.props.showAutoSuggest(false) 29 | this.setState({ filteredSearch: [] }) 30 | Keyboard.dismiss() 31 | } 32 | 33 | renderItem = ({ item }) => ( 34 | this.onPress(item.symbol)} 37 | style={styles.item} 38 | > 39 | 40 | {item.symbol} {item.name} 41 | 42 | 43 | ) 44 | 45 | search = symbol => { 46 | const matches = this.props.symbols.data.filter(stock => stock.symbol.startsWith(symbol)).slice(0, 20) 47 | this.setState({ filteredSearch: matches }) 48 | } 49 | 50 | componentDidMount() { 51 | this.props.getSymbols() 52 | BackHandler.addEventListener('hardwareBackPress', this.onBackPress) 53 | } 54 | 55 | componentDidUpdate(prevProps) { 56 | if (prevProps.symbols.loading !== this.props.symbols.loading) { 57 | this.search(this.props.symbol) 58 | } 59 | } 60 | 61 | componentWillUpdate(nextProps) { 62 | if (nextProps.symbol !== this.props.symbol) { 63 | this.search(nextProps.symbol) 64 | } 65 | } 66 | 67 | componentWillUnmount() { 68 | BackHandler.removeEventListener('hardwareBackPress', this.onBackPress) 69 | } 70 | 71 | render() { 72 | const { filteredSearch } = this.state 73 | 74 | if (!this.props.autoSuggest) { 75 | return false 76 | } 77 | 78 | return ( 79 | 80 | {this.props.symbols.loading ? ( 81 | 82 | ) : ( 83 | filteredSearch.length !== 0 && ( 84 | item.symbol} 89 | renderItem={item => this.renderItem(item)} 90 | style={[styles.container, { height: this.listHeight() }]} 91 | /> 92 | ) 93 | )} 94 | 95 | ) 96 | } 97 | } 98 | 99 | const styles = StyleSheet.create({ 100 | container: { 101 | backgroundColor: Colors.BLUE2 102 | }, 103 | item: { 104 | paddingHorizontal: 16, 105 | paddingVertical: 12 106 | }, 107 | name: { 108 | color: Colors.TEXT_DARK, 109 | fontSize: 13 110 | } 111 | }) 112 | 113 | const mapStateToProps = state => ({ 114 | autoSuggest: state.autoSuggest, 115 | symbol: state.symbol, 116 | symbols: state.symbols 117 | }) 118 | 119 | const mapDispatchToProps = { 120 | getStock, 121 | getSymbols, 122 | setSymbol, 123 | showAutoSuggest 124 | } 125 | 126 | export default connect( 127 | mapStateToProps, 128 | mapDispatchToProps 129 | )(AutoSuggest) 130 | -------------------------------------------------------------------------------- /native-base-theme/components/InputGroup.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const inputGroupTheme = { 5 | "NativeBase.Icon": { 6 | fontSize: 24, 7 | color: variables.sTabBarActiveTextColor, 8 | paddingHorizontal: 5 9 | }, 10 | "NativeBase.IconNB": { 11 | fontSize: 24, 12 | color: variables.sTabBarActiveTextColor, 13 | paddingHorizontal: 5 14 | }, 15 | "NativeBase.Input": { 16 | height: variables.inputHeightBase, 17 | color: variables.inputColor, 18 | paddingLeft: 5, 19 | paddingRight: 5, 20 | flex: 1, 21 | fontSize: variables.inputFontSize, 22 | lineHeight: variables.inputLineHeight 23 | }, 24 | ".underline": { 25 | ".success": { 26 | borderColor: variables.inputSuccessBorderColor 27 | }, 28 | ".error": { 29 | borderColor: variables.inputErrorBorderColor 30 | }, 31 | paddingLeft: 5, 32 | borderWidth: variables.borderWidth, 33 | borderTopWidth: 0, 34 | borderRightWidth: 0, 35 | borderLeftWidth: 0, 36 | borderColor: variables.inputBorderColor 37 | }, 38 | ".regular": { 39 | ".success": { 40 | borderColor: variables.inputSuccessBorderColor 41 | }, 42 | ".error": { 43 | borderColor: variables.inputErrorBorderColor 44 | }, 45 | paddingLeft: 5, 46 | borderWidth: variables.borderWidth, 47 | borderColor: variables.inputBorderColor 48 | }, 49 | ".rounded": { 50 | ".success": { 51 | borderColor: variables.inputSuccessBorderColor 52 | }, 53 | ".error": { 54 | borderColor: variables.inputErrorBorderColor 55 | }, 56 | paddingLeft: 5, 57 | borderWidth: variables.borderWidth, 58 | borderRadius: variables.inputGroupRoundedBorderRadius, 59 | borderColor: variables.inputBorderColor 60 | }, 61 | 62 | ".success": { 63 | "NativeBase.Icon": { 64 | color: variables.inputSuccessBorderColor 65 | }, 66 | "NativeBase.IconNB": { 67 | color: variables.inputSuccessBorderColor 68 | }, 69 | ".rounded": { 70 | borderRadius: 30, 71 | borderColor: variables.inputSuccessBorderColor 72 | }, 73 | ".regular": { 74 | borderColor: variables.inputSuccessBorderColor 75 | }, 76 | ".underline": { 77 | borderWidth: variables.borderWidth, 78 | borderTopWidth: 0, 79 | borderRightWidth: 0, 80 | borderLeftWidth: 0, 81 | borderColor: variables.inputSuccessBorderColor 82 | }, 83 | borderColor: variables.inputSuccessBorderColor 84 | }, 85 | 86 | ".error": { 87 | "NativeBase.Icon": { 88 | color: variables.inputErrorBorderColor 89 | }, 90 | "NativeBase.IconNB": { 91 | color: variables.inputErrorBorderColor 92 | }, 93 | ".rounded": { 94 | borderRadius: 30, 95 | borderColor: variables.inputErrorBorderColor 96 | }, 97 | ".regular": { 98 | borderColor: variables.inputErrorBorderColor 99 | }, 100 | ".underline": { 101 | borderWidth: variables.borderWidth, 102 | borderTopWidth: 0, 103 | borderRightWidth: 0, 104 | borderLeftWidth: 0, 105 | borderColor: variables.inputErrorBorderColor 106 | }, 107 | borderColor: variables.inputErrorBorderColor 108 | }, 109 | ".disabled": { 110 | "NativeBase.Icon": { 111 | color: "#384850" 112 | }, 113 | "NativeBase.IconNB": { 114 | color: "#384850" 115 | } 116 | }, 117 | 118 | paddingLeft: 5, 119 | borderWidth: variables.borderWidth, 120 | borderTopWidth: 0, 121 | borderRightWidth: 0, 122 | borderLeftWidth: 0, 123 | borderColor: variables.inputBorderColor, 124 | backgroundColor: "transparent", 125 | flexDirection: "row", 126 | alignItems: "center" 127 | }; 128 | 129 | return inputGroupTheme; 130 | }; 131 | -------------------------------------------------------------------------------- /components/Tabs/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { BackHandler, Dimensions, StyleSheet } from 'react-native' 3 | import { Icon, View, Text } from 'native-base' 4 | import { connect } from 'react-redux' 5 | import { TabBar, TabView, SceneMap } from 'react-native-tab-view' 6 | 7 | import { Colors } from '../../constants' 8 | import { setTab } from '../../store/actions' 9 | 10 | import Stock from '../Stock' 11 | import Favorites from '../Favorites' 12 | // import Sectors from '../Sectors' 13 | import Gainers from '../Gainers' 14 | import Losers from '../Losers' 15 | import MostActive from '../MostActive' 16 | import Crypto from '../Crypto' 17 | 18 | class Tabs extends Component { 19 | favoritesTab = () => ( 20 | 21 | 22 | 23 | ) 24 | 25 | stockTab = () => ( 26 | 27 | 28 | 29 | ) 30 | 31 | // sectorsTab = () => ( 32 | // 33 | // 34 | // 35 | // ) 36 | 37 | gainersTab = () => ( 38 | 39 | 40 | 41 | ) 42 | 43 | losersTab = () => ( 44 | 45 | 46 | 47 | ) 48 | 49 | mostActiveTab = () => ( 50 | 51 | 52 | 53 | ) 54 | 55 | cryptoTab = () => ( 56 | 57 | 58 | 59 | ) 60 | 61 | ipoTab = () => ( 62 | 63 | IPO 64 | 65 | ) 66 | 67 | earningsTab = () => ( 68 | 69 | Earnings 70 | 71 | ) 72 | 73 | renderIcon = ({ route }) => 74 | 75 | sceneMap = SceneMap({ 76 | search: this.stockTab, 77 | favorites: this.favoritesTab, 78 | // sectors: this.sectorsTab, 79 | gainers: this.gainersTab, 80 | losers: this.losersTab, 81 | mostActive: this.mostActiveTab, 82 | crypto: this.cryptoTab, 83 | ipo: this.ipoTab, 84 | earnings: this.earningsTab 85 | }) 86 | 87 | tabBar = props => ( 88 | 99 | ) 100 | 101 | onBackPress = () => { 102 | const { setTab, tabs } = this.props 103 | setTab(tabs.previousIndex) 104 | return true 105 | } 106 | 107 | componentDidMount() { 108 | BackHandler.addEventListener('hardwareBackPress', this.onBackPress) 109 | } 110 | 111 | componentWillUnmount() { 112 | BackHandler.removeEventListener('hardwareBackPress', this.onBackPress) 113 | } 114 | 115 | render = () => ( 116 | 117 | this.props.setTab(index)} 121 | renderScene={this.sceneMap} 122 | renderTabBar={props => this.tabBar(props)} 123 | tabBarPosition="bottom" 124 | /> 125 | 126 | ) 127 | } 128 | 129 | const styles = StyleSheet.create({ 130 | container: { 131 | flex: 1, 132 | flexDirection: 'column' 133 | }, 134 | initialLayout: { 135 | height: 0, 136 | width: Dimensions.get('window').width 137 | }, 138 | indicatorStyle: { 139 | backgroundColor: Colors.TEXT_DARK, 140 | top: 0 141 | }, 142 | labelStyle: { 143 | color: Colors.TEXT_NORMAL, 144 | fontSize: 10, 145 | height: 65, 146 | marginHorizontal: 0, 147 | marginBottom: 4, 148 | paddingVertical: 0 149 | }, 150 | tabBar: { 151 | backgroundColor: Colors.BLUE1, 152 | borderTopColor: Colors.BLUE2, 153 | borderTopWidth: 1, 154 | elevation: 0, 155 | height: 65, 156 | paddingTop: 2 157 | } 158 | }) 159 | 160 | const mapStateToProps = state => ({ 161 | tabs: state.tabs 162 | }) 163 | 164 | const mapDispatchToProps = { 165 | setTab 166 | } 167 | 168 | export default connect( 169 | mapStateToProps, 170 | mapDispatchToProps 171 | )(Tabs) 172 | -------------------------------------------------------------------------------- /components/List/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Image, RefreshControl, StyleSheet } from 'react-native' 3 | import { Content, Text, View } from 'native-base' 4 | import { connect } from 'react-redux' 5 | import Touchable from 'react-native-platform-touchable' 6 | 7 | import { Colors, Ranges, TextStrings } from '../../constants' 8 | import { getCrypto, getStock, setSymbol, setTab, showAutoSuggest } from '../../store/actions' 9 | import { formatPercentage, positiveOrNegative, upOrDownSymbol } from '../../helpers' 10 | 11 | import ListHeader from '../ListHeader' 12 | 13 | class List extends Component { 14 | onPress = symbol => { 15 | this.props.getStock(symbol, Ranges.ONE_MONTH) 16 | this.props.setSymbol(symbol) 17 | this.props.showAutoSuggest(false) 18 | this.props.setTab(1) 19 | } 20 | 21 | render() { 22 | return ( 23 | 24 | 25 | 33 | } 34 | style={styles.list} 35 | > 36 | {this.props.list.length === 0 && ( 37 | {this.props.noListData || TextStrings.NO_LIST_DATA} 38 | )} 39 | {this.props.list.map((stock, index) => { 40 | // const logo = `https://storage.googleapis.com/iex/api/logos/${stock.symbol}.png` 41 | 42 | return ( 43 | this.onPress(stock.symbol)} 48 | > 49 | 50 | {/* */} 51 | 52 | 53 | {stock.symbol} 54 | {stock.latestPrice} USD 55 | 56 | 57 | 58 | {stock.companyName} 59 | 60 | 61 | {stock.change} 62 | 63 | {' '} 64 | ({formatPercentage(stock.changePercent)} 65 | %) {upOrDownSymbol(stock.changePercent)} 66 | 67 | 68 | 69 | 70 | 71 | 72 | ) 73 | })} 74 | 75 | 76 | ) 77 | } 78 | } 79 | 80 | const styles = StyleSheet.create({ 81 | button: { 82 | backgroundColor: 'transparent', 83 | elevation: 0, 84 | flex: 1, 85 | flexDirection: 'column', 86 | paddingHorizontal: 16, 87 | paddingVertical: 12, 88 | width: '100%' 89 | }, 90 | rowContainer: { 91 | alignItems: 'center', 92 | flexDirection: 'row', 93 | width: '100%' 94 | }, 95 | textContainer: { 96 | flexGrow: 1 97 | }, 98 | textInnerContainer: { 99 | justifyContent: 'space-between', 100 | flexDirection: 'row', 101 | flexGrow: 1 102 | }, 103 | image: { 104 | borderRadius: 3, 105 | height: 28, 106 | marginRight: 16, 107 | width: 28 108 | }, 109 | companyName: { 110 | color: Colors.TEXT_DARK, 111 | flex: 1, 112 | fontSize: 13, 113 | paddingRight: 8 114 | }, 115 | stockChange: { 116 | fontSize: 13 117 | }, 118 | noData: { 119 | color: Colors.TEXT_DARK, 120 | fontSize: 13, 121 | padding: 20, 122 | textAlign: 'center' 123 | } 124 | }) 125 | 126 | const mapStateToProps = state => ({ 127 | crypto: state.crypto, 128 | symbol: state.symbol 129 | }) 130 | 131 | const mapDispatchToProps = { 132 | getCrypto, 133 | getStock, 134 | setSymbol, 135 | setTab, 136 | showAutoSuggest 137 | } 138 | 139 | export default connect( 140 | mapStateToProps, 141 | mapDispatchToProps 142 | )(List) 143 | -------------------------------------------------------------------------------- /native-base-theme/components/CardItem.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from "react-native"; 2 | import variable from "./../variables/platform"; 3 | 4 | export default (variables = variable) => { 5 | const platform = variables.platform; 6 | const transparentBtnCommon = { 7 | "NativeBase.Text": { 8 | fontSize: variables.DefaultFontSize - 3, 9 | color: variables.sTabBarActiveTextColor 10 | }, 11 | "NativeBase.Icon": { 12 | fontSize: variables.iconFontSize - 10, 13 | color: variables.sTabBarActiveTextColor, 14 | marginHorizontal: null 15 | }, 16 | "NativeBase.IconNB": { 17 | fontSize: variables.iconFontSize - 10, 18 | color: variables.sTabBarActiveTextColor 19 | }, 20 | paddingVertical: null, 21 | paddingHorizontal: null 22 | }; 23 | 24 | const cardItemTheme = { 25 | "NativeBase.Left": { 26 | "NativeBase.Body": { 27 | "NativeBase.Text": { 28 | ".note": { 29 | color: variables.listNoteColor, 30 | fontWeight: "400", 31 | marginRight: 20 32 | } 33 | }, 34 | flex: 1, 35 | marginLeft: 10, 36 | alignItems: null 37 | }, 38 | "NativeBase.Icon": { 39 | fontSize: variables.iconFontSize 40 | }, 41 | "NativeBase.IconNB": { 42 | fontSize: variables.iconFontSize 43 | }, 44 | "NativeBase.Text": { 45 | marginLeft: 10, 46 | alignSelf: "center" 47 | }, 48 | "NativeBase.Button": { 49 | ".transparent": { 50 | ...transparentBtnCommon, 51 | paddingRight: variables.cardItemPadding + 5 52 | } 53 | }, 54 | flex: 1, 55 | flexDirection: "row", 56 | alignItems: "center" 57 | }, 58 | ".content": { 59 | "NativeBase.Text": { 60 | color: platform === "ios" ? "#555" : "#222", 61 | fontSize: variables.DefaultFontSize - 2 62 | } 63 | }, 64 | ".cardBody": { 65 | padding: -5, 66 | "NativeBase.Text": { 67 | marginTop: 5 68 | } 69 | }, 70 | "NativeBase.Body": { 71 | "NativeBase.Text": { 72 | ".note": { 73 | color: variables.listNoteColor, 74 | fontWeight: "200", 75 | marginRight: 20 76 | } 77 | }, 78 | "NativeBase.Button": { 79 | ".transparent": { 80 | ...transparentBtnCommon, 81 | paddingRight: variables.cardItemPadding + 5, 82 | alignSelf: "stretch" 83 | } 84 | }, 85 | flex: 1, 86 | alignSelf: "stretch", 87 | alignItems: "flex-start" 88 | }, 89 | "NativeBase.Right": { 90 | "NativeBase.Badge": { 91 | alignSelf: null 92 | }, 93 | "NativeBase.Button": { 94 | ".transparent": { 95 | ...transparentBtnCommon 96 | }, 97 | alignSelf: null 98 | }, 99 | "NativeBase.Icon": { 100 | alignSelf: null, 101 | fontSize: variables.iconFontSize - 8, 102 | color: variables.cardBorderColor 103 | }, 104 | "NativeBase.IconNB": { 105 | alignSelf: null, 106 | fontSize: variables.iconFontSize - 8, 107 | color: variables.cardBorderColor 108 | }, 109 | "NativeBase.Text": { 110 | fontSize: variables.DefaultFontSize - 1, 111 | alignSelf: null 112 | }, 113 | "NativeBase.Thumbnail": { 114 | alignSelf: null 115 | }, 116 | "NativeBase.Image": { 117 | alignSelf: null 118 | }, 119 | "NativeBase.Radio": { 120 | alignSelf: null 121 | }, 122 | "NativeBase.Checkbox": { 123 | alignSelf: null 124 | }, 125 | "NativeBase.Switch": { 126 | alignSelf: null 127 | }, 128 | flex: 0.8 129 | }, 130 | ".header": { 131 | "NativeBase.Text": { 132 | fontSize: 16, 133 | fontWeight: platform === "ios" ? "600" : "500" 134 | }, 135 | ".bordered": { 136 | "NativeBase.Text": { 137 | color: variables.brandPrimary, 138 | fontWeight: platform === "ios" ? "600" : "500" 139 | }, 140 | borderBottomWidth: variables.borderWidth 141 | }, 142 | borderBottomWidth: null, 143 | paddingVertical: variables.cardItemPadding + 5 144 | }, 145 | ".footer": { 146 | "NativeBase.Text": { 147 | fontSize: 16, 148 | fontWeight: platform === "ios" ? "600" : "500" 149 | }, 150 | ".bordered": { 151 | "NativeBase.Text": { 152 | color: variables.brandPrimary, 153 | fontWeight: platform === "ios" ? "600" : "500" 154 | }, 155 | borderTopWidth: variables.borderWidth 156 | }, 157 | borderBottomWidth: null 158 | }, 159 | "NativeBase.Text": { 160 | ".note": { 161 | color: variables.listNoteColor, 162 | fontWeight: "200" 163 | } 164 | }, 165 | "NativeBase.Icon": { 166 | width: variables.iconFontSize + 5, 167 | fontSize: variables.iconFontSize - 2 168 | }, 169 | "NativeBase.IconNB": { 170 | width: variables.iconFontSize + 5, 171 | fontSize: variables.iconFontSize - 2 172 | }, 173 | ".bordered": { 174 | borderBottomWidth: StyleSheet.hairlineWidth, 175 | borderColor: variables.cardBorderColor 176 | }, 177 | ".first": { 178 | borderTopLeftRadius: variables.cardBorderRadius, 179 | borderTopRightRadius: variables.cardBorderRadius 180 | }, 181 | ".last": { 182 | borderBottomLeftRadius: variables.cardBorderRadius, 183 | borderBottomRightRadius: variables.cardBorderRadius 184 | }, 185 | flexDirection: "row", 186 | alignItems: "center", 187 | borderRadius: 2, 188 | padding: variables.cardItemPadding + 5, 189 | paddingVertical: variables.cardItemPadding, 190 | backgroundColor: variables.cardDefaultBg 191 | }; 192 | 193 | return cardItemTheme; 194 | }; 195 | -------------------------------------------------------------------------------- /components/Stock/Chart/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { ActivityIndicator, Dimensions, StyleSheet } from 'react-native' 3 | import { Text, View } from 'native-base' 4 | import { connect } from 'react-redux' 5 | import { LineSegment, VictoryChart, VictoryAxis, VictoryLabel, VictoryLine, VictoryTheme } from 'victory-native' 6 | import Touchable from 'react-native-platform-touchable' 7 | 8 | import { Colors, Ranges } from '../../../constants' 9 | import { getStockChart } from '../../../store/actions' 10 | 11 | class Chart extends Component { 12 | state = { 13 | ranges: [ 14 | // { label: '1d', range: Ranges.ONE_DAY }, 15 | { label: '1m', range: Ranges.ONE_MONTH }, 16 | { label: '3m', range: Ranges.THREE_MONTHS }, 17 | { label: '6m', range: Ranges.SIX_MONTHS }, 18 | { label: 'YTD', range: Ranges.YEAR_TO_DATE }, 19 | { label: '1y', range: Ranges.ONE_YEAR }, 20 | { label: '2y', range: Ranges.TWO_YEARS }, 21 | { label: '5y', range: Ranges.FIVE_YEARS } 22 | ] 23 | } 24 | 25 | activeRangeStyles = range => (this.props.stock.range.query === range ? styles.rangesActive : null) 26 | 27 | positiveOrNegativeOverTime = (x, y) => 28 | x > y ? { ...svgStyles.chartLine, ...svgStyles.negative } : { ...svgStyles.chartLine, ...svgStyles.positive } 29 | 30 | chartWidth = (highestClosePrice, width) => { 31 | const length = Math.round(highestClosePrice).toString().length 32 | 33 | switch (length) { 34 | case 6: 35 | return { marginLeft: 18, width: width + 2 } 36 | case 5: 37 | return { marginLeft: 12, width: width + 8 } 38 | case 4: 39 | return { marginLeft: 6, width: width + 14 } 40 | case 3: 41 | return { marginLeft: 2, width: width + 20 } 42 | case 2: 43 | return { marginLeft: -2, width: width + 24 } 44 | case 1: 45 | return { marginLeft: -10, width: width + 32 } 46 | default: 47 | return { marginLeft: 0, width: width } 48 | } 49 | } 50 | 51 | render() { 52 | const { chart, quote } = this.props.stock.data 53 | const { width } = Dimensions.get('window') 54 | 55 | if (!chart || chart.length === 0) return null 56 | 57 | if (this.props.stock.chartLoading) 58 | return ( 59 | 60 | 61 | 62 | ) 63 | 64 | const _chart = chart 65 | .filter(interval => interval.close || interval.marketClose) 66 | .map(interval => ({ 67 | close: interval.close || interval.marketClose, 68 | label: interval.label 69 | })) 70 | 71 | const highestClosePrice = Math.max.apply(Math, _chart.map(interval => interval.close)) 72 | const label = 73 | const lineSegment = 74 | 75 | return ( 76 | 77 | 78 | {this.state.ranges.map((range, index) => ( 79 | this.props.getStockChart(quote.symbol, range.range)} 83 | style={styles.rangesButton} 84 | > 85 | {range.label} 86 | 87 | ))} 88 | 89 | 93 | 98 | } 103 | /> 104 | t.toLocaleString('en-US')} 109 | /> 110 | 116 | 117 | 118 | 119 | ) 120 | } 121 | } 122 | 123 | const styles = StyleSheet.create({ 124 | spinner: { 125 | height: 250, 126 | justifyContent: 'center' 127 | }, 128 | chart: { 129 | marginBottom: -10, 130 | marginTop: -36 131 | }, 132 | rangesActive: { 133 | color: Colors.TEXT_NORMAL 134 | }, 135 | rangesContainer: { 136 | flexDirection: 'row', 137 | justifyContent: 'space-between', 138 | marginBottom: 8, 139 | paddingHorizontal: 16 140 | }, 141 | rangesButton: { 142 | alignItems: 'center', 143 | flex: 1, 144 | paddingVertical: 12 145 | }, 146 | rangesLabel: { 147 | color: Colors.TEXT_DARK, 148 | fontSize: 12 149 | } 150 | }) 151 | 152 | const svgStyles = { 153 | positive: { 154 | data: { 155 | stroke: Colors.GREEN 156 | } 157 | }, 158 | negative: { 159 | data: { 160 | stroke: Colors.RED 161 | } 162 | }, 163 | chartGrid: { 164 | stroke: Colors.BLUE2 165 | }, 166 | chartLabel: { 167 | fill: Colors.TEXT_DARK, 168 | fontSize: '11', 169 | stroke: 'transparent' 170 | }, 171 | chartLine: { 172 | labels: { 173 | fill: 'transparent' 174 | } 175 | } 176 | } 177 | 178 | const mapStateToProps = state => { 179 | return { 180 | stock: state.stock 181 | } 182 | } 183 | 184 | const mapDispatchToProps = { 185 | getStockChart 186 | } 187 | 188 | export default connect( 189 | mapStateToProps, 190 | mapDispatchToProps 191 | )(Chart) 192 | -------------------------------------------------------------------------------- /native-base-theme/components/index.js: -------------------------------------------------------------------------------- 1 | import _ from "lodash"; 2 | import bodyTheme from "./Body"; 3 | import leftTheme from "./Left"; 4 | import rightTheme from "./Right"; 5 | import headerTheme from "./Header"; 6 | import switchTheme from "./Switch"; 7 | import thumbnailTheme from "./Thumbnail"; 8 | import containerTheme from "./Container"; 9 | import contentTheme from "./Content"; 10 | import buttonTheme from "./Button"; 11 | import titleTheme from "./Title"; 12 | import subtitleTheme from "./Subtitle"; 13 | import inputGroupTheme from "./InputGroup"; 14 | import badgeTheme from "./Badge"; 15 | import checkBoxTheme from "./CheckBox"; 16 | import cardTheme from "./Card"; 17 | import radioTheme from "./Radio"; 18 | import h3Theme from "./H3"; 19 | import h2Theme from "./H2"; 20 | import h1Theme from "./H1"; 21 | import footerTheme from "./Footer"; 22 | import footerTabTheme from "./FooterTab"; 23 | import fabTheme from "./Fab"; 24 | import itemTheme from "./Item"; 25 | import labelTheme from "./Label"; 26 | import textAreaTheme from "./Textarea"; 27 | import textTheme from "./Text"; 28 | import toastTheme from "./Toast"; 29 | import tabTheme from "./Tab"; 30 | import tabBarTheme from "./TabBar"; 31 | import tabContainerTheme from "./TabContainer"; 32 | import viewTheme from "./View"; 33 | import tabHeadingTheme from "./TabHeading"; 34 | import iconTheme from "./Icon"; 35 | import inputTheme from "./Input"; 36 | import swipeRowTheme from "./SwipeRow"; 37 | import segmentTheme from "./Segment"; 38 | import spinnerTheme from "./Spinner"; 39 | import cardItemTheme from "./CardItem"; 40 | import listItemTheme from "./ListItem"; 41 | import formTheme from "./Form"; 42 | import separatorTheme from "./Separator"; 43 | import pickerTheme from "./Picker" 44 | import variable from "./../variables/platform"; 45 | 46 | export default (variables = variable) => { 47 | const theme = { 48 | variables, 49 | "NativeBase.Left": { 50 | ...leftTheme(variables) 51 | }, 52 | "NativeBase.Right": { 53 | ...rightTheme(variables) 54 | }, 55 | "NativeBase.Body": { 56 | ...bodyTheme(variables) 57 | }, 58 | 59 | "NativeBase.Header": { 60 | ...headerTheme(variables) 61 | }, 62 | 63 | "NativeBase.Button": { 64 | ...buttonTheme(variables) 65 | }, 66 | 67 | "NativeBase.Title": { 68 | ...titleTheme(variables) 69 | }, 70 | "NativeBase.Subtitle": { 71 | ...subtitleTheme(variables) 72 | }, 73 | 74 | "NativeBase.InputGroup": { 75 | ...inputGroupTheme(variables) 76 | }, 77 | 78 | "NativeBase.Input": { 79 | ...inputTheme(variables) 80 | }, 81 | 82 | "NativeBase.Badge": { 83 | ...badgeTheme(variables) 84 | }, 85 | 86 | "NativeBase.CheckBox": { 87 | ...checkBoxTheme(variables) 88 | }, 89 | 90 | "NativeBase.Radio": { 91 | ...radioTheme(variables) 92 | }, 93 | 94 | "NativeBase.Card": { 95 | ...cardTheme() 96 | }, 97 | 98 | "NativeBase.CardItem": { 99 | ...cardItemTheme(variables) 100 | }, 101 | 102 | "NativeBase.Toast": { 103 | ...toastTheme(variables) 104 | }, 105 | 106 | "NativeBase.H1": { 107 | ...h1Theme(variables) 108 | }, 109 | "NativeBase.H2": { 110 | ...h2Theme(variables) 111 | }, 112 | "NativeBase.H3": { 113 | ...h3Theme(variables) 114 | }, 115 | "NativeBase.Form": { 116 | ...formTheme(variables) 117 | }, 118 | 119 | "NativeBase.Container": { 120 | ...containerTheme(variables) 121 | }, 122 | "NativeBase.Content": { 123 | ...contentTheme(variables) 124 | }, 125 | 126 | "NativeBase.Footer": { 127 | ...footerTheme(variables) 128 | }, 129 | 130 | "NativeBase.Tabs": { 131 | flex: 1 132 | }, 133 | 134 | "NativeBase.FooterTab": { 135 | ...footerTabTheme(variables) 136 | }, 137 | 138 | "NativeBase.ListItem": { 139 | ...listItemTheme(variables) 140 | }, 141 | 142 | "NativeBase.ListItem1": { 143 | ...listItemTheme(variables) 144 | }, 145 | 146 | "NativeBase.Icon": { 147 | ...iconTheme(variables) 148 | }, 149 | "NativeBase.IconNB": { 150 | ...iconTheme(variables) 151 | }, 152 | "NativeBase.Text": { 153 | ...textTheme(variables) 154 | }, 155 | "NativeBase.Spinner": { 156 | ...spinnerTheme(variables) 157 | }, 158 | 159 | "NativeBase.Fab": { 160 | ...fabTheme(variables) 161 | }, 162 | 163 | "NativeBase.Item": { 164 | ...itemTheme(variables) 165 | }, 166 | 167 | "NativeBase.Label": { 168 | ...labelTheme(variables) 169 | }, 170 | 171 | "NativeBase.Textarea": { 172 | ...textAreaTheme(variables) 173 | }, 174 | 175 | "NativeBase.PickerNB": { 176 | ...pickerTheme(variables), 177 | "NativeBase.Button": { 178 | "NativeBase.Text": {} 179 | } 180 | }, 181 | 182 | "NativeBase.Tab": { 183 | ...tabTheme(variables) 184 | }, 185 | 186 | "NativeBase.Segment": { 187 | ...segmentTheme(variables) 188 | }, 189 | 190 | "NativeBase.TabBar": { 191 | ...tabBarTheme(variables) 192 | }, 193 | "NativeBase.ViewNB": { 194 | ...viewTheme(variables) 195 | }, 196 | "NativeBase.TabHeading": { 197 | ...tabHeadingTheme(variables) 198 | }, 199 | "NativeBase.TabContainer": { 200 | ...tabContainerTheme(variables) 201 | }, 202 | "NativeBase.Switch": { 203 | ...switchTheme(variables) 204 | }, 205 | "NativeBase.Separator": { 206 | ...separatorTheme(variables) 207 | }, 208 | "NativeBase.SwipeRow": { 209 | ...swipeRowTheme(variables) 210 | }, 211 | "NativeBase.Thumbnail": { 212 | ...thumbnailTheme(variables) 213 | } 214 | }; 215 | 216 | const cssifyTheme = (grandparent, parent, parentKey) => { 217 | _.forEach(parent, (style, styleName) => { 218 | // console.log('styleName', styleName); 219 | // console.log('parentKey', parentKey); 220 | if ( 221 | styleName.indexOf(".") === 0 && 222 | parentKey && 223 | parentKey.indexOf(".") === 0 224 | ) { 225 | if (grandparent) { 226 | if (!grandparent[styleName]) { 227 | grandparent[styleName] = {}; 228 | } else { 229 | grandparent[styleName][parentKey] = style; 230 | } 231 | } 232 | } 233 | if (style && typeof style === "object" && styleName !== "fontVariant" && styleName !== "transform") { 234 | cssifyTheme(parent, style, styleName); 235 | } 236 | }); 237 | }; 238 | 239 | cssifyTheme(null, theme, null); 240 | 241 | return theme; 242 | }; 243 | -------------------------------------------------------------------------------- /native-base-theme/components/Item.js: -------------------------------------------------------------------------------- 1 | import { Platform } from "react-native"; 2 | 3 | import variable from "./../variables/platform"; 4 | 5 | export default (variables = variable) => { 6 | const itemTheme = { 7 | ".floatingLabel": { 8 | "NativeBase.Input": { 9 | height: 50, 10 | top: 8, 11 | paddingTop: 3, 12 | paddingBottom: 7, 13 | ".multiline": { 14 | minHeight: variables.inputHeightBase, 15 | paddingTop: Platform.OS === "ios" ? 10 : 3, 16 | paddingBottom: Platform.OS === "ios" ? 14 : 10 17 | } 18 | }, 19 | "NativeBase.Label": { 20 | top: 8 21 | }, 22 | "NativeBase.Icon": { 23 | top: 6, 24 | paddingTop: 8 25 | }, 26 | "NativeBase.IconNB": { 27 | top: 6, 28 | paddingTop: 8 29 | } 30 | }, 31 | ".fixedLabel": { 32 | "NativeBase.Label": { 33 | position: null, 34 | top: null, 35 | left: null, 36 | right: null, 37 | flex: 1, 38 | height: null, 39 | width: null, 40 | fontSize: variables.inputFontSize 41 | }, 42 | "NativeBase.Input": { 43 | flex: 2, 44 | fontSize: variables.inputFontSize 45 | } 46 | }, 47 | ".stackedLabel": { 48 | "NativeBase.Label": { 49 | position: null, 50 | top: null, 51 | left: null, 52 | right: null, 53 | paddingTop: 5, 54 | alignSelf: "flex-start", 55 | fontSize: variables.inputFontSize - 2 56 | }, 57 | "NativeBase.Icon": { 58 | marginTop: 36 59 | }, 60 | "NativeBase.Input": { 61 | alignSelf: Platform.OS === "ios" ? "stretch" : "flex-start", 62 | flex: 1, 63 | width: Platform.OS === "ios" ? null : variables.deviceWidth - 25, 64 | fontSize: variables.inputFontSize, 65 | lineHeight: variables.inputLineHeight - 6, 66 | ".secureTextEntry": { 67 | fontSize: variables.inputFontSize - 4 68 | }, 69 | ".multiline": { 70 | paddingTop: Platform.OS === "ios" ? 9 : undefined, 71 | paddingBottom: Platform.OS === "ios" ? 9 : undefined 72 | } 73 | }, 74 | flexDirection: null, 75 | minHeight: variables.inputHeightBase + 15 76 | }, 77 | ".inlineLabel": { 78 | "NativeBase.Label": { 79 | position: null, 80 | top: null, 81 | left: null, 82 | right: null, 83 | paddingRight: 20, 84 | height: null, 85 | width: null, 86 | fontSize: variables.inputFontSize 87 | }, 88 | "NativeBase.Input": { 89 | paddingLeft: 5, 90 | fontSize: variables.inputFontSize 91 | }, 92 | flexDirection: "row" 93 | }, 94 | "NativeBase.Label": { 95 | fontSize: variables.inputFontSize, 96 | color: variables.inputColorPlaceholder, 97 | paddingRight: 5 98 | }, 99 | "NativeBase.Icon": { 100 | fontSize: 24, 101 | paddingRight: 8 102 | }, 103 | "NativeBase.IconNB": { 104 | fontSize: 24, 105 | paddingRight: 8 106 | }, 107 | "NativeBase.Input": { 108 | ".multiline": { 109 | height: null 110 | }, 111 | height: variables.inputHeightBase, 112 | color: variables.inputColor, 113 | flex: 1, 114 | top: Platform.OS === "ios" ? 1.5 : undefined, 115 | fontSize: variables.inputFontSize 116 | }, 117 | ".underline": { 118 | "NativeBase.Input": { 119 | paddingLeft: 15 120 | }, 121 | ".success": { 122 | borderColor: variables.inputSuccessBorderColor 123 | }, 124 | ".error": { 125 | borderColor: variables.inputErrorBorderColor 126 | }, 127 | borderWidth: variables.borderWidth * 2, 128 | borderTopWidth: 0, 129 | borderRightWidth: 0, 130 | borderLeftWidth: 0, 131 | borderColor: variables.inputBorderColor 132 | }, 133 | ".regular": { 134 | "NativeBase.Input": { 135 | paddingLeft: 8 136 | }, 137 | "NativeBase.Icon": { 138 | paddingLeft: 10 139 | }, 140 | ".success": { 141 | borderColor: variables.inputSuccessBorderColor 142 | }, 143 | ".error": { 144 | borderColor: variables.inputErrorBorderColor 145 | }, 146 | borderWidth: variables.borderWidth * 2, 147 | borderColor: variables.inputBorderColor 148 | }, 149 | ".rounded": { 150 | "NativeBase.Input": { 151 | paddingLeft: 8 152 | }, 153 | "NativeBase.Icon": { 154 | paddingLeft: 10 155 | }, 156 | ".success": { 157 | borderColor: variables.inputSuccessBorderColor 158 | }, 159 | ".error": { 160 | borderColor: variables.inputErrorBorderColor 161 | }, 162 | borderWidth: variables.borderWidth * 2, 163 | borderRadius: 30, 164 | borderColor: variables.inputBorderColor 165 | }, 166 | 167 | ".success": { 168 | "NativeBase.Icon": { 169 | color: variables.inputSuccessBorderColor 170 | }, 171 | "NativeBase.IconNB": { 172 | color: variables.inputSuccessBorderColor 173 | }, 174 | ".rounded": { 175 | borderRadius: 30, 176 | borderColor: variables.inputSuccessBorderColor 177 | }, 178 | ".regular": { 179 | borderColor: variables.inputSuccessBorderColor 180 | }, 181 | ".underline": { 182 | borderWidth: variables.borderWidth * 2, 183 | borderTopWidth: 0, 184 | borderRightWidth: 0, 185 | borderLeftWidth: 0, 186 | borderColor: variables.inputSuccessBorderColor 187 | }, 188 | borderColor: variables.inputSuccessBorderColor 189 | }, 190 | 191 | ".error": { 192 | "NativeBase.Icon": { 193 | color: variables.inputErrorBorderColor 194 | }, 195 | "NativeBase.IconNB": { 196 | color: variables.inputErrorBorderColor 197 | }, 198 | ".rounded": { 199 | borderRadius: 30, 200 | borderColor: variables.inputErrorBorderColor 201 | }, 202 | ".regular": { 203 | borderColor: variables.inputErrorBorderColor 204 | }, 205 | ".underline": { 206 | borderWidth: variables.borderWidth * 2, 207 | borderTopWidth: 0, 208 | borderRightWidth: 0, 209 | borderLeftWidth: 0, 210 | borderColor: variables.inputErrorBorderColor 211 | }, 212 | borderColor: variables.inputErrorBorderColor 213 | }, 214 | ".disabled": { 215 | "NativeBase.Icon": { 216 | color: "#384850" 217 | }, 218 | "NativeBase.IconNB": { 219 | color: "#384850" 220 | } 221 | }, 222 | ".picker": { 223 | marginLeft: 0 224 | }, 225 | 226 | borderWidth: variables.borderWidth * 2, 227 | borderTopWidth: 0, 228 | borderRightWidth: 0, 229 | borderLeftWidth: 0, 230 | borderColor: variables.inputBorderColor, 231 | backgroundColor: "transparent", 232 | flexDirection: "row", 233 | alignItems: "center", 234 | marginLeft: 2 235 | }; 236 | 237 | return itemTheme; 238 | }; 239 | -------------------------------------------------------------------------------- /native-base-theme/variables/material.js: -------------------------------------------------------------------------------- 1 | import color from "color"; 2 | 3 | import { Platform, Dimensions, PixelRatio } from "react-native"; 4 | 5 | const deviceHeight = Dimensions.get("window").height; 6 | const deviceWidth = Dimensions.get("window").width; 7 | const platform = Platform.OS; 8 | const platformStyle = "material"; 9 | const isIphoneX = 10 | platform === "ios" && (deviceHeight === 812 || deviceWidth === 812); 11 | 12 | export default { 13 | platformStyle, 14 | platform, 15 | 16 | //Accordion 17 | headerStyle: "#edebed", 18 | iconStyle: "#000", 19 | contentStyle: "#f5f4f5", 20 | expandedIconStyle: "#000", 21 | accordionBorderColor: "#d3d3d3", 22 | 23 | // Android 24 | androidRipple: true, 25 | androidRippleColor: "rgba(256, 256, 256, 0.3)", 26 | androidRippleColorDark: "rgba(0, 0, 0, 0.15)", 27 | btnUppercaseAndroidText: true, 28 | 29 | // Badge 30 | badgeBg: "#ED1727", 31 | badgeColor: "#fff", 32 | badgePadding: 0, 33 | 34 | // Button 35 | btnFontFamily: "Roboto", 36 | btnDisabledBg: "#b5b5b5", 37 | buttonPadding: 6, 38 | get btnPrimaryBg() { 39 | return this.brandPrimary; 40 | }, 41 | get btnPrimaryColor() { 42 | return this.inverseTextColor; 43 | }, 44 | get btnInfoBg() { 45 | return this.brandInfo; 46 | }, 47 | get btnInfoColor() { 48 | return this.inverseTextColor; 49 | }, 50 | get btnSuccessBg() { 51 | return this.brandSuccess; 52 | }, 53 | get btnSuccessColor() { 54 | return this.inverseTextColor; 55 | }, 56 | get btnDangerBg() { 57 | return this.brandDanger; 58 | }, 59 | get btnDangerColor() { 60 | return this.inverseTextColor; 61 | }, 62 | get btnWarningBg() { 63 | return this.brandWarning; 64 | }, 65 | get btnWarningColor() { 66 | return this.inverseTextColor; 67 | }, 68 | get btnTextSize() { 69 | return this.fontSizeBase - 1; 70 | }, 71 | get btnTextSizeLarge() { 72 | return this.fontSizeBase * 1.5; 73 | }, 74 | get btnTextSizeSmall() { 75 | return this.fontSizeBase * 0.8; 76 | }, 77 | get borderRadiusLarge() { 78 | return this.fontSizeBase * 3.8; 79 | }, 80 | get iconSizeLarge() { 81 | return this.iconFontSize * 1.5; 82 | }, 83 | get iconSizeSmall() { 84 | return this.iconFontSize * 0.6; 85 | }, 86 | 87 | // Card 88 | cardDefaultBg: "#fff", 89 | cardBorderColor: "#ccc", 90 | cardBorderRadius: 2, 91 | cardItemPadding: platform === "ios" ? 10 : 12, 92 | 93 | // CheckBox 94 | CheckboxRadius: 0, 95 | CheckboxBorderWidth: 2, 96 | CheckboxPaddingLeft: 2, 97 | CheckboxPaddingBottom: 5, 98 | CheckboxIconSize: 16, 99 | CheckboxIconMarginTop: 1, 100 | CheckboxFontSize: 17, 101 | checkboxBgColor: "#039BE5", 102 | checkboxSize: 20, 103 | checkboxTickColor: "#fff", 104 | 105 | // Color 106 | brandPrimary: "#3F51B5", 107 | brandInfo: "#62B1F6", 108 | brandSuccess: "#5cb85c", 109 | brandDanger: "#d9534f", 110 | brandWarning: "#f0ad4e", 111 | brandDark: "#000", 112 | brandLight: "#f4f4f4", 113 | 114 | //Container 115 | containerBgColor: "#fff", 116 | 117 | //Date Picker 118 | datePickerTextColor: "#000", 119 | datePickerBg: "transparent", 120 | 121 | // Font 122 | DefaultFontSize: 16, 123 | fontFamily: "Roboto", 124 | fontSizeBase: 15, 125 | get fontSizeH1() { 126 | return this.fontSizeBase * 1.8; 127 | }, 128 | get fontSizeH2() { 129 | return this.fontSizeBase * 1.6; 130 | }, 131 | get fontSizeH3() { 132 | return this.fontSizeBase * 1.4; 133 | }, 134 | 135 | // Footer 136 | footerHeight: 55, 137 | footerDefaultBg: "#3F51B5", 138 | footerPaddingBottom: 0, 139 | 140 | // FooterTab 141 | tabBarTextColor: "#bfc6ea", 142 | tabBarTextSize: 11, 143 | activeTab: "#fff", 144 | sTabBarActiveTextColor: "#007aff", 145 | tabBarActiveTextColor: "#fff", 146 | tabActiveBgColor: "#3F51B5", 147 | 148 | // Header 149 | toolbarBtnColor: "#fff", 150 | toolbarDefaultBg: "#3F51B5", 151 | toolbarHeight: 56, 152 | toolbarSearchIconSize: 23, 153 | toolbarInputColor: "#fff", 154 | searchBarHeight: platform === "ios" ? 30 : 40, 155 | searchBarInputHeight: platform === "ios" ? 40 : 50, 156 | toolbarBtnTextColor: "#fff", 157 | toolbarDefaultBorder: "#3F51B5", 158 | iosStatusbar: "light-content", 159 | get statusBarColor() { 160 | return color(this.toolbarDefaultBg) 161 | .darken(0.2) 162 | .hex(); 163 | }, 164 | get darkenHeader() { 165 | return color(this.tabBgColor) 166 | .darken(0.03) 167 | .hex(); 168 | }, 169 | 170 | // Icon 171 | iconFamily: "Ionicons", 172 | iconFontSize: 28, 173 | iconHeaderSize: 24, 174 | 175 | // InputGroup 176 | inputFontSize: 17, 177 | inputBorderColor: "#D9D5DC", 178 | inputSuccessBorderColor: "#2b8339", 179 | inputErrorBorderColor: "#ed2f2f", 180 | inputHeightBase: 50, 181 | get inputColor() { 182 | return this.textColor; 183 | }, 184 | get inputColorPlaceholder() { 185 | return "#575757"; 186 | }, 187 | 188 | // Line Height 189 | btnLineHeight: 19, 190 | lineHeightH1: 32, 191 | lineHeightH2: 27, 192 | lineHeightH3: 22, 193 | lineHeight: 24, 194 | 195 | // List 196 | listBg: "transparent", 197 | listBorderColor: "#c9c9c9", 198 | listDividerBg: "#f4f4f4", 199 | listBtnUnderlayColor: "#DDD", 200 | listItemPadding: 12, 201 | listNoteColor: "#808080", 202 | listNoteSize: 13, 203 | listItemSelected: "#3F51B5", 204 | 205 | // Progress Bar 206 | defaultProgressColor: "#E4202D", 207 | inverseProgressColor: "#1A191B", 208 | 209 | // Radio Button 210 | radioBtnSize: 23, 211 | radioSelectedColorAndroid: "#3F51B5", 212 | radioBtnLineHeight: 24, 213 | get radioColor() { 214 | return this.brandPrimary; 215 | }, 216 | 217 | // Segment 218 | segmentBackgroundColor: "#3F51B5", 219 | segmentActiveBackgroundColor: "#fff", 220 | segmentTextColor: "#fff", 221 | segmentActiveTextColor: "#3F51B5", 222 | segmentBorderColor: "#fff", 223 | segmentBorderColorMain: "#3F51B5", 224 | 225 | // Spinner 226 | defaultSpinnerColor: "#45D56E", 227 | inverseSpinnerColor: "#1A191B", 228 | 229 | // Tab 230 | tabDefaultBg: "#3F51B5", 231 | topTabBarTextColor: "#b3c7f9", 232 | topTabBarActiveTextColor: "#fff", 233 | topTabBarBorderColor: "#fff", 234 | topTabBarActiveBorderColor: "#fff", 235 | 236 | // Tabs 237 | tabBgColor: "#F8F8F8", 238 | tabFontSize: 15, 239 | 240 | // Text 241 | textColor: "#000", 242 | inverseTextColor: "#fff", 243 | noteFontSize: 14, 244 | get defaultTextColor() { 245 | return this.textColor; 246 | }, 247 | 248 | // Title 249 | titleFontfamily: "Roboto", 250 | titleFontSize: 19, 251 | subTitleFontSize: 14, 252 | subtitleColor: "#FFF", 253 | titleFontColor: "#FFF", 254 | 255 | // Other 256 | borderRadiusBase: 2, 257 | borderWidth: 1 / PixelRatio.getPixelSizeForLayoutSize(1), 258 | contentPadding: 10, 259 | dropdownLinkColor: "#414142", 260 | inputLineHeight: 24, 261 | deviceWidth, 262 | deviceHeight, 263 | isIphoneX, 264 | inputGroupRoundedBorderRadius: 30, 265 | 266 | //iPhoneX SafeArea 267 | Inset: { 268 | portrait: { 269 | topInset: 24, 270 | leftInset: 0, 271 | rightInset: 0, 272 | bottomInset: 34 273 | }, 274 | landscape: { 275 | topInset: 0, 276 | leftInset: 44, 277 | rightInset: 44, 278 | bottomInset: 21 279 | } 280 | } 281 | }; 282 | -------------------------------------------------------------------------------- /native-base-theme/variables/commonColor.js: -------------------------------------------------------------------------------- 1 | import color from "color"; 2 | 3 | import { Platform, Dimensions, PixelRatio } from "react-native"; 4 | 5 | const deviceHeight = Dimensions.get("window").height; 6 | const deviceWidth = Dimensions.get("window").width; 7 | const platform = Platform.OS; 8 | const platformStyle = undefined; 9 | const isIphoneX = 10 | platform === "ios" && (deviceHeight === 812 || deviceWidth === 812); 11 | 12 | export default { 13 | platformStyle, 14 | platform, 15 | 16 | //Accordion 17 | headerStyle: "#edebed", 18 | iconStyle: "#000", 19 | contentStyle: "#f5f4f5", 20 | expandedIconStyle: "#000", 21 | accordionBorderColor: "#d3d3d3", 22 | 23 | //Android 24 | androidRipple: true, 25 | androidRippleColor: "rgba(256, 256, 256, 0.3)", 26 | androidRippleColorDark: "rgba(0, 0, 0, 0.15)", 27 | btnUppercaseAndroidText: true, 28 | 29 | // Badge 30 | badgeBg: "#ED1727", 31 | badgeColor: "#fff", 32 | badgePadding: platform === "ios" ? 3 : 0, 33 | 34 | // Button 35 | btnFontFamily: platform === "ios" ? "System" : "Roboto_medium", 36 | btnDisabledBg: "#b5b5b5", 37 | buttonPadding: 6, 38 | get btnPrimaryBg() { 39 | return this.brandPrimary; 40 | }, 41 | get btnPrimaryColor() { 42 | return this.inverseTextColor; 43 | }, 44 | get btnInfoBg() { 45 | return this.brandInfo; 46 | }, 47 | get btnInfoColor() { 48 | return this.inverseTextColor; 49 | }, 50 | get btnSuccessBg() { 51 | return this.brandSuccess; 52 | }, 53 | get btnSuccessColor() { 54 | return this.inverseTextColor; 55 | }, 56 | get btnDangerBg() { 57 | return this.brandDanger; 58 | }, 59 | get btnDangerColor() { 60 | return this.inverseTextColor; 61 | }, 62 | get btnWarningBg() { 63 | return this.brandWarning; 64 | }, 65 | get btnWarningColor() { 66 | return this.inverseTextColor; 67 | }, 68 | get btnTextSize() { 69 | return platform === "ios" ? this.fontSizeBase * 1.1 : this.fontSizeBase - 1; 70 | }, 71 | get btnTextSizeLarge() { 72 | return this.fontSizeBase * 1.5; 73 | }, 74 | get btnTextSizeSmall() { 75 | return this.fontSizeBase * 0.8; 76 | }, 77 | get borderRadiusLarge() { 78 | return this.fontSizeBase * 3.8; 79 | }, 80 | get iconSizeLarge() { 81 | return this.iconFontSize * 1.5; 82 | }, 83 | get iconSizeSmall() { 84 | return this.iconFontSize * 0.6; 85 | }, 86 | 87 | // Card 88 | cardDefaultBg: "#fff", 89 | cardBorderColor: "#ccc", 90 | cardBorderRadius: 2, 91 | cardItemPadding: platform === "ios" ? 10 : 12, 92 | 93 | // CheckBox 94 | CheckboxRadius: platform === "ios" ? 13 : 0, 95 | CheckboxBorderWidth: platform === "ios" ? 1 : 2, 96 | CheckboxPaddingLeft: platform === "ios" ? 4 : 2, 97 | CheckboxPaddingBottom: platform === "ios" ? 0 : 5, 98 | CheckboxIconSize: platform === "ios" ? 21 : 16, 99 | CheckboxIconMarginTop: platform === "ios" ? undefined : 1, 100 | CheckboxFontSize: platform === "ios" ? 23 / 0.9 : 17, 101 | checkboxBgColor: "#039BE5", 102 | checkboxSize: 20, 103 | checkboxTickColor: "#fff", 104 | 105 | // Color 106 | brandPrimary: platform === "ios" ? "#007aff" : "#3F51B5", 107 | brandInfo: "#62B1F6", 108 | brandSuccess: "#5cb85c", 109 | brandDanger: "#d9534f", 110 | brandWarning: "#f0ad4e", 111 | brandDark: "#000", 112 | brandLight: "#f4f4f4", 113 | 114 | //Container 115 | containerBgColor: "#fff", 116 | 117 | //Date Picker 118 | datePickerTextColor: "#000", 119 | datePickerBg: "transparent", 120 | 121 | // Font 122 | DefaultFontSize: 16, 123 | fontFamily: platform === "ios" ? "System" : "Roboto", 124 | fontSizeBase: 15, 125 | get fontSizeH1() { 126 | return this.fontSizeBase * 1.8; 127 | }, 128 | get fontSizeH2() { 129 | return this.fontSizeBase * 1.6; 130 | }, 131 | get fontSizeH3() { 132 | return this.fontSizeBase * 1.4; 133 | }, 134 | 135 | // Footer 136 | footerHeight: 55, 137 | footerDefaultBg: platform === "ios" ? "#F8F8F8" : "#3F51B5", 138 | footerPaddingBottom: 0, 139 | 140 | // FooterTab 141 | tabBarTextColor: platform === "ios" ? "#737373" : "#bfc6ea", 142 | tabBarTextSize: platform === "ios" ? 14 : 11, 143 | activeTab: platform === "ios" ? "#007aff" : "#fff", 144 | sTabBarActiveTextColor: "#007aff", 145 | tabBarActiveTextColor: platform === "ios" ? "#2874F0" : "#fff", 146 | tabActiveBgColor: platform === "ios" ? "#cde1f9" : "#3F51B5", 147 | 148 | // Header 149 | toolbarBtnColor: platform === "ios" ? "#007aff" : "#fff", 150 | toolbarDefaultBg: platform === "ios" ? "#F8F8F8" : "#3F51B5", 151 | toolbarHeight: platform === "ios" ? 64 : 56, 152 | toolbarSearchIconSize: platform === "ios" ? 20 : 23, 153 | toolbarInputColor: platform === "ios" ? "#CECDD2" : "#fff", 154 | searchBarHeight: platform === "ios" ? 30 : 40, 155 | searchBarInputHeight: platform === "ios" ? 30 : 50, 156 | toolbarBtnTextColor: platform === "ios" ? "#007aff" : "#fff", 157 | iosStatusbar: "dark-content", 158 | toolbarDefaultBorder: platform === "ios" ? "#a7a6ab" : "#3F51B5", 159 | get statusBarColor() { 160 | return color(this.toolbarDefaultBg) 161 | .darken(0.2) 162 | .hex(); 163 | }, 164 | get darkenHeader() { 165 | return color(this.tabBgColor) 166 | .darken(0.03) 167 | .hex(); 168 | }, 169 | 170 | // Icon 171 | iconFamily: "Ionicons", 172 | iconFontSize: platform === "ios" ? 30 : 28, 173 | iconHeaderSize: platform === "ios" ? 33 : 24, 174 | 175 | // InputGroup 176 | inputFontSize: 17, 177 | inputBorderColor: "#D9D5DC", 178 | inputSuccessBorderColor: "#2b8339", 179 | inputErrorBorderColor: "#ed2f2f", 180 | inputHeightBase: 50, 181 | get inputColor() { 182 | return this.textColor; 183 | }, 184 | get inputColorPlaceholder() { 185 | return "#575757"; 186 | }, 187 | 188 | // Line Height 189 | btnLineHeight: 19, 190 | lineHeightH1: 32, 191 | lineHeightH2: 27, 192 | lineHeightH3: 22, 193 | lineHeight: platform === "ios" ? 20 : 24, 194 | 195 | // List 196 | listBg: "transparent", 197 | listBorderColor: "#c9c9c9", 198 | listDividerBg: "#f4f4f4", 199 | listBtnUnderlayColor: "#DDD", 200 | listItemPadding: platform === "ios" ? 10 : 12, 201 | listNoteColor: "#808080", 202 | listNoteSize: 13, 203 | listItemSelected: platform === "ios" ? "#007aff" : "#3F51B5", 204 | 205 | // Progress Bar 206 | defaultProgressColor: "#E4202D", 207 | inverseProgressColor: "#1A191B", 208 | 209 | // Radio Button 210 | radioBtnSize: platform === "ios" ? 25 : 23, 211 | radioSelectedColorAndroid: "#3F51B5", 212 | radioBtnLineHeight: platform === "ios" ? 29 : 24, 213 | get radioColor() { 214 | return this.brandPrimary; 215 | }, 216 | 217 | // Segment 218 | segmentBackgroundColor: platform === "ios" ? "#F8F8F8" : "#3F51B5", 219 | segmentActiveBackgroundColor: platform === "ios" ? "#007aff" : "#fff", 220 | segmentTextColor: platform === "ios" ? "#007aff" : "#fff", 221 | segmentActiveTextColor: platform === "ios" ? "#fff" : "#3F51B5", 222 | segmentBorderColor: platform === "ios" ? "#007aff" : "#fff", 223 | segmentBorderColorMain: platform === "ios" ? "#a7a6ab" : "#3F51B5", 224 | 225 | // Spinner 226 | defaultSpinnerColor: "#45D56E", 227 | inverseSpinnerColor: "#1A191B", 228 | 229 | // Tab 230 | tabDefaultBg: platform === "ios" ? "#F8F8F8" : "#3F51B5", 231 | topTabBarTextColor: platform === "ios" ? "#6b6b6b" : "#b3c7f9", 232 | topTabBarActiveTextColor: platform === "ios" ? "#007aff" : "#fff", 233 | topTabBarBorderColor: platform === "ios" ? "#a7a6ab" : "#fff", 234 | topTabBarActiveBorderColor: platform === "ios" ? "#007aff" : "#fff", 235 | 236 | // Tabs 237 | tabBgColor: "#F8F8F8", 238 | tabFontSize: 15, 239 | 240 | // Text 241 | textColor: "#000", 242 | inverseTextColor: "#fff", 243 | noteFontSize: 14, 244 | get defaultTextColor() { 245 | return this.textColor; 246 | }, 247 | 248 | // Title 249 | titleFontfamily: platform === "ios" ? "System" : "Roboto_medium", 250 | titleFontSize: platform === "ios" ? 17 : 19, 251 | subTitleFontSize: platform === "ios" ? 11 : 14, 252 | subtitleColor: platform === "ios" ? "#000" : "#fff", 253 | titleFontColor: platform === "ios" ? "#000" : "#fff", 254 | 255 | // Other 256 | borderRadiusBase: platform === "ios" ? 5 : 2, 257 | borderWidth: 1 / PixelRatio.getPixelSizeForLayoutSize(1), 258 | contentPadding: 10, 259 | dropdownLinkColor: "#414142", 260 | inputLineHeight: 24, 261 | deviceWidth, 262 | deviceHeight, 263 | isIphoneX, 264 | inputGroupRoundedBorderRadius: 30, 265 | 266 | //iPhoneX SafeArea 267 | Inset: { 268 | portrait: { 269 | topInset: 24, 270 | leftInset: 0, 271 | rightInset: 0, 272 | bottomInset: 34 273 | }, 274 | landscape: { 275 | topInset: 0, 276 | leftInset: 44, 277 | rightInset: 44, 278 | bottomInset: 21 279 | } 280 | } 281 | }; 282 | -------------------------------------------------------------------------------- /native-base-theme/variables/platform.js: -------------------------------------------------------------------------------- 1 | import color from "color"; 2 | 3 | import { Platform, Dimensions, PixelRatio } from "react-native"; 4 | 5 | const deviceHeight = Dimensions.get("window").height; 6 | const deviceWidth = Dimensions.get("window").width; 7 | const platform = Platform.OS; 8 | const platformStyle = undefined; 9 | const isIphoneX = 10 | platform === "ios" && (deviceHeight === 812 || deviceWidth === 812); 11 | 12 | export default { 13 | platformStyle, 14 | platform, 15 | 16 | //Accordion 17 | headerStyle: "#edebed", 18 | iconStyle: "#bcc6d9", 19 | contentStyle: "#f5f4f5", 20 | expandedIconStyle: "#bcc6d9", 21 | accordionBorderColor: "#d3d3d3", 22 | 23 | // Android 24 | androidRipple: true, 25 | androidRippleColor: "rgba(256, 256, 256, 0.3)", 26 | androidRippleColorDark: "rgba(0, 0, 0, 0.15)", 27 | btnUppercaseAndroidText: true, 28 | 29 | // Badge 30 | badgeBg: "#ED1727", 31 | badgeColor: "#bcc6d9", 32 | badgePadding: platform === "ios" ? 3 : 0, 33 | 34 | // Button 35 | btnFontFamily: platform === "ios" ? "System" : "Roboto_medium", 36 | btnDisabledBg: "#b5b5b5", 37 | buttonPadding: 6, 38 | get btnPrimaryBg() { 39 | return this.brandPrimary; 40 | }, 41 | get btnPrimaryColor() { 42 | return this.inverseTextColor; 43 | }, 44 | get btnInfoBg() { 45 | return this.brandInfo; 46 | }, 47 | get btnInfoColor() { 48 | return this.inverseTextColor; 49 | }, 50 | get btnSuccessBg() { 51 | return this.brandSuccess; 52 | }, 53 | get btnSuccessColor() { 54 | return this.inverseTextColor; 55 | }, 56 | get btnDangerBg() { 57 | return this.brandDanger; 58 | }, 59 | get btnDangerColor() { 60 | return this.inverseTextColor; 61 | }, 62 | get btnWarningBg() { 63 | return this.brandWarning; 64 | }, 65 | get btnWarningColor() { 66 | return this.inverseTextColor; 67 | }, 68 | get btnTextSize() { 69 | return platform === "ios" ? this.fontSizeBase * 1.1 : this.fontSizeBase - 1; 70 | }, 71 | get btnTextSizeLarge() { 72 | return this.fontSizeBase * 1.5; 73 | }, 74 | get btnTextSizeSmall() { 75 | return this.fontSizeBase * 0.8; 76 | }, 77 | get borderRadiusLarge() { 78 | return this.fontSizeBase * 3.8; 79 | }, 80 | get iconSizeLarge() { 81 | return this.iconFontSize * 1.5; 82 | }, 83 | get iconSizeSmall() { 84 | return this.iconFontSize * 0.6; 85 | }, 86 | 87 | // Card 88 | cardDefaultBg: "#bcc6d9", 89 | cardBorderColor: "#ccc", 90 | cardBorderRadius: 2, 91 | cardItemPadding: platform === "ios" ? 10 : 12, 92 | 93 | // CheckBox 94 | CheckboxRadius: platform === "ios" ? 13 : 0, 95 | CheckboxBorderWidth: platform === "ios" ? 1 : 2, 96 | CheckboxPaddingLeft: platform === "ios" ? 4 : 2, 97 | CheckboxPaddingBottom: platform === "ios" ? 0 : 5, 98 | CheckboxIconSize: platform === "ios" ? 21 : 16, 99 | CheckboxIconMarginTop: platform === "ios" ? undefined : 1, 100 | CheckboxFontSize: platform === "ios" ? 23 / 0.9 : 17, 101 | checkboxBgColor: "#039BE5", 102 | checkboxSize: 20, 103 | checkboxTickColor: "#bcc6d9", 104 | 105 | // Color 106 | brandPrimary: platform === "ios" ? "#007aff" : "#131c2a", 107 | brandInfo: "#62B1F6", 108 | brandSuccess: "#5cb85c", 109 | brandDanger: "#d9534f", 110 | brandWarning: "#f0ad4e", 111 | brandDark: "#bcc6d9", 112 | brandLight: "#bcc6d9", 113 | 114 | //Container 115 | containerBgColor: "#bcc6d9", 116 | 117 | //Date Picker 118 | datePickerTextColor: "#bcc6d9", 119 | datePickerBg: "transparent", 120 | 121 | // Font 122 | DefaultFontSize: 16, 123 | fontFamily: platform === "ios" ? "System" : "Roboto", 124 | fontSizeBase: 15, 125 | get fontSizeH1() { 126 | return this.fontSizeBase * 1.8; 127 | }, 128 | get fontSizeH2() { 129 | return this.fontSizeBase * 1.6; 130 | }, 131 | get fontSizeH3() { 132 | return this.fontSizeBase * 1.4; 133 | }, 134 | 135 | // Footer 136 | footerHeight: 55, 137 | footerDefaultBg: platform === "ios" ? "#131c2a" : "#131c2a", 138 | footerPaddingBottom: 0, 139 | 140 | // FooterTab 141 | tabBarTextColor: platform === "ios" ? "#6b6b6b" : "#b3c7f9", 142 | tabBarTextSize: platform === "ios" ? 14 : 11, 143 | activeTab: platform === "ios" ? "#007aff" : "#bcc6d9", 144 | sTabBarActiveTextColor: "#007aff", 145 | tabBarActiveTextColor: platform === "ios" ? "#007aff" : "#bcc6d9", 146 | tabActiveBgColor: platform === "ios" ? "#cde1f9" : "#131c2a", 147 | 148 | // Header 149 | toolbarBtnColor: platform === "ios" ? "#6d788c" : "#6d788c", 150 | toolbarDefaultBg: platform === "ios" ? "#182129" : "#182129", 151 | toolbarHeight: platform === "ios" ? 64 : 56, 152 | toolbarSearchIconSize: platform === "ios" ? 20 : 23, 153 | toolbarInputColor: platform === "ios" ? "#6d788c" : "#bcc6d9", 154 | searchBarHeight: platform === "ios" ? 30 : 40, 155 | searchBarInputHeight: platform === "ios" ? 30 : 50, 156 | toolbarBtnTextColor: platform === "ios" ? "#007aff" : "#bcc6d9", 157 | toolbarDefaultBorder: platform === "ios" ? "#131c2a" : "#131c2a", 158 | iosStatusbar: platform === "ios" ? "dark-content" : "light-content", 159 | get statusBarColor() { 160 | return color(this.toolbarDefaultBg) 161 | .darken(0.2) 162 | .hex(); 163 | }, 164 | get darkenHeader() { 165 | return color(this.tabBgColor) 166 | .darken(0.03) 167 | .hex(); 168 | }, 169 | 170 | // Icon 171 | iconFamily: "Ionicons", 172 | iconFontSize: platform === "ios" ? 30 : 28, 173 | iconHeaderSize: platform === "ios" ? 33 : 24, 174 | 175 | // InputGroup 176 | inputFontSize: 17, 177 | inputBorderColor: "#232f3a", 178 | inputSuccessBorderColor: "#2b8339", 179 | inputErrorBorderColor: "#ed2f2f", 180 | inputHeightBase: 50, 181 | get inputColor() { 182 | return this.textColor; 183 | }, 184 | get inputColorPlaceholder() { 185 | return "#6d788c"; 186 | }, 187 | 188 | // Line Height 189 | btnLineHeight: 19, 190 | lineHeightH1: 32, 191 | lineHeightH2: 27, 192 | lineHeightH3: 22, 193 | lineHeight: platform === "ios" ? 20 : 24, 194 | listItemSelected: platform === "ios" ? "#007aff" : "#131c2a", 195 | 196 | // List 197 | listBg: "transparent", 198 | listBorderColor: "#465168", 199 | listDividerBg: "#465168", 200 | listBtnUnderlayColor: "#DDD", 201 | listItemPadding: platform === "ios" ? 14 : 16, 202 | listNoteColor: "#808080", 203 | listNoteSize: 13, 204 | 205 | // Progress Bar 206 | defaultProgressColor: "#E4202D", 207 | inverseProgressColor: "#1A191B", 208 | 209 | // Radio Button 210 | radioBtnSize: platform === "ios" ? 25 : 23, 211 | radioSelectedColorAndroid: "#131c2a", 212 | radioBtnLineHeight: platform === "ios" ? 29 : 24, 213 | get radioColor() { 214 | return this.brandPrimary; 215 | }, 216 | 217 | // Segment 218 | segmentBackgroundColor: platform === "ios" ? "#131c2a" : "#131c2a", 219 | segmentActiveBackgroundColor: platform === "ios" ? "#007aff" : "#bcc6d9", 220 | segmentTextColor: platform === "ios" ? "#007aff" : "#bcc6d9", 221 | segmentActiveTextColor: platform === "ios" ? "#bcc6d9" : "#131c2a", 222 | segmentBorderColor: platform === "ios" ? "#007aff" : "#bcc6d9", 223 | segmentBorderColorMain: platform === "ios" ? "#a7a6ab" : "#131c2a", 224 | 225 | // Spinner 226 | defaultSpinnerColor: "#45D56E", 227 | inverseSpinnerColor: "#1A191B", 228 | 229 | // Tab 230 | tabDefaultBg: platform === "ios" ? "#131c2a" : "#131c2a", 231 | topTabBarTextColor: platform === "ios" ? "#6b6b6b" : "#b3c7f9", 232 | topTabBarActiveTextColor: platform === "ios" ? "#007aff" : "#bcc6d9", 233 | topTabBarBorderColor: platform === "ios" ? "#a7a6ab" : "#bcc6d9", 234 | topTabBarActiveBorderColor: platform === "ios" ? "#007aff" : "#bcc6d9", 235 | 236 | // Tabs 237 | tabBgColor: "#131c2a", 238 | tabFontSize: 15, 239 | 240 | // Text 241 | textColor: "#bcc6d9", 242 | inverseTextColor: "#bcc6d9", 243 | noteFontSize: 14, 244 | get defaultTextColor() { 245 | return this.textColor; 246 | }, 247 | 248 | // Title 249 | titleFontfamily: platform === "ios" ? "System" : "Roboto_medium", 250 | titleFontSize: platform === "ios" ? 17 : 19, 251 | subTitleFontSize: platform === "ios" ? 11 : 14, 252 | subtitleColor: platform === "ios" ? "#8e8e93" : "#bcc6d9", 253 | titleFontColor: platform === "ios" ? "#bcc6d9" : "#bcc6d9", 254 | 255 | // Other 256 | borderRadiusBase: platform === "ios" ? 5 : 2, 257 | borderWidth: 1 / PixelRatio.getPixelSizeForLayoutSize(1), 258 | contentPadding: 10, 259 | dropdownLinkColor: "#414142", 260 | inputLineHeight: 24, 261 | deviceWidth, 262 | deviceHeight, 263 | isIphoneX, 264 | inputGroupRoundedBorderRadius: 30, 265 | 266 | //iPhoneX SafeArea 267 | Inset: { 268 | portrait: { 269 | topInset: 24, 270 | leftInset: 0, 271 | rightInset: 0, 272 | bottomInset: 34 273 | }, 274 | landscape: { 275 | topInset: 0, 276 | leftInset: 44, 277 | rightInset: 44, 278 | bottomInset: 21 279 | } 280 | } 281 | }; 282 | -------------------------------------------------------------------------------- /native-base-theme/components/Button.js: -------------------------------------------------------------------------------- 1 | import variable from "./../variables/platform"; 2 | 3 | export default (variables = variable) => { 4 | const platformStyle = variables.platformStyle; 5 | const platform = variables.platform; 6 | const darkCommon = { 7 | "NativeBase.Text": { 8 | color: variables.brandDark 9 | }, 10 | "NativeBase.Icon": { 11 | color: variables.brandDark 12 | }, 13 | "NativeBase.IconNB": { 14 | color: variables.brandDark 15 | } 16 | }; 17 | const lightCommon = { 18 | "NativeBase.Text": { 19 | color: variables.brandLight 20 | }, 21 | "NativeBase.Icon": { 22 | color: variables.brandLight 23 | }, 24 | "NativeBase.IconNB": { 25 | color: variables.brandLight 26 | } 27 | }; 28 | const primaryCommon = { 29 | "NativeBase.Text": { 30 | color: variables.btnPrimaryBg 31 | }, 32 | "NativeBase.Icon": { 33 | color: variables.btnPrimaryBg 34 | }, 35 | "NativeBase.IconNB": { 36 | color: variables.btnPrimaryBg 37 | } 38 | }; 39 | const successCommon = { 40 | "NativeBase.Text": { 41 | color: variables.btnSuccessBg 42 | }, 43 | "NativeBase.Icon": { 44 | color: variables.btnSuccessBg 45 | }, 46 | "NativeBase.IconNB": { 47 | color: variables.btnSuccessBg 48 | } 49 | }; 50 | const infoCommon = { 51 | "NativeBase.Text": { 52 | color: variables.btnInfoBg 53 | }, 54 | "NativeBase.Icon": { 55 | color: variables.btnInfoBg 56 | }, 57 | "NativeBase.IconNB": { 58 | color: variables.btnInfoBg 59 | } 60 | }; 61 | const warningCommon = { 62 | "NativeBase.Text": { 63 | color: variables.btnWarningBg 64 | }, 65 | "NativeBase.Icon": { 66 | color: variables.btnWarningBg 67 | }, 68 | "NativeBase.IconNB": { 69 | color: variables.btnWarningBg 70 | } 71 | }; 72 | const dangerCommon = { 73 | "NativeBase.Text": { 74 | color: variables.btnDangerBg 75 | }, 76 | "NativeBase.Icon": { 77 | color: variables.btnDangerBg 78 | }, 79 | "NativeBase.IconNB": { 80 | color: variables.btnDangerBg 81 | } 82 | }; 83 | const buttonTheme = { 84 | ".disabled": { 85 | ".transparent": { 86 | backgroundColor: null, 87 | "NativeBase.Text": { 88 | color: variables.btnDisabledBg 89 | }, 90 | "NativeBase.Icon": { 91 | color: variables.btnDisabledBg 92 | }, 93 | "NativeBase.IconNB": { 94 | color: variables.btnDisabledBg 95 | } 96 | }, 97 | "NativeBase.Icon": { 98 | color: variables.brandLight 99 | }, 100 | "NativeBase.IconNB": { 101 | color: variables.brandLight 102 | }, 103 | backgroundColor: variables.btnDisabledBg 104 | }, 105 | ".bordered": { 106 | ".dark": { 107 | ...darkCommon, 108 | backgroundColor: "transparent", 109 | borderColor: variables.brandDark, 110 | borderWidth: variables.borderWidth * 2 111 | }, 112 | ".light": { 113 | ...lightCommon, 114 | backgroundColor: "transparent", 115 | borderColor: variables.brandLight, 116 | borderWidth: variables.borderWidth * 2 117 | }, 118 | ".primary": { 119 | ...primaryCommon, 120 | backgroundColor: "transparent", 121 | borderColor: variables.btnPrimaryBg, 122 | borderWidth: variables.borderWidth * 2 123 | }, 124 | ".success": { 125 | ...successCommon, 126 | backgroundColor: "transparent", 127 | borderColor: variables.btnSuccessBg, 128 | borderWidth: variables.borderWidth * 2 129 | }, 130 | ".info": { 131 | ...infoCommon, 132 | backgroundColor: "transparent", 133 | borderColor: variables.btnInfoBg, 134 | borderWidth: variables.borderWidth * 2 135 | }, 136 | ".warning": { 137 | ...warningCommon, 138 | backgroundColor: "transparent", 139 | borderColor: variables.btnWarningBg, 140 | borderWidth: variables.borderWidth * 2 141 | }, 142 | ".danger": { 143 | ...dangerCommon, 144 | backgroundColor: "transparent", 145 | borderColor: variables.btnDangerBg, 146 | borderWidth: variables.borderWidth * 2 147 | }, 148 | ".disabled": { 149 | backgroundColor: null, 150 | borderColor: variables.btnDisabledBg, 151 | borderWidth: variables.borderWidth * 2, 152 | "NativeBase.Text": { 153 | color: variables.btnDisabledBg 154 | } 155 | }, 156 | ...primaryCommon, 157 | borderWidth: variables.borderWidth * 2, 158 | elevation: null, 159 | shadowColor: null, 160 | shadowOffset: null, 161 | shadowOpacity: null, 162 | shadowRadius: null, 163 | backgroundColor: "transparent" 164 | }, 165 | 166 | ".dark": { 167 | ".bordered": { 168 | ...darkCommon 169 | }, 170 | backgroundColor: variables.brandDark 171 | }, 172 | ".light": { 173 | ".transparent": { 174 | ...lightCommon, 175 | backgroundColor: null 176 | }, 177 | ".bordered": { 178 | ...lightCommon 179 | }, 180 | ...darkCommon, 181 | backgroundColor: variables.brandLight 182 | }, 183 | 184 | ".primary": { 185 | ".bordered": { 186 | ...primaryCommon 187 | }, 188 | backgroundColor: variables.btnPrimaryBg 189 | }, 190 | 191 | ".success": { 192 | ".bordered": { 193 | ...successCommon 194 | }, 195 | backgroundColor: variables.btnSuccessBg 196 | }, 197 | 198 | ".info": { 199 | ".bordered": { 200 | ...infoCommon 201 | }, 202 | backgroundColor: variables.btnInfoBg 203 | }, 204 | 205 | ".warning": { 206 | ".bordered": { 207 | ...warningCommon 208 | }, 209 | backgroundColor: variables.btnWarningBg 210 | }, 211 | 212 | ".danger": { 213 | ".bordered": { 214 | ...dangerCommon 215 | }, 216 | backgroundColor: variables.btnDangerBg 217 | }, 218 | 219 | ".block": { 220 | justifyContent: "center", 221 | alignSelf: "stretch" 222 | }, 223 | 224 | ".full": { 225 | justifyContent: "center", 226 | alignSelf: "stretch", 227 | borderRadius: 0 228 | }, 229 | 230 | ".rounded": { 231 | // paddingHorizontal: variables.buttonPadding + 20, 232 | borderRadius: variables.borderRadiusLarge 233 | }, 234 | 235 | ".transparent": { 236 | backgroundColor: "transparent", 237 | elevation: 0, 238 | shadowColor: null, 239 | shadowOffset: null, 240 | shadowRadius: null, 241 | shadowOpacity: null, 242 | ...primaryCommon, 243 | ".dark": { 244 | ...darkCommon, 245 | backgroundColor: null 246 | }, 247 | ".danger": { 248 | ...dangerCommon, 249 | backgroundColor: null 250 | }, 251 | ".warning": { 252 | ...warningCommon, 253 | backgroundColor: null 254 | }, 255 | ".info": { 256 | ...infoCommon, 257 | backgroundColor: null 258 | }, 259 | ".primary": { 260 | ...primaryCommon, 261 | backgroundColor: null 262 | }, 263 | ".success": { 264 | ...successCommon, 265 | backgroundColor: null 266 | }, 267 | ".light": { 268 | ...lightCommon, 269 | backgroundColor: null 270 | }, 271 | ".disabled": { 272 | backgroundColor: "transparent", 273 | borderColor: variables.btnDisabledBg, 274 | borderWidth: variables.borderWidth * 2, 275 | "NativeBase.Text": { 276 | color: variables.btnDisabledBg 277 | }, 278 | "NativeBase.Icon": { 279 | color: variables.btnDisabledBg 280 | }, 281 | "NativeBase.IconNB": { 282 | color: variables.btnDisabledBg 283 | } 284 | } 285 | }, 286 | 287 | ".small": { 288 | height: 30, 289 | "NativeBase.Text": { 290 | fontSize: 14 291 | }, 292 | "NativeBase.Icon": { 293 | fontSize: 20, 294 | paddingTop: 0 295 | }, 296 | "NativeBase.IconNB": { 297 | fontSize: 20, 298 | paddingTop: 0 299 | } 300 | }, 301 | 302 | ".large": { 303 | height: 60, 304 | "NativeBase.Text": { 305 | fontSize: 22, 306 | } 307 | }, 308 | 309 | ".capitalize": {}, 310 | 311 | ".vertical": { 312 | flexDirection: "column", 313 | height: null 314 | }, 315 | 316 | "NativeBase.Text": { 317 | fontFamily: variables.btnFontFamily, 318 | marginLeft: 0, 319 | marginRight: 0, 320 | color: variables.inverseTextColor, 321 | fontSize: variables.btnTextSize, 322 | paddingHorizontal: 16, 323 | backgroundColor: "transparent" 324 | // childPosition: 1 325 | }, 326 | 327 | "NativeBase.Icon": { 328 | color: variables.inverseTextColor, 329 | fontSize: 24, 330 | marginHorizontal: 16, 331 | paddingTop: platform === "ios" ? 2 : undefined 332 | }, 333 | "NativeBase.IconNB": { 334 | color: variables.inverseTextColor, 335 | fontSize: 24, 336 | marginHorizontal: 16, 337 | paddingTop: platform === "ios" ? 2 : undefined 338 | }, 339 | 340 | ".iconLeft": { 341 | "NativeBase.Text": { 342 | marginLeft: 0 343 | }, 344 | "NativeBase.IconNB": { 345 | marginRight: 0, 346 | marginLeft: 16 347 | }, 348 | "NativeBase.Icon": { 349 | marginRight: 0, 350 | marginLeft: 16 351 | } 352 | }, 353 | ".iconRight": { 354 | "NativeBase.Text": { 355 | marginRight: 0 356 | }, 357 | "NativeBase.IconNB": { 358 | marginLeft: 0, 359 | marginRight: 16 360 | }, 361 | "NativeBase.Icon": { 362 | marginLeft: 0, 363 | marginRight: 16 364 | } 365 | }, 366 | ".picker": { 367 | "NativeBase.Text": { 368 | ".note": { 369 | fontSize: 16, 370 | lineHeight: null 371 | } 372 | } 373 | }, 374 | 375 | paddingVertical: variables.buttonPadding, 376 | // paddingHorizontal: variables.buttonPadding + 10, 377 | backgroundColor: variables.btnPrimaryBg, 378 | borderRadius: variables.borderRadiusBase, 379 | borderColor: variables.btnPrimaryBg, 380 | borderWidth: null, 381 | height: 45, 382 | alignSelf: "flex-start", 383 | flexDirection: "row", 384 | elevation: 2, 385 | shadowColor: platformStyle === "material" ? variables.brandDark : undefined, 386 | shadowOffset: 387 | platformStyle === "material" ? { width: 0, height: 2 } : undefined, 388 | shadowOpacity: platformStyle === "material" ? 0.2 : undefined, 389 | shadowRadius: platformStyle === "material" ? 1.2 : undefined, 390 | alignItems: "center", 391 | justifyContent: "space-between" 392 | }; 393 | return buttonTheme; 394 | }; 395 | -------------------------------------------------------------------------------- /native-base-theme/components/Header.js: -------------------------------------------------------------------------------- 1 | import { PixelRatio, StatusBar } from "react-native"; 2 | 3 | import variable from "./../variables/platform"; 4 | 5 | export default (variables = variable) => { 6 | const platformStyle = variables.platformStyle; 7 | const platform = variables.platform; 8 | 9 | const headerTheme = { 10 | ".span": { 11 | height: 128, 12 | "NativeBase.Left": { 13 | alignSelf: "flex-start" 14 | }, 15 | "NativeBase.Body": { 16 | alignSelf: "flex-end", 17 | alignItems: "flex-start", 18 | justifyContent: "center", 19 | paddingBottom: 26 20 | }, 21 | "NativeBase.Right": { 22 | alignSelf: "flex-start" 23 | } 24 | }, 25 | ".hasSubtitle": { 26 | "NativeBase.Body": { 27 | "NativeBase.Title": { 28 | fontSize: variables.titleFontSize - 2, 29 | fontFamily: variables.titleFontfamily, 30 | textAlign: "center", 31 | fontWeight: "500", 32 | paddingBottom: 3 33 | }, 34 | "NativeBase.Subtitle": { 35 | fontSize: variables.subTitleFontSize, 36 | fontFamily: variables.titleFontfamily, 37 | color: variables.subtitleColor, 38 | textAlign: "center" 39 | } 40 | } 41 | }, 42 | ".transparent": { 43 | backgroundColor: "transparent", 44 | borderBottomColor: "transparent", 45 | elevation: 0, 46 | shadowColor: null, 47 | shadowOffset: null, 48 | shadowRadius: null, 49 | shadowOpacity: null, 50 | paddingTop: platform === "android" ? StatusBar.currentHeight : undefined, 51 | height: platform === "android" ? variables.toolbarHeight + StatusBar.currentHeight : variables.toolbarHeight 52 | }, 53 | ".noShadow": { 54 | elevation: 0, 55 | shadowColor: null, 56 | shadowOffset: null, 57 | shadowRadius: null, 58 | shadowOpacity: null 59 | }, 60 | ".hasTabs": { 61 | elevation: 0, 62 | shadowColor: null, 63 | shadowOffset: null, 64 | shadowRadius: null, 65 | shadowOpacity: null, 66 | borderBottomWidth: null 67 | }, 68 | ".hasSegment": { 69 | elevation: 0, 70 | shadowColor: null, 71 | shadowOffset: null, 72 | shadowRadius: null, 73 | shadowOpacity: null, 74 | borderBottomWidth: null, 75 | "NativeBase.Left": { 76 | flex: 0.3 77 | }, 78 | "NativeBase.Right": { 79 | flex: 0.3 80 | }, 81 | "NativeBase.Body": { 82 | flex: 1, 83 | "NativeBase.Segment": { 84 | marginRight: 0, 85 | alignSelf: "center", 86 | "NativeBase.Button": { 87 | paddingLeft: 0, 88 | paddingRight: 0 89 | } 90 | } 91 | } 92 | }, 93 | ".noLeft": { 94 | "NativeBase.Left": { 95 | width: platform === "ios" ? undefined : 0, 96 | flex: platform === "ios" ? 1 : 0 97 | }, 98 | "NativeBase.Body": { 99 | "NativeBase.Title": { 100 | paddingLeft: platform === "ios" ? undefined : 10 101 | }, 102 | "NativeBase.Subtitle": { 103 | paddingLeft: platform === "ios" ? undefined : 10 104 | } 105 | } 106 | }, 107 | "NativeBase.Button": { 108 | justifyContent: "center", 109 | alignSelf: "center", 110 | alignItems: "center", 111 | ".transparent": { 112 | "NativeBase.Text": { 113 | color: variables.toolbarBtnTextColor, 114 | fontWeight: "600" 115 | }, 116 | "NativeBase.Icon": { 117 | color: variables.toolbarBtnColor 118 | }, 119 | "NativeBase.IconNB": { 120 | color: variables.toolbarBtnColor 121 | }, 122 | paddingHorizontal: variables.buttonPadding 123 | }, 124 | paddingHorizontal: 15 125 | }, 126 | ".searchBar": { 127 | "NativeBase.Item": { 128 | "NativeBase.Icon": { 129 | backgroundColor: "transparent", 130 | color: variables.dropdownLinkColor, 131 | fontSize: variables.toolbarSearchIconSize, 132 | alignItems: "center", 133 | marginTop: 2, 134 | paddingRight: 10, 135 | paddingLeft: 10 136 | }, 137 | "NativeBase.IconNB": { 138 | backgroundColor: "transparent", 139 | color: null, 140 | alignSelf: "center" 141 | }, 142 | "NativeBase.Input": { 143 | alignSelf: "center", 144 | lineHeight: null, 145 | height: variables.searchBarInputHeight 146 | }, 147 | alignSelf: "center", 148 | alignItems: "center", 149 | justifyContent: "flex-start", 150 | flex: 1, 151 | height: variables.searchBarHeight, 152 | borderColor: "transparent", 153 | backgroundColor: variables.toolbarInputColor 154 | }, 155 | "NativeBase.Button": { 156 | ".transparent": { 157 | "NativeBase.Text": { 158 | fontWeight: "500" 159 | }, 160 | paddingHorizontal: null, 161 | paddingLeft: platform === "ios" ? 10 : null 162 | }, 163 | paddingHorizontal: platform === "ios" ? undefined : null, 164 | width: platform === "ios" ? undefined : 0, 165 | height: platform === "ios" ? undefined : 0 166 | } 167 | }, 168 | ".rounded": { 169 | "NativeBase.Item": { 170 | borderRadius: 171 | platform === "ios" && platformStyle !== "material" ? 25 : 3 172 | } 173 | }, 174 | "NativeBase.Left": { 175 | "NativeBase.Button": { 176 | ".hasText": { 177 | marginLeft: -10, 178 | height: 30, 179 | "NativeBase.Icon": { 180 | color: variables.toolbarBtnColor, 181 | fontSize: variables.iconHeaderSize, 182 | marginTop: 2, 183 | marginRight: 5, 184 | marginLeft: 2 185 | }, 186 | "NativeBase.Text": { 187 | color: variables.toolbarBtnTextColor, 188 | fontSize: platform === "ios" ? 17 : 0, 189 | marginLeft: 7, 190 | lineHeight: 19.5 191 | }, 192 | "NativeBase.IconNB": { 193 | color: variables.toolbarBtnColor, 194 | fontSize: variables.iconHeaderSize, 195 | marginTop: 2, 196 | marginRight: 5, 197 | marginLeft: 2 198 | } 199 | }, 200 | ".transparent": { 201 | marginLeft: 202 | platform === "ios" && platformStyle !== "material" ? -3 : 0, 203 | "NativeBase.Icon": { 204 | color: variables.toolbarBtnColor, 205 | fontSize: 206 | platform === "ios" && variables.platformStyle !== "material" 207 | ? variables.iconHeaderSize + 1 208 | : variables.iconHeaderSize, 209 | marginTop: 0, 210 | marginRight: 2, 211 | marginLeft: 1, 212 | paddingTop: 1 213 | }, 214 | "NativeBase.IconNB": { 215 | color: variables.toolbarBtnColor, 216 | fontSize: 217 | platform === "ios" && variables.platformStyle !== "material" 218 | ? variables.iconHeaderSize + 1 219 | : variables.iconHeaderSize - 2, 220 | marginTop: 0, 221 | marginRight: 2, 222 | marginLeft: 1, 223 | paddingTop: 1 224 | }, 225 | "NativeBase.Text": { 226 | color: variables.toolbarBtnTextColor, 227 | fontSize: platform === "ios" ? 17 : 0, 228 | top: platform === "ios" ? 1 : -1.5, 229 | paddingLeft: 230 | platform === "ios" && platformStyle !== "material" ? 2 : 5, 231 | paddingRight: 232 | platform === "ios" && platformStyle !== "material" 233 | ? undefined 234 | : 10 235 | }, 236 | backgroundColor: "transparent", 237 | borderColor: null, 238 | elevation: 0, 239 | shadowColor: null, 240 | shadowOffset: null, 241 | shadowRadius: null, 242 | shadowOpacity: null 243 | }, 244 | "NativeBase.Icon": { 245 | color: variables.toolbarBtnColor 246 | }, 247 | "NativeBase.IconNB": { 248 | color: variables.toolbarBtnColor 249 | }, 250 | alignSelf: null, 251 | paddingRight: variables.buttonPadding, 252 | paddingLeft: platform === "ios" && platformStyle !== "material" ? 4 : 8 253 | }, 254 | flex: platform === "ios" && platformStyle !== "material" ? 1 : 0.4, 255 | alignSelf: "center", 256 | alignItems: "flex-start" 257 | }, 258 | "NativeBase.Body": { 259 | flex: 1, 260 | alignItems: 261 | platform === "ios" && platformStyle !== "material" 262 | ? "center" 263 | : "flex-start", 264 | alignSelf: "center", 265 | "NativeBase.Segment": { 266 | borderWidth: 0, 267 | alignSelf: "flex-end", 268 | marginRight: platform === "ios" ? -40 : -55 269 | }, 270 | "NativeBase.Button": { 271 | alignSelf: "center", 272 | ".transparent": { 273 | backgroundColor: "transparent" 274 | }, 275 | "NativeBase.Icon": { 276 | color: variables.toolbarBtnColor 277 | }, 278 | "NativeBase.IconNB": { 279 | color: variables.toolbarBtnColor 280 | }, 281 | "NativeBase.Text": { 282 | color: variables.inverseTextColor, 283 | backgroundColor: "transparent" 284 | } 285 | } 286 | }, 287 | "NativeBase.Right": { 288 | "NativeBase.Button": { 289 | ".hasText": { 290 | height: 30, 291 | "NativeBase.Icon": { 292 | color: variables.toolbarBtnColor, 293 | fontSize: variables.iconHeaderSize - 2, 294 | marginTop: 2, 295 | marginRight: 2, 296 | marginLeft: 5 297 | }, 298 | "NativeBase.Text": { 299 | color: variables.toolbarBtnTextColor, 300 | fontSize: platform === "ios" ? 17 : 14, 301 | lineHeight: 19.5 302 | }, 303 | "NativeBase.IconNB": { 304 | color: variables.toolbarBtnColor, 305 | fontSize: variables.iconHeaderSize - 2, 306 | marginTop: 2, 307 | marginRight: 2, 308 | marginLeft: 5 309 | } 310 | }, 311 | ".transparent": { 312 | marginRight: platform === "ios" ? -9 : -5, 313 | paddingLeft: 15, 314 | paddingRight: 12, 315 | paddingHorizontal: 15, 316 | borderRadius: 50, 317 | "NativeBase.Icon": { 318 | color: variables.toolbarBtnColor, 319 | fontSize: variables.iconHeaderSize - 2, 320 | marginTop: 0, 321 | marginLeft: 2, 322 | marginRight: 0 323 | // paddingTop: 0 324 | }, 325 | "NativeBase.IconNB": { 326 | color: variables.toolbarBtnColor, 327 | fontSize: variables.iconHeaderSize - 2, 328 | marginTop: 0, 329 | marginLeft: 2, 330 | marginRight: 0 331 | // paddingTop: 0 332 | }, 333 | "NativeBase.Text": { 334 | color: variables.toolbarBtnTextColor, 335 | fontSize: platform === "ios" ? 17 : 14, 336 | top: platform === "ios" ? 1 : -1.5, 337 | paddingRight: 338 | platform === "ios" && variables.platformStyle !== "material" 339 | ? 0 340 | : undefined 341 | }, 342 | backgroundColor: "transparent", 343 | borderColor: null, 344 | elevation: 0, 345 | shadowColor: null, 346 | shadowOffset: null, 347 | shadowRadius: null, 348 | shadowOpacity: null 349 | }, 350 | "NativeBase.Icon": { 351 | color: variables.toolbarBtnColor 352 | }, 353 | "NativeBase.IconNB": { 354 | color: variables.toolbarBtnColor 355 | }, 356 | alignSelf: null, 357 | paddingHorizontal: variables.buttonPadding 358 | }, 359 | flex: 1, 360 | alignSelf: "center", 361 | alignItems: "flex-end", 362 | flexDirection: "row", 363 | justifyContent: "flex-end" 364 | }, 365 | backgroundColor: variables.toolbarDefaultBg, 366 | flexDirection: "row", 367 | // paddingHorizontal: 10, 368 | paddingLeft: 369 | platform === "ios" && variables.platformStyle !== "material" ? 6 : 10, 370 | paddingRight: 10, 371 | justifyContent: "center", 372 | paddingTop: platform === "ios" ? 18 : 0, 373 | borderBottomWidth: 374 | platform === "ios" ? 1 / PixelRatio.getPixelSizeForLayoutSize(1) : 0, 375 | borderBottomColor: variables.toolbarDefaultBorder, 376 | height: 377 | variables.platform === "ios" && variables.platformStyle === "material" 378 | ? variables.toolbarHeight + StatusBar.height 379 | : variables.toolbarHeight, 380 | elevation: 3, 381 | shadowColor: platformStyle === "material" ? "#000" : undefined, 382 | shadowOffset: 383 | platformStyle === "material" ? { width: 0, height: 2 } : undefined, 384 | shadowOpacity: platformStyle === "material" ? 0.2 : undefined, 385 | shadowRadius: platformStyle === "material" ? 1.2 : undefined, 386 | top: 0, 387 | left: 0, 388 | right: 0 389 | }; 390 | 391 | return headerTheme; 392 | }; 393 | -------------------------------------------------------------------------------- /native-base-theme/components/ListItem.js: -------------------------------------------------------------------------------- 1 | import { Platform, PixelRatio } from "react-native"; 2 | 3 | import pickerTheme from "./Picker"; 4 | import variable from "./../variables/platform"; 5 | 6 | export default (variables = variable) => { 7 | const platform = variables.platform; 8 | const selectedStyle = { 9 | "NativeBase.Text": { 10 | color: variables.listItemSelected 11 | }, 12 | "NativeBase.Icon": { 13 | color: variables.listItemSelected 14 | } 15 | }; 16 | 17 | const listItemTheme = { 18 | "NativeBase.InputGroup": { 19 | "NativeBase.Icon": { 20 | paddingRight: 5 21 | }, 22 | "NativeBase.IconNB": { 23 | paddingRight: 5 24 | }, 25 | "NativeBase.Input": { 26 | paddingHorizontal: 5 27 | }, 28 | flex: 1, 29 | borderWidth: null, 30 | margin: -10, 31 | borderBottomColor: "transparent" 32 | }, 33 | ".searchBar": { 34 | "NativeBase.Item": { 35 | "NativeBase.Icon": { 36 | backgroundColor: "transparent", 37 | color: variables.dropdownLinkColor, 38 | fontSize: 39 | platform === "ios" 40 | ? variables.iconFontSize - 10 41 | : variables.iconFontSize - 5, 42 | alignItems: "center", 43 | marginTop: 2, 44 | paddingRight: 8 45 | }, 46 | "NativeBase.IconNB": { 47 | backgroundColor: "transparent", 48 | color: null, 49 | alignSelf: "center" 50 | }, 51 | "NativeBase.Input": { 52 | alignSelf: "center" 53 | }, 54 | alignSelf: "center", 55 | alignItems: "center", 56 | justifyContent: "flex-start", 57 | flex: 1, 58 | height: platform === "ios" ? 30 : 40, 59 | borderColor: "transparent", 60 | backgroundColor: "#fff", 61 | borderRadius: 5 62 | }, 63 | "NativeBase.Button": { 64 | ".transparent": { 65 | "NativeBase.Text": { 66 | fontWeight: "500" 67 | }, 68 | paddingHorizontal: null, 69 | paddingLeft: platform === "ios" ? 10 : null 70 | }, 71 | paddingHorizontal: platform === "ios" ? undefined : null, 72 | width: platform === "ios" ? undefined : 0, 73 | height: platform === "ios" ? undefined : 0 74 | }, 75 | backgroundColor: variables.toolbarInputColor, 76 | padding: 10, 77 | marginLeft: null 78 | }, 79 | "NativeBase.CheckBox": { 80 | marginLeft: -10, 81 | marginRight: 10 82 | }, 83 | ".first": { 84 | ".itemHeader": { 85 | paddingTop: variables.listItemPadding + 3 86 | } 87 | }, 88 | ".itemHeader": { 89 | ".first": { 90 | paddingTop: variables.listItemPadding + 3 91 | }, 92 | borderBottomWidth: platform === "ios" ? variables.borderWidth : null, 93 | marginLeft: null, 94 | padding: variables.listItemPadding, 95 | paddingLeft: variables.listItemPadding + 5, 96 | paddingTop: 97 | platform === "ios" ? variables.listItemPadding + 25 : undefined, 98 | paddingBottom: 99 | platform === "android" ? variables.listItemPadding + 20 : undefined, 100 | flexDirection: "row", 101 | borderColor: variables.listBorderColor, 102 | "NativeBase.Text": { 103 | fontSize: 14, 104 | color: platform === "ios" ? undefined : variables.listNoteColor 105 | } 106 | }, 107 | ".itemDivider": { 108 | borderBottomWidth: null, 109 | marginLeft: null, 110 | padding: variables.listItemPadding, 111 | paddingLeft: variables.listItemPadding + 5, 112 | backgroundColor: variables.listDividerBg, 113 | flexDirection: "row", 114 | borderColor: variables.listBorderColor 115 | }, 116 | ".selected": { 117 | "NativeBase.Left": { 118 | ...selectedStyle 119 | }, 120 | "NativeBase.Body": { 121 | ...selectedStyle 122 | }, 123 | "NativeBase.Right": { 124 | ...selectedStyle 125 | }, 126 | ...selectedStyle 127 | }, 128 | "NativeBase.Left": { 129 | "NativeBase.Body": { 130 | "NativeBase.Text": { 131 | ".note": { 132 | color: variables.listNoteColor, 133 | fontWeight: "200" 134 | }, 135 | fontWeight: "600" 136 | }, 137 | marginLeft: 10, 138 | alignItems: null, 139 | alignSelf: null 140 | }, 141 | "NativeBase.Icon": { 142 | width: variables.iconFontSize - 10, 143 | fontSize: variables.iconFontSize - 10 144 | }, 145 | "NativeBase.IconNB": { 146 | width: variables.iconFontSize - 10, 147 | fontSize: variables.iconFontSize - 10 148 | }, 149 | "NativeBase.Text": { 150 | alignSelf: "center" 151 | }, 152 | flexDirection: "row" 153 | }, 154 | "NativeBase.Body": { 155 | "NativeBase.Text": { 156 | marginHorizontal: variables.listItemPadding, 157 | ".note": { 158 | color: variables.listNoteColor, 159 | fontWeight: "200" 160 | } 161 | }, 162 | alignSelf: null, 163 | alignItems: null 164 | }, 165 | "NativeBase.Right": { 166 | "NativeBase.Badge": { 167 | alignSelf: null 168 | }, 169 | "NativeBase.PickerNB": { 170 | "NativeBase.Button": { 171 | marginRight: -15, 172 | "NativeBase.Text": { 173 | color: variables.topTabBarActiveTextColor 174 | } 175 | } 176 | }, 177 | "NativeBase.Button": { 178 | alignSelf: null, 179 | ".transparent": { 180 | "NativeBase.Text": { 181 | color: variables.topTabBarActiveTextColor 182 | } 183 | } 184 | }, 185 | "NativeBase.Icon": { 186 | alignSelf: null, 187 | fontSize: variables.iconFontSize - 8, 188 | color: "#c9c8cd" 189 | }, 190 | "NativeBase.IconNB": { 191 | alignSelf: null, 192 | fontSize: variables.iconFontSize - 8, 193 | color: "#c9c8cd" 194 | }, 195 | "NativeBase.Text": { 196 | ".note": { 197 | color: variables.listNoteColor, 198 | fontWeight: "200" 199 | }, 200 | alignSelf: null 201 | }, 202 | "NativeBase.Thumbnail": { 203 | alignSelf: null 204 | }, 205 | "NativeBase.Image": { 206 | alignSelf: null 207 | }, 208 | "NativeBase.Radio": { 209 | alignSelf: null 210 | }, 211 | "NativeBase.Checkbox": { 212 | alignSelf: null 213 | }, 214 | "NativeBase.Switch": { 215 | alignSelf: null 216 | }, 217 | padding: null, 218 | flex: 0.28 219 | }, 220 | "NativeBase.Text": { 221 | ".note": { 222 | color: variables.listNoteColor, 223 | fontWeight: "200" 224 | }, 225 | alignSelf: "center" 226 | }, 227 | ".last": { 228 | marginLeft: -(variables.listItemPadding + 5), 229 | paddingLeft: (variables.listItemPadding + 5) * 2, 230 | top: 1 231 | }, 232 | ".avatar": { 233 | "NativeBase.Left": { 234 | flex: 0, 235 | alignSelf: 'flex-start', 236 | paddingTop: 14 237 | }, 238 | "NativeBase.Body": { 239 | "NativeBase.Text": { 240 | marginLeft: null 241 | }, 242 | flex: 1, 243 | paddingVertical: variables.listItemPadding, 244 | borderBottomWidth: variables.borderWidth, 245 | borderColor: variables.listBorderColor, 246 | marginLeft: variables.listItemPadding + 5 247 | }, 248 | "NativeBase.Right": { 249 | "NativeBase.Text": { 250 | ".note": { 251 | fontSize: variables.noteFontSize - 2 252 | } 253 | }, 254 | flex: 0, 255 | paddingRight: variables.listItemPadding + 5, 256 | alignSelf: "stretch", 257 | paddingVertical: variables.listItemPadding, 258 | borderBottomWidth: variables.borderWidth, 259 | borderColor: variables.listBorderColor 260 | }, 261 | ".noBorder": { 262 | "NativeBase.Body": { 263 | borderBottomWidth: null 264 | }, 265 | "NativeBase.Right": { 266 | borderBottomWidth: null 267 | } 268 | }, 269 | borderBottomWidth: null, 270 | paddingVertical: null, 271 | paddingRight: null 272 | }, 273 | ".thumbnail": { 274 | "NativeBase.Left": { 275 | flex: 0 276 | }, 277 | "NativeBase.Body": { 278 | "NativeBase.Text": { 279 | marginLeft: null 280 | }, 281 | flex: 1, 282 | paddingVertical: variables.listItemPadding + 5, 283 | borderBottomWidth: variables.borderWidth, 284 | borderColor: variables.listBorderColor, 285 | marginLeft: variables.listItemPadding + 5 286 | }, 287 | "NativeBase.Right": { 288 | "NativeBase.Button": { 289 | ".transparent": { 290 | "NativeBase.Text": { 291 | fontSize: variables.listNoteSize, 292 | color: variables.sTabBarActiveTextColor 293 | } 294 | }, 295 | height: null 296 | }, 297 | flex: 0, 298 | justifyContent: "center", 299 | alignSelf: "stretch", 300 | paddingRight: variables.listItemPadding + 5, 301 | paddingVertical: variables.listItemPadding + 5, 302 | borderBottomWidth: variables.borderWidth, 303 | borderColor: variables.listBorderColor 304 | }, 305 | ".noBorder": { 306 | "NativeBase.Body": { 307 | borderBottomWidth: null 308 | }, 309 | "NativeBase.Right": { 310 | borderBottomWidth: null 311 | } 312 | }, 313 | borderBottomWidth: null, 314 | paddingVertical: null, 315 | paddingRight: null 316 | }, 317 | ".icon": { 318 | ".last": { 319 | "NativeBase.Body": { 320 | borderBottomWidth: null 321 | }, 322 | "NativeBase.Right": { 323 | borderBottomWidth: null 324 | }, 325 | borderBottomWidth: variables.borderWidth, 326 | borderColor: variables.listBorderColor 327 | }, 328 | "NativeBase.Left": { 329 | "NativeBase.Button": { 330 | "NativeBase.IconNB": { 331 | marginHorizontal: null, 332 | fontSize: variables.iconFontSize - 5 333 | }, 334 | "NativeBase.Icon": { 335 | marginHorizontal: null, 336 | fontSize: variables.iconFontSize - 8 337 | }, 338 | alignSelf: "center", 339 | height: 29, 340 | width: 29, 341 | borderRadius: 6, 342 | paddingVertical: null, 343 | paddingHorizontal: null, 344 | alignItems: "center", 345 | justifyContent: "center" 346 | }, 347 | "NativeBase.Icon": { 348 | width: variables.iconFontSize - 5, 349 | fontSize: variables.iconFontSize - 2 350 | }, 351 | "NativeBase.IconNB": { 352 | width: variables.iconFontSize - 5, 353 | fontSize: variables.iconFontSize - 2 354 | }, 355 | paddingRight: variables.listItemPadding + 5, 356 | flex: 0, 357 | height: 44, 358 | justifyContent: "center", 359 | alignItems: "center" 360 | }, 361 | "NativeBase.Body": { 362 | "NativeBase.Text": { 363 | marginLeft: null, 364 | fontSize: 17 365 | }, 366 | flex: 1, 367 | height: 44, 368 | justifyContent: "center", 369 | borderBottomWidth: 1 / PixelRatio.getPixelSizeForLayoutSize(1), 370 | borderColor: variables.listBorderColor 371 | }, 372 | "NativeBase.Right": { 373 | "NativeBase.Text": { 374 | textAlign: "center", 375 | color: "#8F8E95", 376 | fontSize: 17 377 | }, 378 | "NativeBase.IconNB": { 379 | color: "#C8C7CC", 380 | fontSize: variables.iconFontSize - 10, 381 | alignSelf: "center", 382 | paddingLeft: 10, 383 | paddingTop: 3 384 | }, 385 | "NativeBase.Icon": { 386 | color: "#C8C7CC", 387 | fontSize: variables.iconFontSize - 10, 388 | alignSelf: "center", 389 | paddingLeft: 10, 390 | paddingTop: 3 391 | }, 392 | "NativeBase.Switch": { 393 | marginRight: Platform.OS === "ios" ? undefined : -5, 394 | alignSelf: null 395 | }, 396 | "NativeBase.PickerNB": { 397 | ...pickerTheme() 398 | }, 399 | flexDirection: "row", 400 | alignItems: "center", 401 | flex: 0, 402 | alignSelf: "stretch", 403 | height: 44, 404 | justifyContent: "flex-end", 405 | borderBottomWidth: 1 / PixelRatio.getPixelSizeForLayoutSize(1), 406 | borderColor: variables.listBorderColor, 407 | paddingRight: variables.listItemPadding + 5 408 | }, 409 | ".noBorder": { 410 | "NativeBase.Body": { 411 | borderBottomWidth: null 412 | }, 413 | "NativeBase.Right": { 414 | borderBottomWidth: null 415 | } 416 | }, 417 | borderBottomWidth: null, 418 | paddingVertical: null, 419 | paddingRight: null, 420 | height: 44, 421 | justifyContent: "center" 422 | }, 423 | ".noBorder": { 424 | borderBottomWidth: null 425 | }, 426 | ".noIndent": { 427 | marginLeft: null, 428 | padding: variables.listItemPadding, 429 | paddingLeft: variables.listItemPadding + 6, 430 | }, 431 | alignItems: "center", 432 | flexDirection: "row", 433 | paddingRight: variables.listItemPadding + 6, 434 | paddingVertical: variables.listItemPadding + 3, 435 | marginLeft: variables.listItemPadding + 6, 436 | borderBottomWidth: 1 / PixelRatio.getPixelSizeForLayoutSize(1), 437 | backgroundColor: variables.listBg, 438 | borderColor: variables.listBorderColor 439 | }; 440 | 441 | return listItemTheme; 442 | }; 443 | --------------------------------------------------------------------------------